BinaryBuilder.jlがすごい〜自動でDockerでクロスコンパイルしてcやFortranのコードをJuliaライブラリ化

Juliaを使っていると、時々Arpack_jllみたいな、jllと名のついたパッケージを見たことはありませんか？
大抵、何らかのパッケージをインストールする時に依存関係としてjllのついたパッケージが入っていると思います。
実は、このjllとついたパッケージ、Julia言語ではない他の言語で書かれたコードがコンパイルされたものなのです。インストールする時にはOSに合わせて自動でバイナリがダウンロードされます。

これを実現するのは、
BinaryBuilder.jl
https://github.com/JuliaPackaging/BinaryBuilder.jl
というパッケージです。

私は
https://www.youtube.com/watch?v=3IyXsBwqll8
これを見て存在を知りました。

どうやら、Dockerを使うことで、Mac、Windows、Linuxの様々なプラットフォームでのクロスコンパイルを行ってコードをコンパイルしているようです。その際、それぞれのOSごとに上手く行かない場合には適宜コンパイル方法を修正したりするようです。

非常に面白そうなライブラリですので、試してみました。

今回入れてみたのは、C-LIMEです。
https://usqcd-software.github.io/c-lime/
格子QCD(格子量子色力学)のためのデータフォーマットです。私は全然詳しくありませんが、規模がちょうど良かったので試してみました。



# 環境
Julia 1.5.2
Mac OS 10.15

# BinaryBuilder.jlのインストール
まず、Dockerが必要ですので、Dockerを入れておきます。Dockerのインストール方法は適当に調べてください。
Macであれば、

```
$ brew install docker
$ brew cask install docker
```
でいけそうです。


その後、Juliaで]を押してパッケージモードにして、

```
add BinaryBuilder
```
とします。しかし、2020年10月17日現在、GitHubの何かが変わったために現状のバージョンでは動かないため、上の代わりに

```
add BinaryBuilder#f126fe7
```
として修正されたバージョンを入れる必要があります。

# 使い方

入れた後は、

```julia
using BinaryBuilder
BinaryBuilder.run_wizard()
```
とwizardを実行します。

```
Make a platform selection
 > All Supported Platforms
   Select by Operating System
   Fully Custom Platform Choice
```
ではAll Supported Platformsを選び、

```
Please enter a URL (git repository or compressed archive) containing the source code to build:
```
ではコンパイルしたいソフトウェアのgithubアドレスかファイルを指定します。ここでは、

```
https://github.com/usqcd-software/c-lime.git
```
としました。
あとは指示に従っていきます。最初の問いはgitのブランチのどれを選ぶかですが、これはmasterとしておきます。
今回のコードは特に追加のソースコードやライブラリは必要ありません。
進んでいくと、
名前をつけるのとか、バージョンをつけるのとかありますので適当に入れていきます。

進んでいくと

```
sandbox:${WORKSPACE}/srcdir
```
みたいなものが出てきます。ここで、コードのコンパイルを行います。
今回の場合なら、

```
cd c-lime/
./autogen.sh 
./configure --prefix=${prefix} --build=${MACHTYPE} --host=${target}
make 
make install
```
でコードをコンパイルできます。そして、Ctrl+Dでlogoutします。
次に

```
Your build script was:

	cd $WORKSPACE/srcdir
	cd c-lime/
	./autogen.sh 
	./configure --prefix=${prefix} --build=${MACHTYPE} --host=${target}
	make
	make install
	
Would you like to edit this script now? [y/N]: n
```
とコンパイル方法がまとめられているので、特に問題がなければnとします。
そのあと、何をコンパイルするの？みたいなものが出てくるので、aを押してdを押します。
あとはenterを推しつつ色々なOSやプラットフォームでのコンパイルを行います。

さて、出来上がったあとは、

```
How should we deploy this build recipe?
 > Prepare a pull request against the community buildtree, Yggdrasil
   Write to a local file
   Print to stdout
```
と聞かれます。
もし最初を選ぶと、GitHubのYggdrasil（ユグドラシル）というところにpull requestをします。
これは、どのようにコンパイルすればいいか、という情報をここに載せることを意味します。

```
Would you like to actually open the pull request or just prepare it?
 > Go ahead, open it
   No, just prepare it and let me look at it first
```
そのあと、自分のgithubのアカウント名でpull requestをすることになります。

もし無事に終了すれば、pull requestが自動で行われます。
そして、問題がなければYggdrasilにマージされます。
マージされると、
https://github.com/JuliaBinaryWrappers/
に登録されます。
ここに登録されれば完了です。
https://github.com/JuliaBinaryWrappers/CLIME_jll.jl
は既に登録されたものですが、

```
Linux aarch64 {libc=glibc} (aarch64-linux-gnu)
Linux aarch64 {libc=musl} (aarch64-linux-musl)
Linux armv7l {call_abi=eabihf, libc=glibc} (armv7l-linux-gnueabihf)
Linux armv7l {call_abi=eabihf, libc=musl} (armv7l-linux-musleabihf)
Linux i686 {libc=glibc} (i686-linux-gnu)
Linux i686 {libc=musl} (i686-linux-musl)
Windows i686 (i686-w64-mingw32)
Linux powerpc64le {libc=glibc} (powerpc64le-linux-gnu)
macOS x86_64 (x86_64-apple-darwin)
Linux x86_64 {libc=glibc} (x86_64-linux-gnu)
Linux x86_64 {libc=musl} (x86_64-linux-musl)
FreeBSD x86_64 (x86_64-unknown-freebsd)
Windows x86_64 (x86_64-w64-mingw32)
```
というプラットフォームであればバイナリを提供できるとあります。

# Juliaのライブラリとしての使い方

以後は

```julia
add CLIME_jll
```
とするとインストールできます。
今回のCLIMEはライブラリではなく実行するタイプですので、
https://juliapackaging.github.io/BinaryBuilder.jl/dev/jll/
を参考にすると、

```julia
using CLIME_jll
lime_contents() do exe
    run(`$exe`)
end
```
とすることで、実行ファイル```lime_contents```をJulia上で実行することができます。
なお、今回のコードは実際は引数が必要ですので、```run(`$exe lime_file_test`)```みたいな形で使います。

今回はBinaryBuilder.jlをMac上で実行しましたが、それだけで様々なプラットフォームに対応したJuliaライブラリができてしまいました。驚きです。