如何在从顶层add_subdirectory添加的软件包上使用find_package?

时间:2019-04-26 15:02:25

标签: c++ build cmake static-libraries target

这可能是一个xy问题,所以这是我的情况。

背景


我具有以下项目结构:

-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中发现的第三方库中的目标,而无需使用add_subdirectory,因为它们实际上不是子目录,这是一种不好的做法。

  • 允许example_that_uses_mylib个依赖于mylib目标的可执行文件,而无需将其添加为子目录。

在看到this project谁的顶级命令执行此操作之前,我不确定如何执行此操作:

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

2 个答案:

答案 0 :(得分:1)

  

另一个项目如何能够以这种方式利用find_package

其他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)实际上忽略其配置文件。< / p>

这在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)

换句话说,在foo方法中包含给定的add_subdirectory包的情况下,可以使用find_package(foo),但是可选:一个人可以直接使用{{1 }}或foo目标,而没有任何foo::foo

答案 1 :(得分:0)

您引用的示例项目可以执行以下操作:

#Bar
find_package(foo 0.1.2 CONFIG REQUIRED)

#Baz
find_package(bar CONFIG REQUIRED)

因为两个子项目lib/foosrc/bar都有CMakeLists.txt个文件 包含生成CMake软件包配置文件的CMake代码 如果指定了find_package模式,CONFIG将搜索该文件, 发现哪个将构成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/foosrc/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