关于cmake的范围规则,我有点困惑.我有文件和目录,如
??? test ? CMakeLists.txt ? ??? cmake ? ? MyCMake ? ? MyCMake2 ? ??? child ? ? CMakeLists.txt
内容如下:
cmake的/ MyCMake:
set(MY_NAME MyName) message("MyCMake: " ${MY_NAME} " " ${YOUR_NAME} " " ${HIS_NAME})
cmake的/ MyCMake2:
set(HIS_NAME NewName) message("MyCMake2: " ${MY_NAME} " " ${YOUR_NAME} " " ${HIS_NAME})
子/的CMakeLists.txt:
set(YOUR_NAME YourName) set(HIS_NAME HisName PARENT_SCOPE) message("Child: " ${MY_NAME} " " ${YOUR_NAME} " " ${HIS_NAME})
测试/的CMakeLists.txt:
cmake_minimum_required(VERSION 2.8) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) include(MyCMake) add_subdirectory(child) message("Parent1: " ${MY_NAME} " " ${YOUR_NAME} " " ${HIS_NAME}) include(MyCMake2) message("Parent2: " ${MY_NAME} " " ${YOUR_NAME} " " ${HIS_NAME})
结果是
MyCMake: MyName Child: MyName YourName Parent1: MyName HisName MyCMake2: MyName NewName Parent2: MyName NewName
第一行是OK,第二和第三个变量尚未定义.对于第二行,它看起来像是仅父项设置,即定义的变量仅在父项中具有范围.(那么,我可以/应该使用本地范围的相同变量吗?)第三行仅显示具有父范围的变量,OK.第4行显示我设置了LOCAL范围变量.但是,在第5行中,我看到PARENT范围值已更改,我希望仅在本地更改子子目录中.这里发生了什么?(看起来我可以覆盖变量的值,这不在我的范围内)
为什么我开始尝试:在某些情况下,我没有在父目录中看到子目录中定义的变量(如include目录,库名等).是否有一种标准方法可以使用一个库名来构建一个子节点,并在另一个子节点中使用相同的名称进行链接?
还有一个问题:我有一个应用程序,包括一个库和一个可执行文件.看起来CMake不允许为两者使用相同的目标名称.在我看来,如果我使用名称'A'作为二进制目标和库目标,它不应该导致混淆,因为真正的第二个目标是'libA'.我错了吗?
基本规则很简单:add_subdirectory
建立一个新范围,include
但不是.所以你的例子只涉及两个范围:
顶层CMakeList,其通过受影响的范围set(...)
中的命令MyCMake
和MyCMake2
,并通过set(... PARENT_SCOPE)
内部命令child/CMakeLists.txt
.
子CMakeList的范围,child/CMakeLists.txt
受其中不使用的set(...)
命令的影响.child/CMakeLists.txt
PARENT_SCOPE
您是正确的,仅PARENT_SCOPE
在父作用域中设置值.如果要为当前作用域和父作用域设置值,则必须发出两个set
命令:
set(var Value) set(var Value PARENT_SCOPE)
我们通常在Stack Overflow上更喜欢每个问题一个问题,但我也会回答目标命名问题:CMake目标名称是CMake目标的逻辑名称,它们必须是唯一的.想象一下,如果不是这样的话:
add_library(L STATIC ...) add_library(A SHARED ...) add_executable(A ...) target_link_libraries(A L)
最后一行会有什么影响?库会A
链接L
,还是可执行文件A
会这样做?或两者?Dtto用于设置属性等.
您可以独立于目标名称控制生成的二进制文件的名称:OUTPUT_NAME
有关详细信息,请参阅目标属性.