🐤
CMake: "clang++ is not able to compile a simple test program" エラー対処方法
はじめに
x86_64
マシンでARM64
ターゲット向けにCMakeでクロスビルドする場合に、使い方次第では遭遇する以下のエラーの対処方法についてまとめています。
[ +5 ms] Failed to cmake:
-- The CXX compiler identification is Clang 10.0.0
-- Check for working CXX compiler: /usr/bin/clang++
-- Check for working CXX compiler: /usr/bin/clang++ -- broken
-- Configuring incomplete, errors occurred!
See also "/hoge/CMakeFiles/CMakeOutput.log".
See also "/hoge/CMakeFiles/CMakeError.log".
CMake Error at /usr/share/cmake-3.16/Modules/CMakeTestCXXCompiler.cmake:53 (message):
The C++ compiler
"/usr/bin/clang++"
is not able to compile a simple test program.
It fails with the following output:
Change Dir: /hoge/CMakeFiles/CMakeTmp
Run Build Command(s):/hoge/arm64-sysroot/usr/bin/make cmTC_9cca1/fast && /lib/ld-linux-aarch64.so.1: No such file or directory
CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
CMakeLists.txt:2 (project)
原因
try_compile
する際のコンパイラのバイナリがホストPCのものではなく、指定したsysroot側のものを参照利用しているためです。
try_compile
は、CMakeファイルの中のproject()を指定したところまでの設定で実行される様子です。そのため、project()
が記述されているところまでの設定が不適切である場合、このエラーに遭遇する可能性があります。
クロスビルド時のsysrootの指定方法
そもそも、クロスビルドする場合、通常はターゲット (ARM64) のsysroot
を指定すると思います。この場合、以下の2つのやり方があります。
- CMakeファイルの中で
CMAKE_SYSROOT
オプションを利用 - cmakeコマンドを打つ時のコマンドオプション
-DCMAKE_SYSROOT
を利用
エラーが起きるケース
cmakeコマンドで-DCMAKE_SYSROOT
を指定している場合、必然的にproject()
の前にsysrootが設定されてしまっている状態になるため、この問題が起きる可能性があります。
対策と結論
結論としては、try_compile
が実行される時点でホスト側のツールチェーン(コンパイラ)が利用されるようにしましょう。
- makeコマンドで
-DCMAKE_SYSROOT
を指定せず、CMakeファイルの中でCMAKE_SYSROOT
オプションを利用する(かつproject()
の記述の後) - cmakeコマンドの
-DCMAKE_SYSROOT
オプションを利用する場合、以下のようにproject()
の前にset(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
を記述する
cmake_minimum_required(VERSION 3.15)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) // projectの前にこれを記述する
project(runner LANGUAGES CXX)
のどちらかになります。
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM 変数
find_program()
でプログラムをサーチする際にCMAKE_FIND_ROOT_PATH
およびCMAKE_SYSROOT
で設定されているパスを参照するかどうかを設定します。NEVER
を設定することで必ずホスト側のプログラムが利用されるようになります。
参考文献
Discussion