参数化自定义CMake工具链 [英] Parameterizing custom CMake toolchain

查看:107
本文介绍了参数化自定义CMake工具链的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写CMake工具链文件以进行交叉编译.

I'm writing CMake toolchain files for cross-compilation.

我有几个工具链,它们之间的差别很小.我想为cmake创建一个描述所有工具链的文件,并让用户从命令行指定它们: cmake -DCMAKE_TOOLCHAIN_FILE =/path/to/toolchain.cmake -DTOOLCHAIN_NAME =< name>

I've got several toolchains, that differ very slightly. I'd like to create a single file for cmake that describes all toolchains and have users to specify them from command line: cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain.cmake -DTOOLCHAIN_NAME=<name>

但是,似乎 TOOLCHAIN_NAME 有时会变成一个空字符串.

However, it seems that TOOLCHAIN_NAME sometimes becomes an empty string.

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

Here is the example of the toolchain file:

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)

# further processing

那我叫CMake:

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

并获得以下带有错误的输出:

And get following output with errors:

-- 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包含消息,说明编译器未找到某些库.

CMakeOutput.log and CMakeError.log contain messages, saying that the compiler didn't find some libraries.

如果我打开生成的文件/home/user/project/build/CMakeFiles/3.15.4/CMakeSystem.cmake ,我会看到以下内容

If I open generated file /home/user/project/build/CMakeFiles/3.15.4/CMakeSystem.cmake I can see the following

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 参数用于指定缓存条目.

According to CMake manual, its -D argument is used to specify cache entries.

从上面的输出中可以得出结论,CMake至少处理了所提供的工具链文件3次.在前两次中,有适当的缓存条目,而在第三次运行中,它们不存在.

I conclude from the output above that supplied toolchain file is processed by CMake at least 3 times. During first two times there were proper cache entries, and at the third run they were absent.

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

So, how can I avoid code duplication for toolchain files?

UPD.阅读这个问题后,我尝试了CMake命令行参数的几种排列方式:在工具链之后但在选项之前指定源路径,指定在选项之后,使用 -S -B 选项显式指定源路径和构建路径.没有任何帮助.

UPD. After reading this question I've tried several permutations of CMake command line parameters: specifying source path after toolchain but before options, specifying it after options, explicitly specifying source path and build path with -S and -B options. Nothing has helped.

推荐答案

从上面的输出中可以得出结论,CMake至少处理了所提供的工具链文件3次.前两次有适当的缓存条目,而在第三次运行中则不存在.

I conclude from the output above that supplied toolchain file is processed by CMake at least 3 times. First two times there were proper cache entries, and at the third run they were absent.

是的,这是非常好的观察.从技术上讲,只有在 project()调用中进行的第一次工具链调用才能保证看到CACHE条目(使用 cmake -D 参数创建或在 project()调用之前使用 set()命令).

Yes, this is very good observation. Technically, only the first toolchain invocation at the project() call is guarantee to see the CACHE entries (created with -D parameters to cmake or with set() commands prior to the project() call).

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

One approach for pass CACHE entries between the different toolchain invocations is storing them in the environment variables:

下面的示例使用 MY_TOOLCHAIN_NAME 环境变量作为 TOOLCHAIN_NAME CMake变量的存储.

Example below uses MY_TOOLCHAIN_NAME environment variable as a storage for TOOLCHAIN_NAME CMake variable.

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()

如果您有多个调整"项,变量,您可以为上述所有步骤编写一个宏,然后为所需的每个变量应用(调用)该宏.

If you have several "tuning" variables, you may write a macro for all above steps and apply(call) this macro for every variable you need.

这篇关于参数化自定义CMake工具链的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆