Skip to content

CMake 学习笔记

参考文档

参考官方Cmake Tutorial cmake-examples Cmake中文实战教程

A Basic Starting Point

本章介绍了Cmake的基本使用,包括一系列基本命令:

  • cmake_minimum_required(VERSION 3.10)
  • project(Tutorial VERSION 1.0)
  • set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True)
  • configure_file(TutorialConfig.h.in TutorialConfig.h)
  • add_executable(Tutorial tutorial.cxx)
  • cmake target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/MathFunctions" )

Adding a Library

本章介绍了CMakeLists.txt如何添加一个库,以及添加编译选项来开启库的编译,主要命令包括:

  • add_library(MathFunctions MathFunctions.cxx)
  • add_subdirectory(MathFunctions)
  • target_include_directories()
  • target_link_libraries(Tutorial PUBLIC MathFunctions)
  • PROJECT_SOURCE_DIR
  • if()
  • option(USE_MYMATH "Use tutorial provided math implementation" ON)
  • target_compile_definitions()
  • cmake if(USE_MYMATH) target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") add_library(SqrtLibrary static mysqrt.cxx) target_link_libraries(MathFunctions PRIVATE SqrtLibrary) endif()

Adding Usage Requirements for a Library

本章介绍了现代CMake方法,并给库添加个人的使用要求(控制库或可执行文件的连接和包含),主要命令包括:

  • CMAKE_CURRENT_SOURCE_DIR
  • target_compile_definitions()
  • target_compile_options()
  • target_include_directories()
  • target_link_directories()
  • target_link_options()
  • target_precompile_headers()
  • target_sources()
  • PUBLIC PRIVATE INTERFACE: 三者之间有一定的区别。 + PUBLIC: 当库A以PUBLIC方式链接到库B时,库A使用库B的接口,并且库A的接口也会使用库B的接口。这意味着链接到库A的目标(库或可执行文件)也会自动链接到库B,并且库B的接口属性(如头文件路径、宏定义等)也会传递给这些目标。 + PRIVATE: 当库A以PRIVATE方式链接到库B时,库A使用库B的接口,但库A的接口不使用库B的接口。这意味着链接到库A的目标不会自动链接到库B,且库B的接口属性不会传递给这些目标。PRIVATE链接适用于库B仅在库A的内部实现中使用,而不通过库A的接口暴露给其他目标的情况。 + INTERFACE: 当你设置一个目标的INTERFACE属性时,这些属性不会应用于该目标本身,而只会应用于链接了该目标的其他目标

Adding Generator Expressions

本章介绍了生成表达式,生成表达式用于在编译期间生成信息,包括逻辑,信息和输出表达式,通常用于有条件的添加编译器编译选项:

  • cmake-generator-expressions(7)
  • cmake_minimum_required()
  • set()
  • target_compile_options()

Installing and Testing

本章介绍了CMake支持的本地安装规则,一般需要指定/libinclude目录的安装, 以及CTest的测试框架和测试函数的编写。

编译完成后,在build目录下运行cmake -VV或者cmake -C可以进行CTest并看到测试结果

  • install()
  • TARGETS FILES
  • DESTIANTION
  • cmake if (TARGET SqrtLibrary) list(APPEND installable_libs SqrtLibrary) endif()
  • enable_testing()
  • add_test()
  • function()
  • set_tests_properties()
  • ctest
  • cmake function(do_test target arg result) add_test(NAME Test_${arg} COMMAND ${target} ${arg}) set_tests_properties(Test_${arg} PROPERTIES PASS_REGULAR_EXPRESSION ${result} ) endfunction()

Adding System Introspection

本章为CMakeLists.txt添加系统自检,根据目标平台是否具有某些特性来添加代码更改实现

  • CheckCXXSourceCompiles
  • target_compile_definitions()
  • check_cxx_compile_source()
  • cpp #if defined(HAVE_LOG) and defined(HAVE_EXP) // TODO 5: If both HAVE_LOG and HAVE_EXP are defined, use the following: double result = std::exp(std::log(x) * 0.5); std::cout << "Computing sqrt of " << x << " to be " << result << " using log and exp" << std::endl; // else, use the existing logic. #else double result = x; #endif

Packaging an Installer

添加以下到CMakeLists.txt中,之后就可以调用cpack命令打包安装程序

    include(InstallRequiredSystemLibraries)
    set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
    set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
    set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
    set(CPACK_GENERATOR "TGZ")
    set(CPACK_SOURCE_GENERATOR "TGZ")
    include(CPack)

打包命令: + cpack + cpack -G ZIP -C Debug: 指定二进制生成器和多配置构建 + cpack --config CPackSourceConfig.cmake: 创建完整源代码树的文档

Selecting Static or Shared Libraries

  • set_target_properties
  • option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
  • message
  • cmake if(CMAKE_BUILD_TYPE STREQUAL "Debug") # 设置Debug模式的特定编译器标志 message(STATUS "Configuring for Debug mode") add_compile_definitions(MyExecutable PRIVATE DEBUG_MODE=1) target_compile_options(MyExecutable PRIVATE -g) elseif(CMAKE_BUILD_TYPE STREQUAL "Release") # 设置Release模式的特定编译器标志 message(STATUS "Configuring for Release mode") add_compile_definitions(MyExecutable PRIVATE RELEASE_MODE=1) target_compile_options(MyExecutable PRIVATE -O3) endif()