我有这样的层次结构:
CMakeLists.txt # calls add_subdirectory() for subdirs in the listed order
+-deps
| +-CMakeLists.txt # calls find_package(Vulkan), a 3rd party lib, present on my system
+-mylib
| +-CMakeLists.txt # depends on Vulkan::Vulkan
| +-mylib.cpp
+-example
+-CMakeLists.txt # depends on Vulkan::Vulkan
+-example.cpp
问题在于 mylib/CMakeLists.txt 和 example/CMakeLists.txt 中的以下命令:
target_link_libraries(mylib PRIVATE Vulkan::Vulkan)
我收到以下错误:
CMake Error at mylib/CMakeLists.txt:2 (target_link_libraries):
Target "mylib" links to:
Vulkan::Vulkan
but the target was not found. Possible reasons include:
* There is a typo in the target name.
* A find_package call is missing for an IMPORTED target.
* An ALIAS target is missing.
对于 example/CMakeLists.txt 也是如此。
我的问题: 如何使这些 CMakeLists.txt 文件在其同级 CMakeLists.txt 文件中看到 find_package() 找到的目标?
我尝试过的: 我将
find_package()
移至根 CMakeLists.txt,然后一切正常。但我想整齐地整理我的文件。这是一个高度简化的版本。真正的层次结构要复杂得多。
我找到了
set(PARENT_SCOPE)
并且能够将 TRUE
的 ${Vulkan_FOUND}
值从 deps 传播到根,然后传播到示例。也许需要类似的东西,但对于目标而不是变量?
详情:
./CMakeLists.txt:
cmake_minimum_required(VERSION 3.6...3.22)
project(mylib VERSION 0.0.1)
add_subdirectory(deps)
add_subdirectory(mylib)
add_subdirectory(example)
./deps/CMakeLists.txt:
find_package(Vulkan)
./mylib/CMakeLists.txt:
add_library(mylib mylib.cpp)
target_link_libraries(mylib PUBLIC Vulkan::Vulkan)
./example/CMakeLists.txt:
add_executable(example example.cpp)
target_link_libraries(example PUBLIC mylib Vulkan::Vulkan)
在 CMake 中,
find_package
的使用预计是目录及其后代的 local。如果其他目录(来自其他层次结构)需要相同的包,那么应该重复 find_package
调用。
特别是“deps”功能,我看到许多项目将此功能模式化为单独的
.cmake
脚本,并通过 include()
命令将该脚本包含在根 CMakeLists.txt
中。无论包含的 .cmake
脚本位于何处,include
命令都不会引入目录范围。
因此,该脚本的每个 find_package
调用的作用域都是根 CMakeLists.txt
,因此其结果可以在任何子目录中使用。
./cmake/deps.cmake
:
find_package(Vulkan)
./CMakeLists.txt
:
cmake_minimum_required(VERSION 3.6...3.22)
project(mylib VERSION 0.0.1)
# Specify directory where included scripts will be searched.
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include(deps)
add_subdirectory(mylib)
add_subdirectory(example)