CMake传递的变量编译器无法编译简单的程序

Posted

技术标签:

【中文标题】CMake传递的变量编译器无法编译简单的程序【英文标题】:CMake Passed variables compiler is not able to compile a simple program 【发布时间】:2017-07-28 21:24:10 【问题描述】:

我正在尝试使用 CMake 交叉编译应用程序。当我对交叉编译器的路径进行硬编码时,一切正常。但是,当我通过命令行参数传递路径时,它似乎无法正确跟踪它们。

这是我的 shell 脚本,我从中克隆一个 repo,应用补丁,然后尝试 cmake 构建:

   cmake -D BASE=$PATH_TO_TOOLCHAIN_ROOT -D BOOST_ROOT=$BOOST_ROOT -D CMAKE_TOOLCHAIN_FILE=../toolchain.cmake ../$GIT_PATH/src/

这是我的 toolchain.cmake 文件:

set( CMAKE_SYSTEM_NAME Linux )
set( CMAKE_SYSTEM_VERSION 1 )
set(PKG_CONFIG_EXECUTABLE "/usr/bin/pkg-config")

message("Base: $BASE")
message("Boost: $BOOST_ROOT")

set(CMAKE_SYSROOT "$BASE/sysroot")

set(CMAKE_C_COMPILER "$BASE/sysroot/usr/bin/mipsel-linux-gcc")
set(CMAKE_CXX_COMPILER "$BASE/sysroot/usr/bin/mipsel-linux-g++") 

set( CMAKE_FIND_ROOT_PATH "$BASE/sysroot")

set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
# for libraries and headers in the target directories
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH)
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH)


include_directories($CMAKE_SYSROOT/usr/local/include/)

set(BOOST_INCLUDEDIR $BOOST_ROOT/include)
set(BOOST_LIBRARYDIR $BOOST_ROOT/lib)

include_directories($BOOST_INCLUDEDIR)

set(OPENSSL_ROOT_DIR $BASE/sysroot/usr/lib/)
set(OPENSSL_SSL_LIBRARY libssl.so)
set(OPENSSL_CRYPTO_LIBRARY libcrypto.so)

同样,如果我在这个工具链文件中将 $BASE 硬编码为 /path/to/mipsel-linux-gcc,它可以工作。

但是,当我真正调用它时,我得到了这个打印输出:

+ cmake -D BASE=/path/to/toolchain/root -D BOOST_ROOT=/home/matthew/boost/out -D CMAKE_TOOLCHAIN_FILE=../toolchain.cmake ../build/src/
Base: /path/to/toolchain/root
Boost: /home/matthew/boost/out
Base: /path/to/toolchain/root
Boost: /home/matthew/boost/out
-- The C compiler identification is GNU 4.7.3
-- The CXX compiler identification is GNU 4.7.3
-- Check for working C compiler: /path/to/toolchain/root/sysroot/usr/bin/mipsel-linux-gcc
Base: 
Boost: 
-- Check for working C compiler: /path/to/toolchain/root/sysroot/usr/bin/mipsel-linux-gcc -- broken
CMake Error at /usr/local/share/cmake-3.8/Modules/CMakeTestCCompiler.cmake:51 (message):
  The C compiler
  "/path/to/toolchain/root/sysroot/usr/bin/mipsel-linux-gcc"
  is not able to compile a simple test program.

  It fails with the following output:

   Change Dir: /home/matthew/Desktop/clones/build/CMakeFiles/CMakeTmp

在这里您可以清楚地看到它确实找到了编译器,并将它们都标识为 GNU 4.7.3。但是,请注意打印输出 Base: /path/to/toolchain/root。这个 message() 指令在 toolchain.cmake 中只列出了一次,但它在这里打印了几次,最终显示为一个空白变量。之后,它抱怨 C 编译器不工作,即使它清楚地打印出该编译器的完整路径。

我见过其他人的类似问题,但这似乎不同,因为当我将 toolchain.cmake 中的路径硬编码到 C 和 CXX 编译器时,它工作正常。我尝试过在 C 和 CXX 编译器指令周围加上引号,以及不加引号。

我也有兴趣了解为什么我的消息指令会打印这么多次!

谢谢

【问题讨论】:

I am also interested in learning why my message directives print out so many times! - 它似乎第三次在编译器检查期间打印。此检查实际上是一个(单独的)CMake 项目,它“继承”您的工具链......但不是传递给cmake 的其他定义。看起来使用 CMake 变量参数化工具链不是一个好主意:这些变量不会传递给子项目。顺便说一句,CMake 有一个用于 sysroot 的特殊变量:CMAKE_SYSROOT。 【参考方案1】:

CMake 正在进行测试构建,以确定编译器是否能够构建一个简单的应用程序(基本上只包含 main())。这可能由于多种原因而失败,例如编译器无法使用默认的 CMake 检测标志等。

您应该检查CMakeError.logCMakeOutput.log 以了解测试编译失败的原因。

要跳过编译器测试,不妨将以下内容放到工具链文件中:

set(CMAKE_C_COMPILER_WORKS 1)
set(CMAKE_CXX_COMPILER_WORKS 1)

这将跳过编译器测试,但是当您实际构建项目时,当然编译可能会失败。

【讨论】:

首先,我发现 CMAKE_C_COMPILER_WORKS 及其 CXX 等效项不起作用。我不得不使用-DCMAKE_C_COMPILER_FORCED=true。其次,跳过编译器测试没有意义,因为 cmake 内省可能会在后面的步骤中出错。有一些方法可以规避它,但它只是把一个面具放在一个问题的面具上【参考方案2】:

在这里查看我的回复:

https://intellij-support.jetbrains.com/hc/en-us/community/posts/207460115/comments/360002077699

基本上cmake在其系统自省时会通过try_compile命令生成一些文件(测试C/CXX文件、Makefiles甚至是一个新的CMake项目)然后默认删除。

如果您希望能够禁用删除这些生成的文件并调试您的问题,您可以在运行 cmake 时添加--debug_trycompile,您会在 root/cmake_build/CMakeFiles/CMakeTmp 中找到一些非常有用的信息

【讨论】:

以上是关于CMake传递的变量编译器无法编译简单的程序的主要内容,如果未能解决你的问题,请参考以下文章

如何阻止CMake将特定于平台的标志传递给编译器?

cmake msys2 mingw无法编译简单的测试程序

CMAKE 使用环境变量而不将它们作为命令行参数传递?

cmake - 如何为英特尔编译器设置不同的变量

使用 cmake 和 mingw-w64 错误编译测试程序

cmake交叉编译参数toolchain