CMake范围规则

时间:2015-12-22 14:41:41

标签: cmake

我对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'。我错了吗?

1 个答案:

答案 0 :(得分:5)

基本规则很简单:add_subdirectory建立新的范围,include不会因此,您的示例只涉及两个范围:

  • 顶级CMakeList的范围受set(...)MyCMake中的MyCMake2命令以及set(... PARENT_SCOPE)child/CMakeLists.txt命令的影响}。
  • 子级CMakeList child/CMakeLists.txt的范围,受set(...) child/CMakeLists.txtPARENT_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

相关问题