CMake 中一些有用的模组

在 CMake 的 modules 集合了很多有用的模组,但是有一些模块相比于其他的更有用。以下是一些比较出彩的:

CMakeDependentOption

这增加了命令 cmake_dependent_option ,它根据另外一组变量是否为真来(决定是否)开启一个选项。下面是一个例子:

  1. include(CMakeDependentOption)
  2. cmake_dependent_option(BUILD_TESTS "Build your tests" ON "VAL1;VAL2" OFF)

如上代码是下面的一个缩写:

  1. if(VAL1 AND VAL2)
  2. set(BUILD_TESTS_DEFAULT ON)
  3. else()
  4. set(BUILD_TESTS_DEFAULT OFF)
  5. endif()
  6. option(BUILD_TESTS "Build your tests" ${BUILD_TESTS_DEFAULT})
  7. if(NOT BUILD_TESTS_DEFAULT)
  8. mark_as_advanced(BUILD_TESTS)
  9. endif()

需要注意的是,如果你使用了 include(CTest) ,用 BUILD_TESTING 来检测是否启用是更好的方式,因为它就是为此功能而生的。这里只是一个 CMakeDependentOption 的例子。

CMakePrintHelpers

这个模块包含了几个方便的输出函数。cmake_print_properties 可以让你轻松的打印属性,而 cmake_print_variables 将打印出你给它任意变量的名称和值。

CheckCXXCompilerFlag

这个模块允许你检查编译器是否支持某个标志,例如:

  1. include(CheckCXXCompilerFlag)
  2. check_cxx_compiler_flag(-someflag OUTPUT_VARIABLE)

需要注意的是 OUTPUT_VARIABLE 也会出现在打印的配置输出中,所以请选个不错的变量名。

这只是许多类似模块中的一个,例如 CheckIncludeFileCXXCheckStructHasMemberTestBigEndian 以及CheckTypeSize,它们允许你检查系统的信息(并且你可以在代码中使用这些信息)。

try_compile/try_run

准确的说,这不是一个模块,但是它们对上述列出的许多模块至关重要。通过它你可以在配置时尝试编译(也可能是运行)一部分代码。这可以让你在配置时获取关于系统能力的信息。基本的语法如下:

  1. try_compile(
  2. RESULT_VAR
  3. bindir
  4. SOURCES
  5. source.cpp
  6. )

这里有很多可以添加的选项,例如 COMPILE_DEFINITIONS。在 CMake 3.8+ 中, 这将默认遵循 CMake 中 C/C++/CUDA 的标准设置。如果你使用的是 try_run 而不是 try_compile,它将运行生成的程序并将运行结果存储在 RUN_OUTPUT_VARIABLE 中。

FeatureSummary

这是一个十分有用但是也有些奇怪的模块。它能够让你打印出找到的所有软件包以及你明确设定的所有选项。它和 find_package 有一些联系。像其他模块一样,你首先要包括模块:

  1. include(FeatureSummary)

然后,对于任何你已经运行或者将要运行的 find_package ,你可以这样拓展它的默认信息:

  1. set_package_properties(OpenMP PROPERTIES
  2. URL "http://www.openmp.org"
  3. DESCRIPTION "Parallel compiler directives"
  4. PURPOSE "This is what it does in my package")

你也可以将包的 TYPE 设置为 RUNTIMEOPTIONALRECOMMENDED 或者 REQUIRED。但是你不能降低包的类型,如果你已经通过 find_package 添加了一个 REQUIRED 类型的包,你将会看到你不能改变它的 TYPE

并且,你可以添加任何选项让其成为 feature summary 的一部分。如果你添加的选项名与包的名字一样,他们之间会互相产生影响:

  1. add_feature_info(WITH_OPENMP OpenMP_CXX_FOUND "OpenMP (Thread safe FCNs only)")

然后,你可以将所有特性 (features) 的集合打印到屏幕或日志文件中:

  1. if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
  2. feature_summary(WHAT ENABLED_FEATURES DISABLED_FEATURES PACKAGES_FOUND)
  3. feature_summary(FILENAME ${CMAKE_CURRENT_BINARY_DIR}/features.log WHAT ALL)
  4. endif()

你可以建立一个 WHAT 目标来集合任何你想查看的特性 (features),或者直接使用 ALL 目标也行。