search
LoginSignup
2

More than 3 years have passed since last update.

posted at

statically linkedなGNU nanoをビルドする

バイナリ単体で動作するGNU nanoを作ります。

GNU nano とは

軽量なスクリーンエディタです。
vimやemacsのように高機能ではありませんが、小さな編集のみ行う場合には十分な機能を有しています。
操作にクセが少ないので、初めてスクリーンエディタを使う方でも扱いやすいかと思います。

ref. nano - ArchWiki

静的リンクされたnano

パッケージマネージャなどで手に入るnanoは大抵、依存するライブラリをdynamic linkして動作するものであり、nanoのバイナリファイルだけをどこかに持っていったとしても高い確率で動作しません。
かといって、プロダクション環境のサーバに依存ライブラリと一緒にゴチャッとインストールするのも気が引けるものです。
そこで、すべての依存ライブラリを静的リンクしてしまい、単一ファイルで動作する可搬性の高いnanoバイナリが作りたい!というモチベーションがあります。

ビルド手順

ビルド環境の立ち上げ

Dockerで立ち上げたコンテナ上で作業します。イメージはalpine:edgeです1
Alpine Linuxは軽量なコンテナイメージとして有名ですが、デフォルトで採用されているmusl libcは静的リンクに最適化された軽量なlibcであり、今回の目的にもマッチしています。

docker run -it --name builder alpine:edge

以降はコンテナ内での作業になります。

必要なパッケージのインストール

以下のパッケージが必要ですので、インストールします。

apk add gcc make groff linux-headers musl-dev ncurses-dev ncurses-static zlib-dev zlib-static

ncursesとzlibはそれぞれ、nanoが依存するライブラリであり、静的リンク用のファイルを提供するパッケージが用意されています。
(末尾が-staticのもの。)

libmagic.aのビルド

libmagicは、nanoがファイルの種別判定に用いるライブラリです。
このlibmagicは、file-devパッケージに含まれていますが、静的リンク用のバイナリは提供されていません!

ということで、自前でビルドする必要があります。libmagicのソースコードは、ファイルの種類を判定するコマンドfile(1)のソースコードに含まれているので、これをビルドします。

cd /
wget ftp://ftp.astron.com/pub/file/file-5.37.tar.gz -O - | tar zxvf -
cd file-5.37
./configure CFLAGS="-Ofast" --prefix=/usr --enable-static
make -j8
make install

./configure時に--enable-staticオブションをつけることで、静的リンク用のバイナリlibmagic.aが生成されるようになります。

nanoのビルド

これで材料が揃ったので、nanoをビルドできます。
LDFLAGS-staticを指定して静的リンクします。

cd /
wget https://www.nano-editor.org/dist/v4/nano-4.5.tar.gz -O - | tar zxvf -
cd nano-4.5
./configure CFLAGS="-Ofast" LDFLAGS="-static -no-pie -s" LIBS="-lz" --prefix=/usr
make -j8
make install

確認してみます。

# file /usr/bin/nano
/usr/bin/nano: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, with debug_info, not stripped

# ldd /usr/bin/nano
/lib/ld-musl-x86_64.so.1: /usr/bin/nano: Not a valid dynamic program

# ls -lha /usr/bin/nano
-rwxr-xr-x    1 root     root      793.8K Oct  7 17:05 /usr/bin/nano

できてる!
当たり前ですが、全部入りなので若干バイナリサイズが大きいですね。

後処理

コンテナから抜けて……

exit

ビルドしたnanoをホストマシンに持ってきます。ビルドに使ったコンテは不要なので、削除。

exit
docker cp builder:/usr/bin/nano .
docker rm builder

ホストマシンでもちゃんと動作しています。

$ ./nano --version
 GNU nano, version 4.5
 (C) 1999-2011, 2013-2019 Free Software Foundation, Inc.
 (C) 2014-2019 the contributors to nano
 Email: nano@nano-editor.org    Web: https://nano-editor.org/
 Compiled options: --disable-nls --enable-utf8

完成

今回ビルドしたnanoを以下においておきました。自己責任でご利用ください。
https://www.dropbox.com/s/a0xmtaqy4jvb6nb/nano?dl=0

便利な機能を使おうとすると他に必要なファイルがあったりする(例えば今回無効になっているNative Language SupportやSyntax Highlightingなど)のですが、基本的な機能は一通り利用できるバイナリが生成できました。


  1. edgeバージョンを用いるのは、後ほどインストールするzlib-staticが現行の最新バージョンv3.10では提供されていないからです。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2