はじめに
Ubuntu18.04でtinygoをインストールしようとしたらハマったのでメモっておく。
基本はここの手順。
Requirement
あとは、ターゲットのツールチェイン。
- ARM Cortex-M
- AVR(Arduino)
- WebAssembly
詳細は先述のリンク元を参照。
筆者環境はarm-none-eabiがインストール済み。
goのインストール
いろいろ手段があるが、インストーラによるインストールが一番便利だった。
$ sudo apt install wget git $ wget -q https://storage.googleapis.com/golang/getgo/installer_linux $ chmod +x installer_linux $ ./installer_linux -version 1.11.7
GOPATHの設定は.bash_profile
に自動的に作成される。
このインストーラ意外と優秀で-version 1.11.7
とかやると、特定のバージョンをインストールしてくれる。
引数なしの場合は最新バージョン。今回は1.12がインストールされた。
(4/7 追記)
ここで1.11
系のgoをインストールしておく必要がある。現時点では1.11.7
が最新。
そうしないと、tinygoの実行時に次のエラーが発生する。
$ tinygo flash -target=bluepill examples/blinky1 .go/src/syscall/js/func.go:74:3: todo: unknown expression: select blocking []
既にインストールしてしまった場合はgoを入れ直す必要がある。
このインストーラでインストールした場合は~/.go
を削除すれば良い。
$ rm -rf ~/.go $ ./installer_linux -version 1.11.7
GOPATHの設定
UbuntuのGUI環境では、.bash_profile
はログイン時にしか読み込まれないので、
一度ログインし直すか、新しく開いた端末で次のコマンドを実行する。
$ source ${HOME}/.bash_profile
.bash_profile
に追加された内容を.bashrc
に移動してしまうというのも手。
export PATH=$PATH:/home/mickey/.go/bin export GOPATH=/home/mickey/go export PATH=$PATH:/home/mickey/go/bin
llvm-7のインストール
ここを参考にした。
sources.listの追加
llvm 7.0.1をインストールするために、/etc/apt/sources.list.d/llvm.list
を次の内容で作成する。
# i386 not available deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main # 7 deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main # 8 deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main
これがないと、7.0.0がインストールされる。
$ wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - $ sudo apt update
これも忘れずに。
パッケージのインストール
Install (stable branch)
に書いてあったものすべて入れた。
$ sudo apt install clang-7 lldb-7 lld-7 $ sudo apt install libllvm-7-ocaml-dev libllvm7 llvm-7 llvm-7-dev llvm-7-doc llvm-7-examples llvm-7-runtime $ sudo apt install clang-7 clang-tools-7 clang-7-doc libclang-common-7-dev libclang-7-dev libclang1-7 clang-format-7 python-clang-7 $ sudo apt install lldb-7 lld-7 libc++-7-dev libc++abi-7-dev
tinygoのインストール
まずはgo get
を実行する。が、これは必ず失敗する(した)。
$ go get -u github.com/tinygo-org/tinygo
エラー発生(その1)
次のようなエラーが発生した。
$ go get -u github.com/tinygo-org/tinygo # tinygo.org/x/go-llvm ../../go/src/tinygo.org/x/go-llvm/analysis.go:17:10: fatal error: llvm-c/Analysis.h: No such file or directory #include "llvm-c/Analysis.h" // If you are getting an error here read bindings/go/README.txt ^~~~~~~~~~~~~~~~~~~ compilation terminated.
ここによると、次のように説明されている。
If you get an error like this:: /usr/local/go/pkg/tool/linux_amd64/link: running g++ failed: exit status 1 /usr/bin/ld: error: cannot find -lLLVM-7 cgo-gcc-prolog:58: error: undefined reference to 'LLVMVerifyFunction' cgo-gcc-prolog:80: error: undefined reference to 'LLVMVerifyModule' [...etc...] Or like this:: ../go-llvm/analysis.go:17:93: fatal error: llvm-c/Analysis.h: No such file or directory #include "llvm-c/Analysis.h" // If you are getting an error here read bindings/go/README.txt It means something is wrong with your LLVM installation. Make sure LLVM 7 is installed (Debian package llvm-7-dev). If it still doesn’t work, you can try running: cd $GOPATH/src/github.com/tinygo-org/go-llvm make config And retry: go install github.com/tinygo-org/tinygo
llvm-7-dev
はインストールしてあるので、make config
を実行する。
go-llvmのソースの場所が実際は異なっているので次のようにする。
$ cd $GOPATH/src/tinygo.org/x/go-llvm/ $ make config
アドバイス通りに次を実行する。
$ go install github.com/tinygo-org/tinygo
エラー発生(その2)
今度は次のようなエラーが発生した。
# tinygo.org/x/go-llvm panic: overlapping edits: [8156,8319)->"func() _Ctype_LLVMMetadataRef{ _cgo0 := /*line :297:3*/d.ref; var _cgo1 *_Ctype_char = /*line :298:3*/name; var _cgo2 _Ctype_size_t = _Ctype_size_t(len(t.Name)); var _cgo3 _Ctype_uint64_t = _Ctype_uint64_t(t.SizeInBits); var _cgo4 _Ctype_LLVMDWARFTypeEncoding = _Ctype_LLVMDWARFTypeEncoding(t.Encoding); _cgoCheckPointer(_cgo0); return _Cfunc_LLVMDIBuilderCreateBasicType(_cgo0, _cgo1, _cgo2, _cgo3, _cgo4); }()", [8299,8312)->" /*line :302:3*/_Ctype_LLVMDIFlags /*line :302:16*/" goroutine 1 [running]: cmd/internal/edit.(*Buffer).Bytes(0xc0000e1650, 0xc0001b20e0, 0x5f171f, 0xe) /usr/local/go/src/cmd/internal/edit/edit.go:79 +0x5a4 main.(*Package).writeOutput(0xc0000b4000, 0xc0000a63c0, 0x7ffe1ab7ad12, 0x35) /usr/local/go/src/cmd/cgo/out.go:562 +0x38e main.main() /usr/local/go/src/cmd/cgo/main.go:356 +0xceb
これは解決方法も示されていなかったので、こまった。
どうやらgo-llvm
でエラーが発生しているらしい。
解決方法
go-llvmのソースはgitリポジトリなので、コミットログを調べてみた。
commit 7707ae5d1261a8929edea7336c8087ca8b520d8d (HEAD -> master, origin/master, origin/llvm8, origin/HEAD) Author: Ayke van Laethem <aykevanlaethem@gmail.com> Date: Thu Feb 14 11:10:53 2019 +0100 Switch to LLVM 8
なんと、(現時点の)最新のコミットで LLVM 8に移行した と。
気を取り直してブランチを確認してみる。
$ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/llvm7 remotes/origin/llvm8 remotes/origin/make-release remotes/origin/master remotes/origin/windows
llvm7系のブランチはあるみたい。
tinygoのgo getでリポジトリが汚れているようなので一度きれいにする。
$ git reset --hard HEAD
llvm7ブランチに切り替える
$ git checkout -b llvm7 origin/llvm7
ビルドしてみる。
$ go build -v github.com/tinygo-org/tinygo tinygo.org/x/go-llvm github.com/tinygo-org/tinygo/ir github.com/tinygo-org/tinygo/interp github.com/tinygo-org/tinygo/compiler github.com/tinygo-org/tinygo
通った。
インストール
$ go install github.com/tinygo-org/tinygo
成功した!
まとめ
go-llvmがLLVM 8に移行していた。 回避するには手でブランチを切り替える必要がある。
go get
では依存するリポジトリのコミットかブランチを指定できればよいのに。。
(4/7 追記)
goのバージョンは1.11
系(現時点の最新は1.11.7
)をインストールする必要がある。