C compiler cannot create executables
plottersをcrossでarm-unknown-linux-gnueabihf
向けにクロスコンパイルしようとしたら、その依存ライブラリであるservo-fontconfig-sysをコンパイルしているときにエラーが出た。
C compiler cannot create executables
ってなにそれ??
$ cross build --target arm-unknown-linux-gnueabihf
Compiling servo-fontconfig-sys v5.1.0
error: failed to run custom build command for `servo-fontconfig-sys v5.1.0`
...
configure: error: C compiler cannot create executables
まとめ
本来crossのDocker imageに導入されているツールチェインには arm-linux-gnueabihf-gcc
などの名前がついているが、どういうわけか arm-**unknown**-linux-gnueabihf-gcc
とtripleをプレフィックスにしたものがビルドに使われていた。
解決策として、crossのイメージを継承したDockerfileを書いて、そこで環境変数CC, AR
を手動で設定し直した。
FROM rustembedded/cross:arm-unknown-linux-gnueabihf-0.2.1
ENV CC=arm-linux-gnueabihf-gcc
ENV AR=arm-linux-gnueabihf-ar
RUN dpkg --add-architecture armhf && \
apt-get update && \
apt-get install --assume-yes libc6-dev:armhf libfreetype6-dev:armhf libfontconfig1-dev:armhf
流れ
最小限の構成で再現する。Cargo.toml
はこんな感じ。
...
[dependencies]
servo-fontconfig-sys = { version = "~5.1.0" }
まずそのままコンパイルする。失敗する。
$ cross build --target arm-unknown-linux-gnueabihf
Compiling servo-fontconfig-sys v5.1.0
error: failed to run custom build command for `servo-fontconfig-sys v5.1.0`
...
configure: error: C compiler cannot create executables
ログの途中を見ると、CC, AR
がarm-unknown-linux-gnueabihf-*
になっている。後でDockerイメージを中から操作してわかることだが、このバイナリは存在しない。「Cコンパイラが実行可能形式を作れない」というエラーメッセージはミスリーディングだった。
cd /target/arm-unknown-linux-gnueabihf/debug/build/servo-fontconfig-sys-8faeaf562738eeb3/out && \
CC="arm-unknown-linux-gnueabihf-gcc" \
AR="arm-unknown-linux-gnueabihf-ar" \
...
--host=arm-unknown-linux-gnueabihf --sysconfdir=/etc --localstatedir=/var
そこから下に移ると、やはりarm-unknown-linux-gnueabihf-gcc
を探していることがわかる(1行目)。そもそもコンパイラが存在しないので、動作するも何もない。よって whether the C compiler works... no
となる(これもミスリーディング)。そして冒頭のエラーが出る。config.log
は後で見る。
checking for arm-unknown-linux-gnueabihf-gcc... arm-unknown-linux-gnueabihf-gcc
checking whether the C compiler works... no
makefile.cargo:83: recipe for target '/target/arm-unknown-linux-gnueabihf/debug/build/servo-fontconfig-sys-8faeaf562738eeb3/ou
t/Makefile' failed
--- stderr
configure: error: in `/target/arm-unknown-linux-gnueabihf/debug/build/servo-fontconfig-sys-8faeaf562738eeb3/out':
configure: error: C compiler cannot create executables
See `config.log' for more details
ちなみに、最後のはmake/configureのエラーを受けてRustが吐いているだけなので特に気にする必要はない。
make: *** [/target/arm-unknown-linux-gnueabihf/debug/build/servo-fontconfig-sys-8faeaf562738eeb3/out/Makefile] Error 77
thread 'main' panicked at 'assertion failed: Command::new(\"make\").env(\"MAKEFLAGS\",\n env::var(\"CA
RGO_MAKEFLAGS\").unwrap_or_default()).args(&[\"-R\",\n
\"-f\",\n \"makefile.cargo\"]).status().u
nwrap().success()', /cargo/registry/src/github.com-1ecc6299db9ec823/servo-fontconfig-sys-5.1.0/build.rs:41:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
さて、config.log
を見てみたいのだが、crossのデフォルトではコンパイルが終わると即座にDockerイメージが終了してしまう。config.log
がどこにあるかもよくわからないので、イメージをシェル経由で触りたい。
crossに-v
オプションをつけて実行すると、内部で呼び出しているコマンドが見えた。rustup関連のチェックの後にDockerコンテナを立ち上げている。
$ cross build --target arm-unknown-linux-gnueabihf -v
+ "rustc" "--print" "sysroot"
+ "rustup" "toolchain" "list"
+ "rustup" "target" "list" "--toolchain" "stable-x86_64-unknown-linux-gnu"
+ "rustup" "component" "list" "--toolchain" "stable-x86_64-unknown-linux-gnu"
+ "/usr/bin/docker" "run" "--userns" "host" "-e" "PKG_CONFIG_ALLOW_CROSS=1" "--rm" "--user" "1000:1000" "-e" "XARGO_HOME=/xargo"
"-e" "CARGO_HOME=/cargo" "-e" "CARGO_TARGET_DIR=/target" "-e" "USER=sei0o" "-e" "CROSS_RUNNER=" "-v" "/home/sei0o/.xargo:/xargo
:Z" "-v" "/home/sei0o/.cargo:/cargo:Z" "-v" "/cargo/bin" "-v" "/home/sei0o/sandbox/test_fontconfig:/project:Z" "-v" "/home/sei0o
/.rustup/toolchains/stable-x86_64-unknown-linux-gnu:/rust:Z,ro" "-v" "/home/sei0o/sandbox/test_fontconfig/target:/target:Z" "-w"
"/project" "-i" "-t" "rustembedded/cross:arm-unknown-linux-gnueabihf-0.2.1" "sh" "-c" "PATH=$PATH:/rust/bin cargo build --targe
t arm-unknown-linux-gnueabihf -v"
Fresh pkg-config v0.3.22
Fresh cc v1.0.71
最後の "sh" "-c" "PATH=$PATH:/rust/bin cargo build --target arm-unknown-linux-gnueabihf -v"
をbash
に変えればインタラクティブシェルに入れた。CC
で指定されていたarm-unknown-linux-gnueabihf-gcc
は存在していなくて、arm-linux-gnueabihf-gcc
を使うべきだった。
$ "/usr/bin/docker" "run" "--userns" "host" "-e" "PKG_CONFIG_ALLOW_CROSS
=1" "--rm" "--user" "1000:1000" "-e" "XARGO_HOME=/xargo" "-e" "CARGO_HOME=/cargo" "-e" "CARGO_TARGET_DIR=/target" "-e" "USER=sei
0o" "-e" "CROSS_RUNNER=" "-v" "/home/sei0o/.xargo:/xargo:Z" "-v" "/home/sei0o/.cargo:/cargo:Z" "-v" "/cargo/bin" "-v""/home/sei0
o/sandbox/test_fontconfig:/project:Z" "-v" "/home/sei0o/.rustup/toolchains/stable-x86_64-unknown-linux-gnu:/rust:Z,ro" "-v" "/ho
me/sei0o/sandbox/test_fontconfig/target:/target:Z" "-w" "/project" "-i" "-t" "rustembedded/cross:arm-unknown-linux-gnueabihf-0.2
.1" bash
I have no name!@eac85a1a70d6:/project$ arm-unknown-linux-gnueabihf-gcc
bash: arm-unknown-linux-gnueabihf-gcc: command not found
I have no name!@eac85a1a70d6:/project$ arm-linux-gnueabihf-gcc
arm-linux-gnueabihf-gcc: fatal error: no input files
compilation terminated.
パッケージがビルドされる場所にconfig.log
を見つけた。command not found
やら$? = 127
やら怪しい匂いがする。最終的に使われた環境変数もすべて載っているので、とりあえずAR, CC
を変えてやればいいことがわかった。
I have no name!@eac85a1a70d6:/project$ cat /target/arm-unknown-linux-gnueabihf/debug/build/servo-fontconfig-sys-8faeaf562738eeb3
...
## ----------- ##
## Core tests. ##
## ----------- ##
...
configure:3332: checking for arm-unknown-linux-gnueabihf-gcc
configure:3359: result: arm-unknown-linux-gnueabihf-gcc
configure:3628: checking for C compiler version
...
configure:3668: checking whether the C compiler works
configure:3690: arm-unknown-linux-gnueabihf-gcc -fPIC conftest.c >&5
/cargo/registry/src/github.com-1ecc6299db9ec823/servo-fontconfig-sys-5.1.0/configure: line 3692: arm-unknown-linux-gnueabihf-gcc
: command not found
configure:3694: $? = 127
configure:3732: result: no
...
configure:3737: error: in `/target/arm-unknown-linux-gnueabihf/debug/build/servo-fontconfig-sys-8faeaf562738eeb3/out':
configure:3739: error: C compiler cannot create executables
See `config.log' for more details
## ---------------- ##
## Cache variables. ##
## ---------------- ##
...
## ----------------- ##
## Output variables. ##
## ----------------- ##
...
AR='arm-unknown-linux-gnueabihf-ar'
...
CC='arm-unknown-linux-gnueabihf-gcc'
...
I have no name!@eac85a1a70d6:/project$
まあ I have no name!
と言っている通り、crossのコンテナ内部に入ることは想定されていないし、できれば外部で済ませたい。issue #260にも同じようなことが書かれている。