あのKotlinがnativeなバイナリを吐くようになったらしいので、少しためしてみました。 公式サイト→ Kotlin/Native for Native
とりあえず、 github にツールチェーンのバイナリがあるようなので取得。 ソースコードはめっちゃ小さい(2Mとか)のに、バイナリのtarballはえらく巨大(80M超え)なので、 「なんぞ?」と思ったのですが、ソースのREADMEを読んでみたら最初のステップが 依存ファイルを取得するためにgradleを実行とか書いてあって萎える。
しかも失敗するし……。
% ./gradlew dependencies:update
FAILURE: Build failed with an exception.
* What went wrong:
Could not create service of type ScriptPluginFactory using BuildScopeServices.createScriptPluginFactory().
> Could not create service of type PluginResolutionStrategyInternal using BuildScopeServices.createPluginResolutionStrategy().
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in xxs
まぁ、気をとりなおしてバイナリを持ってきました。 ウェブサイトだと、ホームディレクトリに展開しろとあっていやな予感がするも、ひとまず /opt にrootで展開してみる。 で、以下のhello.ktを作成。
fun main(args: Array<String>) {
println("Hello Kotlin!!")
}
おもむろにコンパイラをかける。
% /opt/kotlin-native-linux/bin/kotlinc-native hello.kt
そしたら、盛大にclang-llvmとかをダウンロードしだしました……。600MB超え。
幸か不幸か、/opt以下に吐き出すようなことはなく、 ~/.konan
というディレクトリに吐く模様。
しかし、ファイル展開後の ~/.konan
のサイズはなんと2G超え!!
おいマジか。
% du -sh ~/.konan/*
568M /home/rare/.konan/cache
1.9G /home/rare/.konan/dependencies
もう最近の言語がホームディレクトリを汚すのは我慢するしかないのでしょうか。 にしたってでかいよ。Hello Worldでこれか……。
さて、気をとりなおして、先程のコンパイルは普通に動作完了。
そしたらなんか、 program.kexe
なんて名前のファイルが。
もうちょっとネーミングなんとかならなかったのでしょうか。
バイナリを見てみると、以下のような感じ。
% ./program.kexe
Hello Kotlin!!
% file ./program.kexe
./program.kexe: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.16, BuildID[sha1]=cdbdc0ea05eaa710e7683260d8430c6d3b6232f8, not stripped
% readelf -hl program.kexe
ELF ヘッダ:
マジック: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
クラス: ELF64
データ: 2 の補数、リトルエンディアン
バージョン: 1 (current)
OS/ABI: UNIX - System V
ABI バージョン: 0
型: EXEC (実行可能ファイル)
マシン: Advanced Micro Devices X86-64
バージョン: 0x1
エントリポイントアドレス: 0x4040d1
プログラムの開始ヘッダ: 64 (バイト)
セクションヘッダ始点: 455040 (バイト)
フラグ: 0x0
このヘッダのサイズ: 64 (バイト)
プログラムヘッダサイズ: 56 (バイト)
プログラムヘッダ数: 10
セクションヘッダ: 64 (バイト)
セクションヘッダサイズ: 36
セクションヘッダ文字列表索引: 35
プログラムヘッダ:
タイプ オフセット 仮想Addr 物理Addr
ファイルサイズ メモリサイズ フラグ 整列
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x0000000000000230 0x0000000000000230 R 0x8
INTERP 0x0000000000000270 0x0000000000400270 0x0000000000400270
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000003a4a8 0x000000000003a4a8 R E 0x1000
LOAD 0x000000000003a7e0 0x000000000043b7e0 0x000000000043b7e0
0x000000000000b0e0 0x000000000001e671 RW 0x1000
DYNAMIC 0x0000000000041d20 0x0000000000442d20 0x0000000000442d20
0x0000000000000200 0x0000000000000200 RW 0x8
NOTE 0x000000000000028c 0x000000000040028c 0x000000000040028c
0x0000000000000044 0x0000000000000044 R 0x4
GNU_EH_FRAME 0x00000000000386b4 0x00000000004386b4 0x00000000004386b4
0x0000000000001df4 0x0000000000001df4 R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x0
TLS 0x000000000003a7e0 0x000000000043b7e0 0x000000000043b7e0
0x0000000000000000 0x0000000000000340 R 0x8
GNU_RELRO 0x000000000003a7e0 0x000000000043b7e0 0x000000000043b7e0
0x0000000000007820 0x0000000000007820 RW 0x10
セグメントマッピングへのセクション:
セグメントセクション...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .dynsym .dynstr .gnu.hash .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .gcc_except_table .eh_frame .eh_frame_hdr
03 .ctors .dtors .jcr .data.rel.ro .init_array .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .tbss
09 .ctors .dtors .jcr .data.rel.ro .init_array .dynamic .got
09 .ctors .dtors .jcr .data.rel.ro .init_array .dynamic .got
ふむふむ。 ほんとに実行可能なelfになってる。 Windowsな世界だと、ネイティブなバイナリを作れるのは大きいので、機会があったら使ってみてもいいかも。 色々と容量食うみたいだけど……。