cmake,丢失在全局变量的概念(和PARENT_SCOPE或add_subdirectory替代) [英] cmake, lost in the concept of global variables (and PARENT_SCOPE or add_subdirectory alternatives)

查看:327
本文介绍了cmake,丢失在全局变量的概念(和PARENT_SCOPE或add_subdirectory替代)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个cmake项目,其中有一些模块,我正在使用Find - * .cmake在应用程序中包含共享模块。
为了不考虑我添加的每个模块,我已经定义了一种全局 LIB 变量的链接器:

 #在一个Find  -  * .cmake或模块的CMakeLists.txt中:
set(LIB $ {LIB} ...)

所以在最后一个应用程序中使用我可以做的一些模块:

  target_link_libraries($ {APP_NAME} $ {LIB})

然后,我想将编译的模块放在 / project_path / modules / foo / build 中,以便如果一个模块真的很大编译它可以编译一次所有使用它的应用程序。我实现这个的方式是从Find - * .cmake以这种方式加载模块的CMakeLists.txt:

 #内部FindFoo.cmake,用于加载/project_path/modules/foo/CMakeLists.txt 
#并将其编译到/ project_path / modules / foo / build
add_subdirectory($ {CMAKE_CURRENT_LIST_DIR} / .. / modules / $ {PACKAGE_NAME}
$ {CMAKE_CURRENT_LIST_DIR} /../ modules / $ {PACKAGE_NAME} / build

include_directories($ {CMAKE_CURRENT_LIST_DIR} /../ modules / $ { PACKAGE_NAME} / include)

但有时候有些模块需要另外一个模块,以便 add_subdirectory 创建新的范围,可以正确加载 LIB ,但无法写入(当我使用设置它在更深的范围,而不是更改上限)。为了绕过这个,我必须在集合中添加 PARENT_SCOPE 。所以我试图将它添加到我认为可以嵌套的某个模块中隐藏在某些依赖关系中,但编译我突然面临的所有应用程序:

  / path_to_repo / cmake / FindFooX.cmake:6(set):
无法设置LIB:当前范围没有父级。
调用堆栈(最近的首次调用):
CMakeLists.txt:14(find_package)
此警告是为项目开发人员。使用-Wno-dev来抑制它。

我恐怕这可以从应用程序更改为应用程序,我需要或尊重的模块的模块本身的依赖树,所以我正在寻找一个更清洁的解决方案。

解决方案

CMake中的所有变量都是本地的默认。虽然您可以使用 PARENT_SCOPE 参数将局部变量的范围增加一层,但这对于函数



另一方面,脚本通常需要一个全局变量的行为:一旦找到脚本被任何人调用,你希望结果可以随处可见。特别地,对同一个find脚本的第二个调用应该只是重用第一个调用的结果。
在CMake中,通过将变量存储到缓存来实现。各种查找_ * 调用已经自动执行,所以你应该更喜欢使用那些适用的。对于任何其他自定义变量, set 还提供存储到缓存的功能:

  set(MY_GLOBAL_VARIABLE一些值CACHE STRING描述)

请注意,局部变量可以隐藏相同名称的缓存变量在其范围内。


I have a cmake project in which I have some modules and I'm using Find-*.cmake for including the shared modules in the application. For not taking in account every module that I add, I have defined a kind of global LIB variables tor the linker:

# inside a Find-*.cmake or in the CMakeLists.txt of the modules:
set(LIB ${LIB} ...)

so in one of the final applications that uses some modules I can just do:

target_link_libraries(${APP_NAME} ${LIB})

Then, I'd like to have the compiled modules in the /project_path/modules/foo/build so that if a module is really big to compile it can be compiled once for all the application that use it. The way I'm achieving this is to load the CMakeLists.txt of the module from the Find-*.cmake in this way:

# Inside FindFoo.cmake, for loading /project_path/modules/foo/CMakeLists.txt
# and compile it in /project_path/modules/foo/build
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../modules/${PACKAGE_NAME} 
                 ${CMAKE_CURRENT_LIST_DIR}/../modules/${PACKAGE_NAME}/build
)
include_directories(${CMAKE_CURRENT_LIST_DIR}/../modules/${PACKAGE_NAME}/include)

But it happened sometimes that some module require another modules so that the add_subdirectory creates new scopes and can correctly load LIB but cannot write it (when I use set it is in the deeper scope and not changes the upper scope). For bypass this I have to add PARENT_SCOPE in the set).. So I have tried to add it in some module that I think could be nested and hidden in some dependencies but compiling all the application I suddenly faced with:

CMake Warning (dev) at /path_to_repo/cmake/FindFooX.cmake:6 (set):
  Cannot set "LIB": current scope has no parent.
Call Stack (most recent call first):
  CMakeLists.txt:14 (find_package)
This warning is for project developers.  Use -Wno-dev to suppress it.

I am afraid that this can change from app to app in respect to which module I need or in respect of the dependecies tree in the modules itself so I'm looking for a cleaner solution.

解决方案

All variables in CMake are local by default. While you can use the PARENT_SCOPE parameter to increase the scope of a local variable by one layer, that mostly makes sense for return values of functions.

For find scripts on the other hand you usually want the behavior of a global variable: Once the find script is called by anyone, you want the results to be available everywhere. In particular, a second call to the same find script should just reuse the results of the first call. In CMake this is achieved by storing variables to the cache. The various find_* calls already do this automatically, so you should prefer using those where applicable. For any additional custom variables, set offers the capability to store to the cache as well:

set(MY_GLOBAL_VARIABLE "Some value" CACHE STRING "Description")

Note that local variables can hide cached variables of the same name in their scope.

这篇关于cmake,丢失在全局变量的概念(和PARENT_SCOPE或add_subdirectory替代)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆