gpt4 book ai didi

cmake - CMake:文件解析顺序(缓存,工具链等)是什么?

转载 作者:行者123 更新时间:2023-12-03 10:42:54 27 4
gpt4 key购买 nike

这似乎是一个琐碎的问题,因为CMake是一种脚本语言,通常的答案是:严格顺序执行。但是我遇到了几种情况,在什么情况下CMake解析特定文件的时间或顺序很重要。所以我想知道:

  • 是否有可用的文档来描述其中的顺序
    文件(包括内部CMake文件)是否已解析?
  • 是文件顺序,取决于CMake版本或某些CMake选项/设置/环境(包括)。选择的发电机或主机
    环境?

  • 到目前为止,我所遇到的案例很重要,上述信息很重要:
  • 在识别编译器之前已对工具链文件进行了解析,因此您必须首先在工具链文件中/在工具链文件中填充某些CMake变量:CMake cross-compile with specific linker doesn't pass arguments to armlink
  • 该工具链文件被多次分析,因此例如来自工具链文件的打印消息显示多次:CMake toolchain includes multiple files
  • 可以从已解析主CMakeLists.txt文件之外的范围调用一个变量watch:Execute command or macro in CMake as the last step before the 'configure' step finishes

  • 也许您知道更多。

    为了找到答案,我尝试了以下操作:我已经设置了一个简单的主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

    因此,到目前为止,看到以上输出,我得出了以下结论(我希望这是正确的,并且有些通用):
  • 启动配置时仅读取一次CMakeCache.txt文件,并在生成完成后写入。它只是保留“全局变量”缓存的状态。
  • project()命令触发CMake的大多数检测魔术(包括从Toolchain.txt文件读取)。
  • 工具链文件被读取两次。一次在检测到make / compile系统之前,一次在随后生成的CMakeSystem.cmake中。
  • variable_watch()挂钩可以随时触发,因此未定义最佳“执行命令”的作用域。
  • 最佳答案

    没有有关CMake的特定内部工作原理的官方文档,因此,请在下面找到我到目前为止所学到的有关CMake的摘要...

    解析哪些文件取决于

  • 主机和目标操作系统
  • 目标编译器
  • 您的主机环境(变量,注册表,安装的软件)
  • 您项目的CMake脚本文件,其中可能包括
  • 您的工具链文件
  • 您选择的编程语言
  • 任何外部项目/库/文件/脚本

  • 这些参数有很多可能的组合,但是大多数时候CMake都会自动为您检测正确的设置,而您无需理会它的完成方式。好消息是-当您需要知道时-它遵循某些固有模式。

    有趣的是,它仅在一定程度上取决于您选择的 CMake generator

    初始步骤:编译器检测和验证

    这主要从 project() 命令开始。以 CXX语言为例,用于编译器检测的主要文件为(另请参阅问题的跟踪输出中的根文件):
  • share/cmake-x.y/Modules/CMakeDetermineCXXCompiler.cmake

    这基本上是尝试确定编译器可执行文件的位置,并调用它来获取更具体的编译器ID。

    此外它例如根据主机环境和目标操作系统定义源/输出文件扩展名。
  • share/cmake-x.y/Modules/CMakeCXXCompiler.cmake.in

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

    这些变量主要是: CMAKE_CXX_COMPILER CMAKE_CXX_SOURCE_FILE_EXTENSIONS CMAKE_CXX_IGNORE_EXTENSIONS CMAKE_CXX_COMPILER_ENV_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)
  • share/cmake-x.y/Modules/CMakeTestCXXCompiler.cmake

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

  • 这些步骤的结果存储在缓存的变量中,并且这些文件很特殊,在这种情况下,它们由 CMAKE_CXX_COMPILER_LOADED CMAKE_CXX_INFORMATION_LOADEDCMAKE_CXX_COMPILER_WORKS这样的变量保护,不会再与每个连续的CMake配置步骤一起运行。

    项目配置文件:修改默认值

    您可以通过多种方法来更改CMake默认值,而无需实际触摸项目的 CMakeLists.txt文件。
  • -C <initial-cache> 命令行选项

    如果要通过几个项目反复给出一些预设值(通常通过-D ...选项给出),可以使用此方法。例如计算机上的某些库搜索路径或公司中使用的某些预设。
  • CMakeCache.txt ,例如 cmake-gui

    在最终生成构建环境之前,cmake-gui允许您手动修改项目的选项(编辑CMakeCache.txt中的所有非内部变量)。
  • CMAKE_TOOLCHAIN_FILE

    主要用于cross-compiling,但更笼统地可以描述为每个使用的编译器工具链的预设值。
  • PreLoad.cmake

    与“初始缓存”选项(请参见上文)大致相同,但不是通过命令行选项给出的。它必须与项目的CMakeLists.txt位于同一目录中。

    注意:它支持所有CMake脚本命令,例如 if() 调用,但是PreLoad.cmake具有其功能
  • 自己的变量范围(在主CMakeLists.txt中不可见所有未缓存的内容)
  • 限制已知的限制(它先于其他所有功能运行,因此大多数情况下您可以检查 CMAKE_GENERATOR )
  • CMAKE_USER_MAKE_RULES_OVERRIDE CMAKE_USER_MAKE_RULES_OVERRIDE_<LANG>

    这允许在CMake自动检测后修改非缓存的默认值。

    Example:通过.c文件扩展有效的CXX源文件扩展名

    MakeRulesOverwrite.cmake
    list(APPEND CMAKE_CXX_SOURCE_FILE_EXTENSIONS c)

    然后,您可以使用以下内容调用cmake
    > cmake -D CMAKE_USER_MAKE_RULES_OVERRIDE:PATH=..\MakeRulesOverwrite.cmake ..
  • CMAKE_PROJECT_ParserTest_INCLUDE

    这意味着在处理完project()命令(检测到构建环境)后,立即将“自定义代码注入(inject)到项目构建中,而无需修改其源代码”。

  • Toolchain.cmake:多次分析

    在确定系统,编译器等时,会多次读取 toolchain file

    重要的是要知道:
  • 每次 try_compile() 调用都会读取它。而且由于try编译必须产生有效的可执行文件,因此您可能需要-如果您是交叉编译-至
  • CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY(CMake版本3.6或更高版本)
  • 检查 IN_TRY_COMPILE 全局属性以添加其他选项
  • 如果更改工具链文件,则CMake将重新触发编译器检测(如上面的跟踪所示)。这极大地有助于您使用编译器设置。

  • CMake重新配置:一切都来自缓存

    最后但并非最不重要的一点是,重要的是要知道上面的跟踪仅显示了初始步骤。所有连续的项目配置将几乎从缓存的变量中获取所有内容,因此在重新配置运行中将读取更少的文件。

    引用文献
  • The Architecture of Open Source Applications: CMake
  • Generic rule from makefile to CMake
  • CMake error at CMakeLists.txt:30 (project): No CMAKE_C_COMPILER could be found
  • 关于cmake - CMake:文件解析顺序(缓存,工具链等)是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30503631/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com