CMake:文件的解析顺序(缓存、工具链等)?

CMake:文件的解析顺序(缓存、工具链等)?,cmake,Cmake,这似乎是一个无关紧要的问题,因为CMake是一种脚本语言,一般的答案是:严格顺序。但我遇到了几个案例,其中CMake解析某些文件的时间或顺序非常重要。所以我想知道: 是否有文档描述了使用的顺序 是否解析文件(包括内部CMake文件) 文件顺序是否取决于CMake版本或某些CMake选项/设置/环境(包括所选的生成器或主机) 环境 到目前为止,我遇到的案例中,上述信息非常重要: 在识别编译器之前会解析工具链文件,因此必须首先在缓存中/在工具链文件中填充某些CMake变量: 工具链文件会被多次解析

这似乎是一个无关紧要的问题,因为CMake是一种脚本语言,一般的答案是:严格顺序。但我遇到了几个案例,其中CMake解析某些文件的时间或顺序非常重要。所以我想知道:

  • 是否有文档描述了使用的顺序 是否解析文件(包括内部CMake文件)
  • 文件顺序是否取决于CMake版本或某些CMake选项/设置/环境(包括所选的生成器或主机) 环境
  • 到目前为止,我遇到的案例中,上述信息非常重要:

    • 在识别编译器之前会解析工具链文件,因此必须首先在缓存中/在工具链文件中填充某些CMake变量:
    • 工具链文件会被多次解析,因此,例如,打印工具链文件中的消息会多次显示:
    • 可以从主
      CMakeLists.txt
      文件已解析的范围之外的范围调用变量watch:
    也许你知道的更多

    为了找到答案,我尝试了以下方法:我设置了一个简单的main CMakeLists.txt,如下所示,并运行
    cmake--trace…
    来分析解析顺序

    cmake_minimum_required(VERSION 2.8)
    
    include(BeforeProjectCmd.cmake)
    
    project(ParserTest CXX)
    
    add_subdirectory(LibTarget1)
    add_subdirectory(LibTarget2)
    
    add_executable(ExeTarget Test.cpp)
    
    variable_watch(CMAKE_BACKWARDS_COMPATIBILITY)
    
    然后,当我运行例如
    cmake--debug output--trace-g“Visual Studio 12 2013”-DCMAKE_TOOLCHAIN_FILE:FILE_PATH=TOOLCHAIN.txt时,我得到了一个很长的跟踪,我试图对其进行总结:

    # Begin try to read
    CMakeCache.txt
    ${CMAKE_BINARY_DIR}/CMakeCache.txt
    PreLoad.cmake
    ${CMAKE_BINARY_DIR}/PreLoad.cmake
    # End try to read
    
    ┌ CMakeLists.txt(1):  cmake_minimum_required(VERSION 2.8 )
    │ CMakeLists.txt(3):  include(BeforeProjectCmd.cmake )
    │
    ├─ BeforeProjectCmd.cmake
    │
    │ CMakeLists.txt(5):  project(ParserTest CXX )
    ├┬ share/cmake-3.2/Modules/CMakeDetermineSystem.cmake
    ││
    │└─ Toolchain.txt
    │
    ├┬ ${CMAKE_PLATFORM_INFO_DIR}/CMakeSystem.cmake
    ││
    │└─ Toolchain.txt
    │
    ├─ share/cmake-3.2/Modules/CMakeSystemSpecificInitialize.cmake
    ├┬ share/cmake-3.2/Modules/CMakeDetermineCXXCompiler.cmake
    │├┬ share/cmake-3.2/Modules/CMakeDetermineCompiler.cmake
    ││├ share/cmake-3.2/Modules/Platform/Windows-CXX.cmake
    …
    ││├ share/cmake-3.2/Modules/CMakeDetermineCompilerId.cmake
    ││├─ share/cmake-3.2/Modules/CMakeCompilerIdDetection.cmake
    …
    ││├ share/cmake-3.2/Modules/Compiler/MSVC-DetermineCompiler.cmake
    …
    │├ ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/3.2.2/CMakeCXXCompiler.cmake
    │├ share/cmake-3.2/Modules/CMakeSystemSpecificInformation.cmake
    │├┬ share/cmake-3.2/Modules/CMakeGenericSystem.cmake
    ││├ share/cmake-3.2/Modules/Platform/Windows.cmake
    ││└─ share/cmake-3.2/Modules/Platform/WindowsPaths.cmake
    │├ share/cmake-3.2/Modules/CMakeCXXInformation.cmake
    │├┬ share/cmake-3.2/Modules/Compiler/MSVC-CXX.cmake
    ││├ share/cmake-3.2/Modules/Platform/Windows-MSVC-CXX.cmake
    ││├┬ share/cmake-3.2/Modules/Platform/Windows-MSVC.cmake
    │││└─ share/cmake-3.2/Modules/CMakeRCInformation.cmake
    ││└ share/cmake-3.2/Modules/CMakeCommonLanguageInclude.cmake
    │├ share/cmake-3.2/Modules/CMakeTestCXXCompiler.cmake
    │├┬ share/cmake-3.2/Modules/CMakeTestCompilerCommon.cmake
    ││├ share/cmake-3.2/Modules/CMakeDetermineCompilerABI.cmake
    ││├ share/cmake-3.2/Modules/CMakeDetermineCompileFeatures.cmake
    ││├ share/cmake-3.2/Modules/Internal/FeatureTesting.cmake
    ││└ share/cmake-3.2/Modules/Compiler/MSVC-CXX-FeatureTests.cmake
    │└ ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/3.2.2/CMakeCXXCompiler.cmake
    │
    │ CMakeLists.txt(7):  add_subdirectory(LibTarget1 )
    │
    ├─ LibTarget1/CMakeLists.txt
    │
    │ CMakeLists.txt(8):  add_subdirectory(LibTarget2 )
    │
    ├─ LibTarget2/CMakeLists.txt
    │
    │ CMakeLists.txt(10):  add_executable(ExeTarget Test.cpp )
    │ CMakeLists.txt(12):  variable_watch(CMAKE_BACKWARDS_COMPATIBILITY )
    │
    │  CMake Debug Log in CMakeLists.txt:
    │  Variable "CMAKE_BACKWARDS_COMPATIBILITY" was accessed using UNKNOWN_READ_ACCESS with value "".
    
    -- Configuring done
    -- Generating ${CMAKE_BINARY_DIR}
    -- Generating ${CMAKE_BINARY_DIR}/LibTarget1
    -- Generating ${CMAKE_BINARY_DIR}/LibTarget2
    -- Generating done
    
    # Writes
    ${CMAKE_BINARY_DIR}/CMakeCache.txt
    
    因此,看到上述结果,到目前为止,我得出了以下结论(我希望这些结论是正确的,并且有些通用):

  • CMAKECHACHE.txt文件仅在配置启动时读取一次,并在生成完成后写入。它只是保持“全局变量”缓存的状态
  • project()
  • 工具链文件将被读取两次。一次在检测到生成/编译系统之前,一次在随后生成的
    CMakeSystem.cmake
  • 变量_watch()
    钩子可以随时触发,因此调用最佳“要执行的命令”的范围未定义
  • 目前还没有关于CMake这个特殊内部工作的官方文档,所以请在下面找到我到目前为止对CMake的了解的摘要

    解析哪些文件取决于

  • 主机和目标操作系统
  • 目标编译器
  • 主机的环境(变量、注册表、已安装的软件)
  • 项目的CMake脚本文件,其中可能包括
  • 你的工具链文件
  • 您选择的编程语言
  • 任何外部项目/库/文件/脚本
  • 这些参数有很多可能的组合,但大多数情况下,CMake会自动为您检测正确的设置,而您不需要担心如何完成。好消息是——当你需要知道的时候——它遵循某些固有的模式

    有趣的是,它只在一定程度上取决于您选择的对象

    初始步骤:编译器检测和验证 这主要从命令开始。以
    CXX
    语言为例,编译器检测的主要文件有(另请参见问题跟踪输出中的根文件):

    • share/cmake-x.y/Modules/CMakeDetermineCXXCompiler.cmake

      这基本上是试图确定编译器可执行文件的位置,并调用它以获得更具体的编译器id

      此外,它还定义了基于主机环境和目标操作系统的源/输出文件扩展名

    • share/cmake-x.y/Modules/cmakecxcompiler.cmake.in

      这是将编译器检测结果存储在
      ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/x.y.z/cmakecxcompiler.CMAKE
      中的模板

      这些变量主要是:,和
      CMAKE\u CXX\u COMPILER\u ENV\u VAR

    • share/cmake-x.y/Modules/CMakeCXXInformation.cmake

      此文件设置编译器的基本标志。这也是编译器、主机和目标对设置影响最大的地方,调用如下:

      include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CXX_COMPILER_ID}-CXX-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
      include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CXX_COMPILER_ID}-CXX OPTIONAL)
      include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL)
      include(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL)        
      
    • 共享/cmake-x.y/Modules/cmaketestcxcompiler.cmake

      这会测试所有内容,例如,通过在简单生成的CMake项目中实际调用编译器来确定编译器功能

    这些步骤的结果存储在缓存的变量中,这些文件是特殊的,在这种情况下,它们由变量保护,例如,
    CMAKE\u CXX\u INFORMATION\u LOADED
    CMAKE\u CXX\u COMPILER\u工作
    以避免在每个连续的CMAKE配置步骤中再次运行

    项目配置文件:修改默认值 有几种方法可以更改CMake默认值,而无需实际接触项目的
    CMakeLists.txt
    文件

    • 命令行选项

      如果您想通过多个项目反复给出一些预设值(通常通过
      -D…
      选项给出),可以使用此选项。例如计算机上的某些库搜索路径或公司中使用的某些预设

    • cmakcache.txt
      通过例如

      cmakegui
      允许您在最终生成生成环境之前手动修改项目的选项(在
      CMakeCache.txt
      中编辑所有非内部变量)

    • 主要用于,但它可以更一般地描述为每个编译器工具链使用的预设值

    • 预加载.cmake

      与“初始缓存”选项(见上文)大致相同,但它是n
      list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS c)
      
      > cmake -D CMAKE_USER_MAKE_RULES_OVERRIDE:PATH=..\MakeRulesOverwrite.cmake ..