这似乎是一个微不足道的问题,因为CMake是一种脚本语言,一般的答案是:严格顺序。但是我遇到了几个案例,其中重要的是CMake在何时或以何种顺序解析某些文件。所以我想知道:
到目前为止我遇到的案例,上述信息很重要:
CMakeLists.txt
文件外部的范围调用变量监视: 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
所以看到上面的输出,到目前为止,我得到了以下结论(我希望这是真的,有些通用):
project()
命令会触发大部分CMake的检测魔法(包括从Toolchain.txt
文件中读取)。CMakeSystem.cmake
。variable_watch()
挂钩可以随时触发,因此执行最佳"命令的范围是"被称为未定义。答案 0 :(得分:17)
没有关于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_LOADED
或CMAKE_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
强>
与&#34;初始缓存大致相同&#34;选项(见上文),但它不是通过命令行选项提供的。它只需与您的项目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)
然后你可以用{/ p>之类的东西来呼叫cmake
> cmake -D CMAKE_USER_MAKE_RULES_OVERRIDE:PATH=..\MakeRulesOverwrite.cmake ..
<强> CMAKE_PROJECT_ParserTest_INCLUDE
强>
这意味着&#34;将自定义代码注入到项目构建中,而无需修改其源代码&#34;在处理project()
命令之后直接执行(并检测到构建环境)。
在确定系统,编译器等时多次读取toolchain file
重要的是要知道:
每次try_compile()
电话都会阅读。因为try compile必须生成一个有效的可执行文件,所以你可能需要 - 如果你是交叉编译 - 到
CMAKE_TRY_COMPILE_TARGET_TYPE
至STATIC_LIBRARY
(CMake版本3.6或以上)IN_TRY_COMPILE
全局属性以添加其他选项如果更改工具链文件,CMake将重新触发编译器检测(如上面的跟踪)。这对您的编译器设置有很大帮助。
最后但并非最不重要的一点是,知道上面的跟踪只显示了初始步骤,这一点非常重要。所有连续项目配置几乎都包含缓存变量,因此在重新配置运行中将读取更少的文件。