【问题标题】:CMake scoping rulesCMake 范围规则
【发布时间】:2015-12-22 14:41:40
【问题描述】:

我对 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

这第一行没问题,第二个和第三个变量还没有定义。 对于第二行,它看起来像是一个仅限父级的设置,即定义的变量仅在父级中具有范围。 (所以,我可以/应该在本地范围内使用相同的变量?)第三行仅显示具有父范围的变量,好的。第 4 行显示我设置了 LOCAL 范围变量。但是,在第 5 行中,我看到 PARENT 范围值已更改,我希望仅在子目录中本地更改该值。 这里发生了什么? (看起来我可以覆盖变量的值,这不在我的范围内)

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

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

【问题讨论】:

标签: cmake


【解决方案1】:

基本规则很简单:add_subdirectory 建立一个新范围,include 没有。 所以您的示例只涉及两个范围:

  • 顶级 CMakeList 的范围,受MyCMakeMyCMake2 中的set(...) 命令以及child/CMakeLists.txt 中的set(... PARENT_SCOPE) 命令影响。
  • 子 CMakeList child/CMakeLists.txt 的范围,受 child/CMakeLists.txt 内部的 set(...) 命令影响,这些命令不使用 PARENT_SCOPE

PARENT_SCOPE 仅在父范围内设置值是正确的。 如果您想同时为当前范围和父范围设置值,则必须发出两个 @987654334 @ 命令:

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 等目标属性。

【讨论】:

  • 基本上,我同意“一题一题”的规则,但这次三个问题是相互关联的,问题之间的强制性延迟意味着我需要 4.5 小时才能发布三个问题。关于逻辑名称:您是对的,但是这种方案阻止使用库 libA 创建名称为 A 的二进制文件。
  • @katang 不,它根本不会阻止二进制库方案。您只需给目标逻辑名称A_binA_lib,并将它们的OUTPUT_NAME 属性都设置为A没有什么能阻止你这样做。
猜你喜欢
  • 2015-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-24
相关资源
最近更新 更多