C compiler cannot create executables

plotterscrossarm-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, ARarm-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にも同じようなことが書かれている。

Backlinks