CMake范围规则

CMake范围规则,cmake,Cmake,我对cmake的范围规则有点困惑。 我有像这样的文件和目录 ├── test │ CMakeLists.txt │   ├── cmake │   │   MyCMake │   │   MyCMake2 │   ├── child │   │   CMakeLists.txt 内容包括: cmake/MyCMake: set(MY_NAME MyName) message("MyCMake: " ${MY_NAME} " " ${YOUR_

我对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})
child/CMakeLists.txt:

set(YOUR_NAME YourName)
set(HIS_NAME HisName PARENT_SCOPE)
message("Child: " ${MY_NAME} " " ${YOUR_NAME} " " ${HIS_NAME})
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})
test/CMakeLists.txt:

set(YOUR_NAME YourName)
set(HIS_NAME HisName PARENT_SCOPE)
message("Child: " ${MY_NAME} " " ${YOUR_NAME} " " ${HIS_NAME})
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。第四行显示我设置了一个局部范围变量。但是,在第5行中,我看到父作用域的值已经更改,我希望在子目录中只在本地更改。 这是怎么回事?(看起来我可以覆盖不在我作用域内的变量值)

为什么我开始实验:在某些情况下,我在父目录中看不到子目录中定义的变量(如include目录、库名称等)。是否有一种标准的方法可以在一个子系统中使用库名进行构建,在另一个子系统中使用相同的名称进行链接


还有一个问题:我有一个应用程序,由一个库和一个可执行文件组成。看起来CMake不允许对这两个对象使用相同的目标名称。在我看来,如果我对二进制目标和库目标都使用名称“A”,这应该不会导致混淆,因为真正的第二个目标是“libA”。我错了吗?

基本规则很简单:
添加子目录
建立一个新范围,
包含
没有。因此,您的示例只涉及两个范围:

  • 顶级CMakeList的范围,受
    MyCMake
    MyCMake2
    中的
    set(…)
    命令的影响,以及受
    子/CMakeList.txt中的
    set(…父范围)
    命令的影响
  • 子CMakeList
    child/CMakeLists.txt
    ,受
    set(…)
    命令的影响,该命令在
    child/CMakeLists.txt
    中不使用
    父范围
正确的是,
PARENT\u SCOPE
仅在父作用域中设置值。如果要同时为当前范围和父级设置值,则必须发出两个
set
命令:

set(var Value)
set(var Value PARENT_SCOPE)

关于堆栈溢出,我们通常希望每个问题有一个问题,但我也会回答目标命名问题:CMake目标名称是CMake目标的逻辑名称,它们必须是唯一的。想象一下,如果不是这样的话:

add_library(L STATIC ...)
add_library(A SHARED ...)
add_executable(A ...)

target_link_libraries(A L)
最后一行会有什么影响?库
A
会链接到
L
,还是可执行文件
A
会这样做?或者两者都有?Dtto用于设置属性等


您可以独立于目标名称控制生成的二进制文件的名称:有关详细信息,请参阅目标属性,如。

有关第一个问题,请参阅。关于你的第二个问题,我想你正在寻找。对于你的第三个问题,你可能想看一看基本上,我同意“每个问题一个问题”的规则,但这一次这三个问题是相互关联的,问题之间的强制性延迟意味着我需要4.5小时来发布三个问题。关于逻辑名称:您是对的,但此方案阻止使用库libA创建名为的二进制文件。@katang不,它根本不阻止二进制文件库方案。您只需给目标逻辑名称
A_bin
A_lib
,并将它们的
OUTPUT_NAME
属性设置为
A
。没有什么能阻止你那样做。