我对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'。我错了吗?
答案 0 :(得分:5)
基本规则很简单:add_subdirectory
建立新的范围,include
不会。因此,您的示例只涉及两个范围:
set(...)
和MyCMake
中的MyCMake2
命令以及set(... PARENT_SCOPE)
内child/CMakeLists.txt
命令的影响}。child/CMakeLists.txt
的范围,受set(...)
child/CMakeLists.txt
内PARENT_SCOPE
命令的影响而不使用PARENT_SCOPE
。 set
仅设置父作用域中的值是正确的。如果要为当前作用域和父作用域设置值,则必须发出两个值set(var Value)
set(var Value PARENT_SCOPE)
命令:
add_library(L STATIC ...)
add_library(A SHARED ...)
add_executable(A ...)
target_link_libraries(A L)
我们通常更喜欢Stack Overflow上的每个问题一个问题,但我也会回答目标命名问题:CMake目标名称是CMake目标的逻辑名称,它们必须是唯一的。想象一下,如果不是这样的话:
A
最后一行会有什么影响?库L
会链接到A
,还是可执行文件datediff()
会这样做?或两者? Dtto用于设置属性等。
您可以独立于目标名称控制生成的二进制文件的名称:有关详细信息,请参阅目标属性,如OUTPUT_NAME
。