如何在 add_subdirectory 之后使用 find_package
How to use find_package after add_subdirectory
我正在尝试将第三方包导入到我的项目中。所以我一直在关注:
但这失败了:
/tmp/top-level/bin/extern/MyLib
CMake Error at bin/extern/MyLib/MyLibConfig.cmake:12 (include):
include could not find load file:
/tmp/top-level/bin/extern/MyLib/MyLibTargets.cmake
Call Stack (most recent call first):
CMakeLists.txt:6 (find_package)
文档中缺少什么?作为参考,我的最高水平 cmakelists.txt 是:
cmake_minimum_required(VERSION 3.18)
project(top-level)
add_subdirectory(extern)
find_package(MyLib CONFIG REQUIRED HINTS
${CMAKE_CURRENT_BINARY_DIR}/extern/MyLib)
'MyLib' 的 cmakelists.txt 文件是:
cmake_minimum_required(VERSION 3.18)
project(MyLib VERSION 1.0 LANGUAGES C)
add_library(MyLib mylib.c)
add_library(MyLib::MyLib ALIAS MyLib)
install(
TARGETS MyLib
EXPORT MyLibTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES
DESTINATION include)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
MyLibConfigVersion.cmake
VERSION ${PACKAGE_VERSION}
COMPATIBILITY AnyNewerVersion)
install(
EXPORT MyLibTargets
FILE MyLibTargets.cmake
NAMESPACE MyLib::
DESTINATION lib/cmake/MyLib)
configure_file(MyLibConfig.cmake.in MyLibConfig.cmake @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/MyLibConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/MyLibConfigVersion.cmake"
DESTINATION lib/cmake/MyLib)
错误消息不言自明:
您使用 build 目录中的脚本 MyLibConfig.cmake
,此脚本尝试加载由 install(EXPORT MyLibTargets)
创建的脚本 MyLibTargets.cmake
。
但后一个脚本仅在项目 安装 后才能工作,在项目 构建 时无法工作.
实际上,在那种情况下不需要整个调用 find_package(MyLib)
:
由于当前项目构建 MyLib
,您已经可以访问目标 MyLib::MyLib
。
如果你想让你的顶级项目变得灵活,这样它就可以在 MyLib
已经安装或正在构建的情况下工作,那么你可以使用 find_package
有条件地:
cmake_minimum_required(VERSION 3.18)
project(top-level)
# This project could be built as standalone.
# In that case 'MyLib' is assumed to be already installed.
#
# Also, this project could work as a subproject of some other project,
# which also builds `MyLib` via 'add_subdirectory(MyLib)'.
if(NOT TARGET MyLib::MyLib)
find_package(MyLib CONFIG REQUIRED)
endif()
# ... use MyLib via 'MyLib::MyLib' target.
或者,您可以编写 MyLibConfig.cmake
脚本,即使当前正在构建 MyLib
也可以使用它。
if(TARGET MyLib::MyLib)
return()
endif()
# ... usual content of the config file.
在这种情况下,可以简化根项目的 CMakeLists.txt
:
cmake_minimum_required(VERSION 3.18)
project(top-level)
# Normal use case is that 'MyLib' is already installed.
# But the project could work as a subproject in other scenarios.
#
# In those scenarios, a parent project should care about
# 'find_package' to work.
find_package(MyLib CONFIG REQUIRED)
# ... use MyLib via 'MyLib::MyLib' target.
在构建'MyLib'的情况下项目的用法如下:
- CMakeLists.txt (outer)
- MyLib
- CMakeLists.txt (MyLib)
- top_level
- CMakeLists.txt ("top-level")
外CMakeLists.txt
:
cmake_minimum_required(VERSION 3.18)
project(outer)
add_subdirectory(MyLib)
# Help inner project to find config file for MyLib.
#
# Here we use *internal* knowledge of MyLib project,
# that it generates 'MyLibConfig.cmake' directly in its build directory.
#
# Note: find_package expects 'XXX_DIR' variable to be CACHE one.
set(MyLib_DIR "${CMAKE_CURRENT_BINARY_DIR}/MyLib"
CACHE INTERNAL "Directory with MyLibConfig.cmake"
)
add_subdirectory(top_level)
我正在尝试将第三方包导入到我的项目中。所以我一直在关注:
但这失败了:
/tmp/top-level/bin/extern/MyLib
CMake Error at bin/extern/MyLib/MyLibConfig.cmake:12 (include):
include could not find load file:
/tmp/top-level/bin/extern/MyLib/MyLibTargets.cmake
Call Stack (most recent call first):
CMakeLists.txt:6 (find_package)
文档中缺少什么?作为参考,我的最高水平 cmakelists.txt 是:
cmake_minimum_required(VERSION 3.18)
project(top-level)
add_subdirectory(extern)
find_package(MyLib CONFIG REQUIRED HINTS
${CMAKE_CURRENT_BINARY_DIR}/extern/MyLib)
'MyLib' 的 cmakelists.txt 文件是:
cmake_minimum_required(VERSION 3.18)
project(MyLib VERSION 1.0 LANGUAGES C)
add_library(MyLib mylib.c)
add_library(MyLib::MyLib ALIAS MyLib)
install(
TARGETS MyLib
EXPORT MyLibTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES
DESTINATION include)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
MyLibConfigVersion.cmake
VERSION ${PACKAGE_VERSION}
COMPATIBILITY AnyNewerVersion)
install(
EXPORT MyLibTargets
FILE MyLibTargets.cmake
NAMESPACE MyLib::
DESTINATION lib/cmake/MyLib)
configure_file(MyLibConfig.cmake.in MyLibConfig.cmake @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/MyLibConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/MyLibConfigVersion.cmake"
DESTINATION lib/cmake/MyLib)
错误消息不言自明:
您使用 build 目录中的脚本 MyLibConfig.cmake
,此脚本尝试加载由 install(EXPORT MyLibTargets)
创建的脚本 MyLibTargets.cmake
。
但后一个脚本仅在项目 安装 后才能工作,在项目 构建 时无法工作.
实际上,在那种情况下不需要整个调用 find_package(MyLib)
:
由于当前项目构建 MyLib
,您已经可以访问目标 MyLib::MyLib
。
如果你想让你的顶级项目变得灵活,这样它就可以在 MyLib
已经安装或正在构建的情况下工作,那么你可以使用 find_package
有条件地:
cmake_minimum_required(VERSION 3.18)
project(top-level)
# This project could be built as standalone.
# In that case 'MyLib' is assumed to be already installed.
#
# Also, this project could work as a subproject of some other project,
# which also builds `MyLib` via 'add_subdirectory(MyLib)'.
if(NOT TARGET MyLib::MyLib)
find_package(MyLib CONFIG REQUIRED)
endif()
# ... use MyLib via 'MyLib::MyLib' target.
或者,您可以编写 MyLibConfig.cmake
脚本,即使当前正在构建 MyLib
也可以使用它。
if(TARGET MyLib::MyLib)
return()
endif()
# ... usual content of the config file.
在这种情况下,可以简化根项目的 CMakeLists.txt
:
cmake_minimum_required(VERSION 3.18)
project(top-level)
# Normal use case is that 'MyLib' is already installed.
# But the project could work as a subproject in other scenarios.
#
# In those scenarios, a parent project should care about
# 'find_package' to work.
find_package(MyLib CONFIG REQUIRED)
# ... use MyLib via 'MyLib::MyLib' target.
在构建'MyLib'的情况下项目的用法如下:
- CMakeLists.txt (outer)
- MyLib
- CMakeLists.txt (MyLib)
- top_level
- CMakeLists.txt ("top-level")
外CMakeLists.txt
:
cmake_minimum_required(VERSION 3.18)
project(outer)
add_subdirectory(MyLib)
# Help inner project to find config file for MyLib.
#
# Here we use *internal* knowledge of MyLib project,
# that it generates 'MyLibConfig.cmake' directly in its build directory.
#
# Note: find_package expects 'XXX_DIR' variable to be CACHE one.
set(MyLib_DIR "${CMAKE_CURRENT_BINARY_DIR}/MyLib"
CACHE INTERNAL "Directory with MyLibConfig.cmake"
)
add_subdirectory(top_level)