Elixirをとりあえず最小の手数でソースビルドしてみる

https://qiita.com/advent-calendar/2021/elixir

この記事は [Elixir Advent Calendar 2021](https://qiita.com/advent-calendar/2021/elixir) の4日目です．
昨日は @iyanayatudaze さんの「[iexで関数のドキュメントを調べる方法 他3本](https://zenn.dev/ito_shigeru/articles/dc238b216d73f2)」でした．

---

Elixirの東京なコミュニティである [tokyo.ex a.k.a beam-lang.tokyo](https://beam-lang.connpass.com/) がrebootされました！！
ワタクシゴトで恐縮ですが4月から東京に拠点が移りましたので，ぜひ楽しんでいきたい／contributionしていきたいなと思っています．

https://beam-lang.connpass.com/event/227103/

さて上記のイベントで @ohr486 さんからawesome!!な発表がありました．
Hack and Read Elixir - Speaker Deck 
https://speakerdeck.com/ohr486/hack-and-read-elixir

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240349/b1c9245f-dbfd-8cf5-cb43-768e5bc01161.png)](https://speakerdeck.com/ohr486/hack-and-read-elixir)

質問タイムで聞いてみたところ，ElixirのソースビルドはErlang環境があればさくっといけまっせ！とのことでした．
元来の組込みやさんとしては，ビルドログをぜひ眺めてみたい！でも最小の手数でやりたいしDockerだよね？ってのをトライしてみました．ということで（@torifukukaiou さんのAdvent Calendar芸を見習って）[Elixir Advent Calendar 2021](https://qiita.com/advent-calendar/2021/elixir)に投下してみます．

# ErlangのDockerコンテナを起動

Erlangの[Official image](https://hub.docker.com/_/erlang)をさくっと使います．デフォルトのENTRYPOINTでは `erl` が起動されるので `/bin/bash` を明示的に使います．

```bash
$ docker run -it erlang /bin/bash
Unable to find image 'erlang:latest' locally
latest: Pulling from library/erlang
1230f17f526c: Pull complete 
d17d0de332ca: Pull complete 
7474d56348f5: Pull complete 
211c565de405: Pull complete 
71337a3dfc6f: Pull complete 
c393abc13548: Pull complete 
be296cceaf64: Pull complete 
4f7a765b6d95: Pull complete 
Digest: sha256:847c83c7a03a24ea5e6f2074e3e6f1eca3d9815608dc2101552f5c3ec5e5d953
Status: Downloaded newer image for erlang:latest
root@a05161b27ca6:/# 
```

試してみた時点でのErlangのバージョンは24.1.6でした（いつも忘れる[FYI](https://stackoverflow.com/questions/9560815/how-to-get-erlangs-release-version-number-from-a-shell)

```shell-session
root@a05161b27ca6:/# which erl
/usr/local/bin/erl
root@a05161b27ca6:/# cat /usr/local/lib/erlang/releases/24/OTP_VERSION 
24.1.6
```

エレガントにやるならこんな感じ？

```shell-session
root@a05161b27ca6:/# erl -eval '{ok, Version} = file:read_file(filename:join([code:root_dir(), "releases", erlang:system_info(otp_release), "OTP_VERSION"])), io:fwrite(Version), halt().' -noshell
24.1.6
```

もちろんElixirはまだありません．

```shell-session
root@a05161b27ca6:/# which elixir

```

# Elixirのソースコードをgit clone

ElixirのソースコードはGitHubで公開されています．

https://github.com/elixir-lang/elixir

ホームに移動して `git clone` します．

```shell-session
root@a05161b27ca6:~# git clone https://github.com/elixir-lang/elixir
Cloning into 'elixir'...
remote: Enumerating objects: 165885, done.
remote: Counting objects: 100% (11/11), done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 165885 (delta 3), reused 2 (delta 0), pack-reused 165874
Receiving objects: 100% (165885/165885), 49.04 MiB | 15.13 MiB/s, done.
Resolving deltas: 100% (108440/108440), done.
```

お試し時のcommit hashは [bb386c9](https://github.com/elixir-lang/elixir/tree/bb386c9f5134962d9a149f83683bc658a99569ad) でした．

```shell-session
root@a05161b27ca6:~# cd elixir/
root@a05161b27ca6:~/elixir# git log | head -n 1
commit bb386c9f5134962d9a149f83683bc658a99569ad
```

# 環境変数の設定

ElixirはUTF-8であってほしいところDockerイメージはデフォルトでは文字コードが設定されていないので，よしなにしておきます．これでビルド時の警告抑止＆テスト実行ができるようになります．

```shell-session
root@a05161b27ca6:~/elixir# export LANG=C.UTF-8
```

# さてソースビルド

なんとトップディレクトリで `make` するだけでした．

```shell-session
root@a05161b27ca6:~/elixir# make 
Recompile: src/elixir_utils
Recompile: src/elixir_tokenizer
Recompile: src/elixir_sup
Recompile: src/elixir_rewrite
Recompile: src/elixir_quote
Recompile: src/elixir_parser
Recompile: src/elixir_overridable
Recompile: src/elixir_module
Recompile: src/elixir_map
Recompile: src/elixir_locals
Recompile: src/elixir_lexical
Recompile: src/elixir_interpolation
Recompile: src/elixir_import
Recompile: src/elixir_fn
Recompile: src/elixir_expand
Recompile: src/elixir_errors
Recompile: src/elixir_erl_var
Recompile: src/elixir_erl_try
Recompile: src/elixir_erl_pass
Recompile: src/elixir_erl_for
Recompile: src/elixir_erl_compiler
Recompile: src/elixir_erl_clauses
Recompile: src/elixir_erl
Recompile: src/elixir_env
Recompile: src/elixir_dispatch
Recompile: src/elixir_def
Recompile: src/elixir_config
Recompile: src/elixir_compiler
Recompile: src/elixir_code_server
Recompile: src/elixir_clauses
Recompile: src/elixir_bootstrap
Recompile: src/elixir_bitstring
Recompile: src/elixir_aliases
Recompile: src/elixir
Generated elixir app
==> bootstrap (compile)
Compiled lib/elixir/lib/kernel.ex
Compiled lib/elixir/lib/macro/env.ex
Compiled lib/elixir/lib/keyword.ex
Compiled lib/elixir/lib/module.ex
Compiled lib/elixir/lib/list.ex
Compiled lib/elixir/lib/macro.ex
Compiled lib/elixir/lib/kernel/typespec.ex
Compiled lib/elixir/lib/kernel/utils.ex
Compiled lib/elixir/lib/code.ex
Compiled lib/elixir/lib/code/identifier.ex
Compiled lib/elixir/lib/protocol.ex
Compiled lib/elixir/lib/stream/reducers.ex
Compiled lib/elixir/lib/enum.ex
Compiled lib/elixir/lib/regex.ex
Compiled lib/elixir/lib/inspect/algebra.ex
Compiled lib/elixir/lib/inspect.ex
Compiled lib/elixir/lib/string.ex
Compiled lib/elixir/lib/string/chars.ex
Compiled lib/elixir/lib/kernel.ex
Compiled lib/elixir/lib/list/chars.ex
Compiled lib/elixir/lib/module/locals_tracker.ex
Compiled lib/elixir/lib/module/parallel_checker.ex
Compiled lib/elixir/lib/module/types/helpers.ex
Compiled lib/elixir/lib/module/types/unify.ex
Compiled lib/elixir/lib/module/types/of.ex
Compiled lib/elixir/lib/module/types/pattern.ex
Compiled lib/elixir/lib/module/types/expr.ex
Compiled lib/elixir/lib/module/types.ex
Compiled lib/elixir/lib/exception.ex
Compiled lib/elixir/lib/path.ex
Compiled lib/elixir/lib/file.ex
Compiled lib/elixir/lib/map.ex
Compiled lib/elixir/lib/range.ex
Compiled lib/elixir/lib/access.ex
Compiled lib/elixir/lib/io.ex
Compiled lib/elixir/lib/system.ex
Compiled lib/elixir/lib/code/formatter.ex
Compiled lib/elixir/lib/code/normalizer.ex
Compiled lib/elixir/lib/kernel/cli.ex
Compiled lib/elixir/lib/kernel/error_handler.ex
Compiled lib/elixir/lib/kernel/parallel_compiler.ex
Compiled lib/elixir/lib/kernel/lexical_tracker.ex
make[1]: Entering directory '/root/elixir'
==> unicode (compile)
make[1]: Leaving directory '/root/elixir'
==> elixir (compile)
make[1]: Entering directory '/root/elixir'
Generated elixir app
make[1]: Leaving directory '/root/elixir'
==> eex (compile)
==> mix (compile)
Generated mix app
==> ex_unit (compile)
Generated ex_unit app
==> logger (compile)
Generated logger app
Generated eex app
==> iex (compile)
Generated iex app
```

なお手元の環境では，Docker使用なのにソースビルドに1分も掛からずという感じでした．

```shell-session
root@a05161b27ca6:~/elixir# make clean ; time make 
Generated iex app

real	0m48.377s
user	1m12.529s
sys	0m17.817s
```

たのしい:yum:

# できたものを確認してみる

`./bin/` にいろいろあります．

```shell-session
root@a05161b27ca6:~/elixir# ls bin/
elixir	elixir.bat  elixirc  elixirc.bat  iex  iex.bat	mix  mix.bat  mix.ps1
```

1.14.0タノシミダナ〜

```shell-session
root@a05161b27ca6:~/elixir# ./bin/elixir --version 
Erlang/OTP 24 [erts-12.1.5] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Elixir 1.14.0-dev (bb386c9) (compiled with Erlang/OTP 24)
```

tokyo.ex でバズった `ELIXIR_CLI_DRY_RUN` をやってみます．

```shell-session
root@a05161b27ca6:~/elixir# ELIXIR_CLI_DRY_RUN=1 ./bin/elixir --version 
erl -pa /root/elixir/bin/../lib/eex/ebin /root/elixir/bin/../lib/elixir/ebin /root/elixir/bin/../lib/ex_unit/ebin /root/elixir/bin/../lib/iex/ebin /root/elixir/bin/../lib/logger/ebin /root/elixir/bin/../lib/mix/ebin -elixir ansi_enabled true -noshell -s elixir start_cli -extra --version
root@a05161b27ca6:~/elixir# ELIXIR_CLI_DRY_RUN=1 ./bin/iex --version 
erl -pa /root/elixir/bin/../lib/eex/ebin /root/elixir/bin/../lib/elixir/ebin /root/elixir/bin/../lib/ex_unit/ebin /root/elixir/bin/../lib/iex/ebin /root/elixir/bin/../lib/logger/ebin /root/elixir/bin/../lib/mix/ebin -elixir ansi_enabled true -noshell -user Elixir.IEx.CLI -extra --no-halt +iex --version
```

# テストしてみる

テストは大事です，しらんけど．
`make test` でやれます．やっぱりちょっとは時間が掛かりますね．

```shell-session
root@a05161b27ca6:~/elixir# time make test 
==> elixir (eunit)
  All 131 tests passed.

==> elixir (ex_unit)
Excluding tags: [windows: true]

.................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

Finished in 37.4 seconds (17.7s on load, 12.8s async, 6.8s sync)
1783 doctests, 3925 tests, 0 failures, 11 excluded

Randomized with seed 376387
==> ex_unit (ex_unit)
..............................................................................................................................................................................................................................................................................................................................................................................................

Finished in 4.2 seconds (1.9s on load, 0.3s async, 1.9s sync)
44 doctests, 338 tests, 0 failures

Randomized with seed 479964
==> logger (ex_unit)
.............................................................................................................................................

Finished in 2.1 seconds (1.5s on load, 0.03s async, 0.6s sync)
3 doctests, 138 tests, 0 failures

Randomized with seed 820044
==> eex (ex_unit)
..........................................................................................................

Finished in 0.4 seconds (0.3s on load, 0.07s async, 0.00s sync)
7 doctests, 99 tests, 0 failures

Randomized with seed 287602
==> iex (ex_unit)
.............................................................................................................................................................................................................................................

Finished in 7.3 seconds (1.1s on load, 0.4s async, 5.6s sync)
237 tests, 0 failures

Randomized with seed 87948
==> mix (ex_unit)
Excluding tags: [windows: true]

..........................run_erl[10672]: Erlang closed the connection.

...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

Finished in 159.6 seconds (5.0s on load, 0.03s async, 154.5s sync)
6 doctests, 707 tests, 0 failures

Randomized with seed 876273

real	3m39.851s
user	3m45.667s
sys	1m39.993s
```

# Wrapping Up

awesome!!!:tada::tada::tada::tada:

さてソースビルドできたところでここからなにやっていくか,,, 次回に乞うご期待！？？

明日の [Elixir Advent Calendar 2021](https://qiita.com/advent-calendar/2021/elixir) は @h3_poteto さんによる「[ElixirでHot Code Reloadingするときに気をつけること](https://medium.com/ovice/elixir%E3%81%A7hot-code-reloading%E3%81%99%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%AB%E6%B0%97%E3%82%92%E3%81%A4%E3%81%91%E3%82%8B%E3%81%93%E3%81%A8-b5058eec86dd)」です．