Nimで動的ライブラリに依存しないLinuxコマンドを作成する方法

# 概要

得意のパクリ記事です。
[Rustで動的ライブラリに依存しないLinuxコマンドを作成する方法](https://qiita.com/sile/items/e9d331b3b06565728d1d)を読んで、Nimでも同じ事ができるのか調べてみました。

## MUSLのインストール

[MUSLのホームページ](http://www.musl-libc.org/download.html)から、musl-1.1.20.tar.gz をダウンロードします。
ダウンロードファイルを展開し、ビルドします。

```
wget http://www.musl-libc.org/releases/musl-1.1.20.tar.gz
tar xzvf musl-1.1.20.tar.gz
cd musl-1.1.20

./configure
make install

# obj/musl-gccが本体っぽい
ls -la obj/musl-gcc

# インストール先は、/usr/local/musl
tree -L 1 /usr/local/musl                                                                                      [master]
/usr/local/musl
├── bin
├── include
└── lib
```

## NimでMuslを利用するには

githubにそのものズバリのリポジトリがいくつかありました。

こちらはconfig.nimsに、コンパイルオプション等が入っているサンプル
https://github.com/kaushalmodi/hello_musl

こちらはシェルでビルドするサンプル
https://github.com/yuhangwang/musl-nim

## 試してみる

１つめのサンプルで試してみます。
まずは、先ほどインストールしたmusl-gccへのパスを設定し、サンプルソースをgithubからcloneします。

```
# PATHは絶対パスで指定する必要あり
export PATH=/usr/local/musl/bin:$PATH
git clone https://github.com/kaushalmodi/hello_musl.git
cd hello_musl

```

hello_muslフォルダに、Nimファイルを作成します。

```nim:hello.nim
echo "hello musl"
```

まずは、普通にコンパイルし動的ライブラリを確認してみる

```shell-session
$ nim c -o:hello-nomal hello.nim                                                                                Hint: used config file '/opt/apps/nim/nim-0.19.0/config/nim.cfg' [Conf]
Hint: used config file '/mnt/ramdisk/hello_musl/config.nims' [Conf]
Hint: system [Processing]
Hint: hello [Processing]
CC: hello
Hint:  [Link]
Hint: operation successful (27405 lines compiled; 0.194 sec total; 38.844MiB peakmem; Debug Build) [SuccessX]

# 依存SOファイルを表示する
$ ldd hello-nomal                                                                                          	 
    linux-vdso.so.1 =>  (0x00007ffc98fa6000)
    libm.so.6 => /lib64/libm.so.6 (0x00007f68e04b4000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f68e02af000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f68dfeed000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f68e07db000)
```

５つの動的ライブラリに依存していることがわかります。

次に、MUSLでビルドし、依存ライブラリを確認してみます。
[config.nims](https://github.com/kaushalmodi/hello_musl/blob/master/config.nims)にて、nimコマンドに渡されるコマンドを拡張しています。
このconfig.nimsですが、けっこうすごいことしています。Nimって**こんな拡張ができるものなの**かと感動しました。

```
$ nim musl -o:hello hello.nim                                                                               Hint: used config file '/opt/apps/nim/nim-0.19.0/config/nim.cfg' [Conf]
Hint: used config file '/mnt/ramdisk/hello_musl/config.nims' [Conf]

Running 'nim c -d:musl -d:release --opt:size -o:hello hello.nim' ..
Hint: used config file '/opt/apps/nim/nim-0.19.0/config/nim.cfg' [Conf]
Hint: used config file '/mnt/ramdisk/hello_musl/config.nims' [Conf]
  [-d:musl] Building a static binary using musl ..
debug: ../musl-1.1.20/obj/musl-gcc
Hint: system [Processing]
Hint: hello [Processing]
CC: hello
Hint:  [Link]
Hint: operation successful (27405 lines compiled; 0.193 sec total; 38.809MiB peakmem; Release Build) [SuccessX]

Running 'strip -s' ..

Created binary: hello

# 依存SOファイルを表示する
$ ldd hello       
  動的実行ファイルではありません

```

lddコマンドの結果を見ると、どの動的ライブラリにも依存していないことがわかります。

## 出来上がったバイナリを他のディストリビューションで試してみる

今回は、Window10のbash on windows上に、先のhelloコマンドをコピーして実行してみたところ、問題なく動作しました。
本来はもっと検証したいところですが。

## まとめ

MUSLを利用したNimのビルドを試し、動的ライブラリに依存しないコマンドを作成することができました。
今回は、Linuxでの動作確認となりましたが、Windows10のMINGW環境でMUSLをビルドしてもうまく行かず時間もなかったので、今回はスキップしています。
MacでもMuslのビルドは問題なさそうな気がしますが、時間があるときに試してみる予定です。

なお、hello_muslでは、正規表現およびSSLを使う時の専用のオプションもあります。
詳細は[こちら](https://github.com/kaushalmodi/hello_musl)でご確認ください。