如何在从顶级 add_subdirectory 添加的包上使用 find_package?
How to use find_package on a package added from top level add_subdirectory?
这可能是一个 x y 问题,所以这是我的情况。
背景
我有以下项目结构:
-project
-examples
-example_that_uses_mylib_1
* CMakeLists.txt
* main.cpp
-example_that_uses_mylib_2
* CMakeLists.txt
* main.cpp
-external
-notmylib_a
* CMakeLists.txt
* ... (other stuff)
-notmylib_b
* CMakeLists.txt
* ... (other stuff)
-src
-mylib_stuff
* file1.cpp
* file1.h
*CMakeLists.txt
CMakeLists.txt
我正在尝试制作一个执行以下操作的 cmake 文件:
允许 mylib
依赖在 external
中找到的第 3 方库中的目标,而不使用 add_subdirectory
,因为它们实际上不是子目录,而且是不好的做法。
允许 example_that_uses_mylib
依赖于 mylib
目标的可执行文件而不将其添加为子目录。
在看到 this project 谁的顶级 cmake 这样做之前,我不确定该怎么做:
add_subdirectory(lib/foo)
add_subdirectory(src/bar)
add_subdirectory(src/baz)
bar 和 baz CMakeLists.txt
这样做:
#Bar
find_package(foo 0.1.2 CONFIG REQUIRED)
#Baz
find_package(bar CONFIG REQUIRED)
这让我觉得我可以对我的图书馆做同样的事情。我不能。
原本单顶层CMakeLists.txt建造所有目标,我想摆脱这个,与add_subdirectories分开建造,从mylib
开始。
问题
最初我的顶层 CMakeLists.txt 看起来很像这样(以前有效):
add_subdirectory(external/notmylib_a)
add_library(mylib STATIC src/mylib_stuff/file1.cpp)
target_include_directories(mylib PUBLIC src/)
target_link_libraries(mylib PRIVATE notmylib_a::notmylib_a)
当我决定将事情分开时,我最初是这样做的(这也有效):
#CMakeLists.txt
add_subdirectory(external/notmylib_a)
#src/CMakeLists.txt
add_library(mylib STATIC src/mylib_stuff/file1.cpp)
target_include_directories(mylib PUBLIC src/)
target_link_libraries(mylib PRIVATE notmylib_a::notmylib_a)
然后为了跟进另一个项目,我决定这样做:
#CMakeLists.txt
add_subdirectory(external/notmylib_a)
#src/CMakeLists.txt
find_package(notmylib_a CONFIG REQUIRED) #NEW LINE!!
add_library(mylib STATIC src/mylib_stuff/file1.cpp)
target_include_directories(mylib PUBLIC src/)
target_link_libraries(mylib PRIVATE notmylib_a::notmylib_a)
我在 CMAKE 中遇到错误
CMake Error at src/CMakeLists.txt:25 (find_package):
Could not find a package configuration file provided by "notmylib_a"
with any of the following names:
notmylib_aConfig.cmake
notmylib_a-config.cmake
Add the installation prefix of "notmylib_a" to CMAKE_PREFIX_PATH or set
"notmylib_a_DIR" to a directory containing one of the above files. If
"notmylib_a" provides a separate development package or SDK, be sure it
has been installed.
其他项目如何以这种方式利用 find_package
?
How was the other project able to utilize find_package
in such a way?
其他 foo
项目的配置文件 has these lines:
if(NOT TARGET foo::foo)
include("${foo_CMAKE_DIR}/foo-targets.cmake")
endif()
也就是说,当 foo
包含在 add_subdirectory
方法中并创建 foo::foo
目标时,find_package(foo)
实际上 忽略 它的配置文件。
这在 foo's CMakeLists.txt 中注明:
# We also add an alias definition so that we shadown
# the export namespace when using add_subdirectory() instead.
add_library(foo::foo ALIAS foo)
换句话说,使用 add_subdirectory
方法中包含的给定 foo
包,使用 find_package(foo)
是可能的,但是 可选 :一个可能直接使用 foo
或 foo::foo
目标而不使用任何 find_package()
.
您引用的示例项目可以做到:
#Bar
find_package(foo 0.1.2 CONFIG REQUIRED)
#Baz
find_package(bar CONFIG REQUIRED)
因为子项目lib/foo
和src/bar
都有CMakeLists.txt
文件
包含生成 CMake 包配置文件的 CMake 代码
当指定 CONFIG
模式时,将由 find_package
搜索,
发现这将构成 find_package
命令的成功。
以lib/foo/CMakeLists.txt
为例,这样的代码包括:
include(CMakePackageConfigHelpers)
...
set(PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/foo-config.cmake")
...
configure_package_config_file(cmake/foo-config.cmake.in
${PROJECT_CONFIG_FILE}
INSTALL_DESTINATION ${INSTALL_CONFIG_DIR})
因此,当cmake
是运行生成项目构建文件时,
包配置文件在生成的文件中,如下所示:
$ git clone https://github.com/sunsided/cmake.git
...
$ cd cmake/
$ mkdir build
$ cd build
$ cmake ..
...
$ find -name '*-config.cmake'
./lib/foo/foo-config.cmake
./src/bar/bar-config.cmake
那两个*-config.cmake
文件分别是包配置
lib/foo
和 src/bar
的文件。 find_package CONFIG
mode 的文档
描述了 find_package
将发现它们的(复杂)搜索算法。对于子项目
src/bar
,
find_package(foo 0.1.2 CONFIG REQUIRED)
能够找到 lib/foo/foo-config.cmake
因为当它运行时,构建文件
因为它的依赖性 lib/foo
已经生成。同样对于子项目
src/baz
,
find_package(bar CONFIG REQUIRED)
成功,因为其依赖项 src/bar
的构建文件已经完成
生成。
您在尝试以相同方式使用 find_package
时收到的 CMake 错误:
CMake Error at src/CMakeLists.txt:25 (find_package):
Could not find a package configuration file provided by "notmylib_a"
with any of the following names:
notmylib_aConfig.cmake
notmylib_a-config.cmake
...
现在有了明显的意义。要修复它,您需要填写缺失的
external/notmylib_a/CMakeLists.txt
中的CMake代码生成notmylib_a-config.cmake
.
这可能是一个 x y 问题,所以这是我的情况。
背景
我有以下项目结构:
-project
-examples
-example_that_uses_mylib_1
* CMakeLists.txt
* main.cpp
-example_that_uses_mylib_2
* CMakeLists.txt
* main.cpp
-external
-notmylib_a
* CMakeLists.txt
* ... (other stuff)
-notmylib_b
* CMakeLists.txt
* ... (other stuff)
-src
-mylib_stuff
* file1.cpp
* file1.h
*CMakeLists.txt
CMakeLists.txt
我正在尝试制作一个执行以下操作的 cmake 文件:
允许
mylib
依赖在external
中找到的第 3 方库中的目标,而不使用add_subdirectory
,因为它们实际上不是子目录,而且是不好的做法。允许
example_that_uses_mylib
依赖于mylib
目标的可执行文件而不将其添加为子目录。
在看到 this project 谁的顶级 cmake 这样做之前,我不确定该怎么做:
add_subdirectory(lib/foo)
add_subdirectory(src/bar)
add_subdirectory(src/baz)
bar 和 baz CMakeLists.txt
这样做:
#Bar
find_package(foo 0.1.2 CONFIG REQUIRED)
#Baz
find_package(bar CONFIG REQUIRED)
这让我觉得我可以对我的图书馆做同样的事情。我不能。
原本单顶层CMakeLists.txt建造所有目标,我想摆脱这个,与add_subdirectories分开建造,从mylib
开始。
问题
最初我的顶层 CMakeLists.txt 看起来很像这样(以前有效):
add_subdirectory(external/notmylib_a)
add_library(mylib STATIC src/mylib_stuff/file1.cpp)
target_include_directories(mylib PUBLIC src/)
target_link_libraries(mylib PRIVATE notmylib_a::notmylib_a)
当我决定将事情分开时,我最初是这样做的(这也有效):
#CMakeLists.txt
add_subdirectory(external/notmylib_a)
#src/CMakeLists.txt
add_library(mylib STATIC src/mylib_stuff/file1.cpp)
target_include_directories(mylib PUBLIC src/)
target_link_libraries(mylib PRIVATE notmylib_a::notmylib_a)
然后为了跟进另一个项目,我决定这样做:
#CMakeLists.txt
add_subdirectory(external/notmylib_a)
#src/CMakeLists.txt
find_package(notmylib_a CONFIG REQUIRED) #NEW LINE!!
add_library(mylib STATIC src/mylib_stuff/file1.cpp)
target_include_directories(mylib PUBLIC src/)
target_link_libraries(mylib PRIVATE notmylib_a::notmylib_a)
我在 CMAKE 中遇到错误
CMake Error at src/CMakeLists.txt:25 (find_package):
Could not find a package configuration file provided by "notmylib_a"
with any of the following names:
notmylib_aConfig.cmake
notmylib_a-config.cmake
Add the installation prefix of "notmylib_a" to CMAKE_PREFIX_PATH or set
"notmylib_a_DIR" to a directory containing one of the above files. If
"notmylib_a" provides a separate development package or SDK, be sure it
has been installed.
其他项目如何以这种方式利用 find_package
?
How was the other project able to utilize
find_package
in such a way?
其他 foo
项目的配置文件 has these lines:
if(NOT TARGET foo::foo)
include("${foo_CMAKE_DIR}/foo-targets.cmake")
endif()
也就是说,当 foo
包含在 add_subdirectory
方法中并创建 foo::foo
目标时,find_package(foo)
实际上 忽略 它的配置文件。
这在 foo's CMakeLists.txt 中注明:
# We also add an alias definition so that we shadown
# the export namespace when using add_subdirectory() instead.
add_library(foo::foo ALIAS foo)
换句话说,使用 add_subdirectory
方法中包含的给定 foo
包,使用 find_package(foo)
是可能的,但是 可选 :一个可能直接使用 foo
或 foo::foo
目标而不使用任何 find_package()
.
您引用的示例项目可以做到:
#Bar
find_package(foo 0.1.2 CONFIG REQUIRED)
#Baz
find_package(bar CONFIG REQUIRED)
因为子项目lib/foo
和src/bar
都有CMakeLists.txt
文件
包含生成 CMake 包配置文件的 CMake 代码
当指定 CONFIG
模式时,将由 find_package
搜索,
发现这将构成 find_package
命令的成功。
以lib/foo/CMakeLists.txt
为例,这样的代码包括:
include(CMakePackageConfigHelpers)
...
set(PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/foo-config.cmake")
...
configure_package_config_file(cmake/foo-config.cmake.in
${PROJECT_CONFIG_FILE}
INSTALL_DESTINATION ${INSTALL_CONFIG_DIR})
因此,当cmake
是运行生成项目构建文件时,
包配置文件在生成的文件中,如下所示:
$ git clone https://github.com/sunsided/cmake.git
...
$ cd cmake/
$ mkdir build
$ cd build
$ cmake ..
...
$ find -name '*-config.cmake'
./lib/foo/foo-config.cmake
./src/bar/bar-config.cmake
那两个*-config.cmake
文件分别是包配置
lib/foo
和 src/bar
的文件。 find_package CONFIG
mode 的文档
描述了 find_package
将发现它们的(复杂)搜索算法。对于子项目
src/bar
,
find_package(foo 0.1.2 CONFIG REQUIRED)
能够找到 lib/foo/foo-config.cmake
因为当它运行时,构建文件
因为它的依赖性 lib/foo
已经生成。同样对于子项目
src/baz
,
find_package(bar CONFIG REQUIRED)
成功,因为其依赖项 src/bar
的构建文件已经完成
生成。
您在尝试以相同方式使用 find_package
时收到的 CMake 错误:
CMake Error at src/CMakeLists.txt:25 (find_package):
Could not find a package configuration file provided by "notmylib_a"
with any of the following names:
notmylib_aConfig.cmake
notmylib_a-config.cmake
...
现在有了明显的意义。要修复它,您需要填写缺失的
external/notmylib_a/CMakeLists.txt
中的CMake代码生成notmylib_a-config.cmake
.