提问者:小点点

参数化自定义CMake工具链


我正在编写用于交叉编译的CMake工具链文件。

我有几个工具链,差别很小。 我想为cmake创建一个描述所有工具链的文件,并让用户从命令行指定它们:cmake-dcmake_toolchain_file=/path/to/Toolchain.cmake-dtoolchain_name=

但是,似乎toolchain_name参数有时会变成空字符串。

下面是工具链文件的示例:

set(tools /opt/toolchains/Custom/toolchains/toolchain)
set(sdk   /opt/toolchains/Custom/platforms/)

message(STATUS "toolchain_name ${TOOLCHAIN_NAME}")
if(NOT TOOLCHAIN_NAME) 
    message(SEND_ERROR "Please specify toolchain name in -DTOOLCHAIN_NAME parameter")
endif()

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR ARM)

string(REPLACE "-" ";" toolchain_description ${TOOLCHAIN_NAME})
list(GET toolchain_description 0 t_proc)
list(GET toolchain_description 1 t_os)
list(GET toolchain_description 2 abi)

# further processing

然后我调用cmake:

mkdir build
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain.cmake -DTOOLCHAIN_NAME=proc-os-gnueabi-gcc_6_3

  

并获得以下错误:

-- toolchain name proc-os-gnueabi-gcc_6_3
-- toolchain name proc-os-gnueabi-gcc_6_3
-- The C compiler identification is GNU 6.3.1
-- The CXX compiler identification is GNU 6.3.1
-- Check for working C compiler: /opt/toolchains/.../bin/arm-os-gnueabi-gcc
CMake Error at /home/user/project/cmake/toolchain.cmake:59 (message):
  Please specify toolchain name in -DTOOLCHAIN_NAME parameter

Call Stack (most recent call first):
  /home/user/project/build/CMakeFiles/3.15.4/CMakeSystem.cmake:6 (include)
  /home/user/project/build/CMakeFiles/CMakeTmp/CMakeLists.txt:2 (project)


CMake Error at /usr/local/share/cmake-3.15/Modules/CMakeTestCCompiler.cmake:44 (try_compile):
  Failed to configure test project build system.
Call Stack (most recent call first):
  CMakeLists.txt:15 (project)


-- Configuring incomplete, errors occurred!
See also "/home/user/project/build/CMakeFiles/CMakeOutput.log".
See also "/home/user/project/build/CMakeFiles/CMakeError.log".

CMakeOutput.log和CMakeError.log包含消息,表示编译器没有找到某些库。

如果打开生成的文件/home/user/project/build/cmakefiles/3.15.4/cmakesystem.cmake,可以看到以下内容

set(CMAKE_HOST_SYSTEM "Linux-4.2.0-27-generic")
set(CMAKE_HOST_SYSTEM_NAME "Linux")
set(CMAKE_HOST_SYSTEM_VERSION "4.2.0-27-generic")
set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64")

include("/home/user/project/cmake/toolchain.cmake")

set(CMAKE_SYSTEM "Generic")
set(CMAKE_SYSTEM_NAME "Generic")
set(CMAKE_SYSTEM_VERSION "")
set(CMAKE_SYSTEM_PROCESSOR "ARM")

set(CMAKE_CROSSCOMPILING "TRUE")

set(CMAKE_SYSTEM_LOADED 1)

根据CMake手册,其-d参数用于指定缓存条目。

从上面的输出中我得出结论,所提供的工具链文件至少被CMake处理了3次。 前两次有正确的缓存条目,第三次运行时没有这些条目。

那么,如何避免工具链文件的代码重复呢?

UPD。 在阅读了这个问题之后,我尝试了几种CMake参数的排列:在toolchain之后但在options之前指定源路径,在options之后指定它,通过-s-b选项传递源路径和构建路径。 没有任何帮助


共1个答案

匿名用户

从上面的输出中我得出结论,所提供的工具链文件至少被CMake处理了3次。 前两次有正确的缓存条目,第三次运行时没有这些条目。

是的,这是很好的观察。 从技术上讲,只有在project()调用时的第一次工具链调用才能确保看到缓存条目(在cmake调用之前,使用-d参数或使用set()命令创建)。

在不同的工具链调用之间传递缓存条目的一种方法是将它们存储在环境变量中:

下面的示例使用my_toolchain_name环境变量作为toolchain_nameCMake变量的存储。

if(DEFINED ENV{MY_TOOLCHAIN_NAME})
    # Environment variable is set.
    if (TOOLCHAIN_NAME)
        # CMake variable is set too.
        # It is up to your which one to use.
        # Uncomment line below for prefer environment variable to CMake one.
        # set(TOOLCHAIN_NAME $ENV{MY_TOOLCHAIN_NAME})
    else ()
        # CMake variable is not set. Use environment one.
        set(TOOLCHAIN_NAME $ENV{MY_TOOLCHAIN_NAME})
    endif()
else()
    # Environment variable is not set.
    if (TOOLCHAIN_NAME)
        # But CMake variable is set.
        # Store it into the environment and use it.
        set(ENV{MY_TOOLCHAIN_NAME} ${TOOLCHAIN_NAME})
    else()
        # Neither environment nor CMake variable is set.
        message(SEND_ERROR "Please specify toolchain name in -DTOOLCHAIN_NAME parameter")
    endif()
endif()

如果你有几个“调优”变量,你可以为上面的所有步骤编写一个宏,并为你需要的每个变量应用(调用)这个宏。