我有一个cmake项目,其中我有一些模块,我正在使用Find-*.cmake将共享模块包含在应用程序中。为了不考虑我添加的每个模块,我定义了一种全局LIB
变量或链接器:
# inside a Find-*.cmake or in the CMakeLists.txt of the modules:
set(LIB ${LIB} ...)
因此,在使用某些模块的最终应用程序中,我可以这样做:
target_link_libraries(${APP_NAME} ${LIB})
然后,我希望将编译后的模块放在/project_path/modules/foo/build
中,这样如果一个模块真的很大,可以编译一次,用于使用它的所有应用程序。我实现此目的的方法是以这种方式从 Find-*.cmake 加载模块的 CMakeLists.txt:
# 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)
但有时会发生某些模块需要另一个模块,以便add_subdirectory
创建新的作用域并且可以正确加载LIB
但无法编写它(当我使用set
时,它在更深的作用域中并且不会更改上作用域)。为了绕过这一点,我必须在set
中添加PARENT_SCOPE)。所以我试图将它添加到一些模块中,我认为这些模块可以嵌套并隐藏在某些依赖项中,但编译了我突然面临的所有应用程序:
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.
我担心这可能会因我需要哪个模块或模块本身的依赖树而因应用程序而异,所以我正在寻找一个更干净的解决方案。
你可以通过使用具有全局范围的属性来"模拟"全局变量行为:
SET_PROPERTY(GLOBAL PROPERTY MyGlobalProperty "MyGlobalPropertyValue")
然后,您可以使用
GET_PROPERTY(MyLocalVariable GLOBAL PROPERTY MyGlobalProperty)
然后,MyLocalVariable 包含 "MyGlobalPropertyValue"。
由于PARENT_SCOPE将变量定义扩展到唯一的父目录(而不是其父目录),因此在某些情况下这还不够,例如,如果您有一个深层源代码树......
默认情况下,CMake 中的所有变量都是局部变量。虽然您可以使用 PARENT_SCOPE
参数将局部变量的作用域增加一层,但这主要对函数的返回值有意义。
通常需要全局变量的行为:一旦任何人调用了查找脚本,您就希望结果在任何地方都可用。特别是,对同一查找脚本的第二次调用应仅重用第一次调用的结果。在 CMake 中,这是通过将变量存储到缓存来实现的。各种find_*
调用已经自动执行此操作,因此您应该首选在适用的情况下使用这些调用。对于任何其他自定义变量,set
还提供了存储到缓存的功能:
set(MY_GLOBAL_VARIABLE "Some value" CACHE STRING "Description")
请注意,局部变量可以隐藏其作用域中同名的缓存变量。