CMake注意事项

使用CMake时,不熟悉的内容千万不要想当然,主观臆断保不齐就被“特性”坑了。

注意事项

判断环境变量或字符串的误区

参考官方文档《if()》一节:

A quoted string always evaluates to false unless:

  • The string’s value is one of the true constants, or
  • Policy CMP0054 is not set to NEW and the string’s value happens to be a variable name that is affected by CMP0054’s behavior.

带引号的字符串始终评估为 false ,除非:

  • 字符串的值是真正的常量之一,或者
  • 策略 CMP0054 未设置为 NEW,并且该字符串的值恰好是受 CMP0054 行为影响的变量名称。

首先,正如文档所提到,字符串始终被视为假,因此如果你需要判断一个环境变量已定义且非空,应该这么写:

1
if (DEFINED ENV{VAR} AND NOT "$ENV{VAR}" STREQUAL "")

在此情况下,ENV{VAR}是空字符串,$ENV{VAR}是设置的环境变量的值的字符串,都视为假

所以需要使用字符串的判断方法进行处理,即"$ENV{VAR}" STREQUAL ""

至于为什么要加引号,涉及到文档的例外情况CMP0054,我就不展开说明了,大意就是老版本cmake中存在一个特性:当if的判断参数和已存在的变量名相同时,会被展开作为字符串进行判断,而且这个展开是无限的,也即如果展开后依然和现有变量名相同则继续展开。

CMake 3.1版本引入新策略,即只会展开一次。具体情况参见《CMake compare to empty string with STREQUAL failed》。

使用CMAKE_TOOLCHAIN_FILE

参见《CMake ignore custom toolchain file.》中Tsyvarev的回答:

The variable CMAKE_TOOLCHAIN_FILE should be set before the first project() call:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
cmake_minimum_required(VERSION <..>)

# set up the Microchip cross toolchain
set(CMAKE_TOOLCHAIN_FILE ./external/cmake-microchip/toolchain.cmake)

project(Test)

# set the default MCU model
set(MICROCHIP_MCU PIC18F97J60)

add_executable(main main.c)

When first project() call is processed, CMake automatically calls the script specified in CMAKE_TOOLCHAIN_FILE.

Note, that preferred way is to not hardcode path to the toolchain in the CMakeLists.txt but pass -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain option to the cmake.

简单来说就是:

  • 工具链必须在调用project()之前进行设置
  • 首选方法是将-DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain选项传递给cmake

这里给出一个例子:

1
2
3
4
5
6
if (NOT DEFINED CMAKE_TOOLCHAIN_FILE)
    # 工具链必须在调用`project()`之前进行设置
    # 首选方法是将`-DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain`选项传递给`cmake`
    set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/toolchain/toolchain.cmake)
    message(STATUS "CMAKE_TOOLCHAIN_FILE not defined, using default value: " ${CMAKE_TOOLCHAIN_FILE})
endif ()

官方文档对CMAKE_TOOLCHAIN_FILE的解释:

This is initialized by the CMAKE_TOOLCHAIN_FILE environment variable if it is set when a new build tree is first created.

The CMAKE_TOOLCHAIN_FILE environment variable specifies a default value for the CMAKE_TOOLCHAIN_FILE variable when there is no explicit configuration given on the first run while creating a new build tree. On later runs in an existing build tree the value persists in the cache as CMAKE_TOOLCHAIN_FILE.

如果在首次创建新的构建树时设置了 CMAKE_TOOLCHAIN_FILE 环境变量,则会对其进行初始化。

当创建新的构建树时首次运行时没有给出显式配置时, CMAKE_TOOLCHAIN_FILE 环境变量会指定 CMAKE_TOOLCHAIN_FILE 变量的默认值。稍后在现有构建树中运行时,该值将在缓存中保留为 CMAKE_TOOLCHAIN_FILE

引用