平常運転

アニソンが好き

過去記事とかは記事一覧で見れます

macOS 上の Go 1.8 でクロスコンパイルしたバイナリが QNAP で動かなくて困っている

だいたいのことはタイトルで言い尽くした。 Docker でビルドする、という workaround で凌いでいるけど、根本的な原因も解決策も分かっていない……

前書き

手元の QNAP TS-220 という NAS を使っている。これは ARMv5 で、 Linux ベースの QTS という OS が動いている。こいつの監視の為に Go で書かれた mackerel-agent を macOS でクロスコンパイルして動かしているのだけど、手元の Go を 1.8 に上げたらバイナリが動かなくなった。

最初は mackerel-agent が悪いのかと思ったけど、 Hello World 程度でも再現するのでソースコードの問題では無さそう。

状況

こういう超素朴な Go のソースに対して、
gist.github.com

arm 向けのクロスコンパイルを (macOS で) 行う。

$ GOOS=linux GOARCH=arm GOARM=5 go build hello.go -o hello

scp して動かすと、 Go 1.7.4 でビルドしたバイナリはふつうに動く。

[~] # ~/hello
Hello!

しかし、これと同じことを Go 1.8 でやると、 "Illegal instruction" が出るだけで実行できない。巷の噂によるとスタックトレースが出るという話もあるけど、ただこの1行だけを残して死ぬ。

[~] # ~/hello
Illegal instruction

いっぽうで、 Docker 上の Go でビルドするとふつうに動く。ビルドはこういう感じ。

$ docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp -e GOOS=linux -e GOARCH=arm -e GOARM=5 golang go build

現在地

最初は Go 1.8 が全部だめなのかと思って絶望していたけど、ひとまずは Docker 経由でビルドすれば動いているので我慢している。面倒なので直って欲しいけれど、 gdb が入ってすらいない QNAP で詳細を追うのが面倒で手を付けられていない……

付録

Docker 経由で QNAP 用 mackerel-agent をビルドするコマンドです。マウントポイントが可愛いですね。

$ docker run --rm -v "$PWD":/go/src/github.com/mackerelio/mackerel-agent -w /go/src/github.com/mackerelio/mackerel-agent -e GOOS=linux -e GOARCH=arm -e GOARM=5 golang make build

QNAP ではそのままだと動かない箇所があるので、適当にパッチを当てています。この辺にあります : https://github.com/astj/mackerel-agent/tree/qts