【问题标题】:How to use find_package on a package added from top level add_subdirectory?如何在从顶级 add_subdirectory 添加的包上使用 find_package?
【发布时间】:2019-04-26 15:02:24
【问题描述】:

这可能是一个 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 中找到的第三方库中的目标,而不使用add_subdirectory,因为它们实际上不是子目录,这是不好的做法。

  • 允许依赖于mylib 目标的example_that_uses_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

【问题讨论】:

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


    【解决方案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) 实际上忽略其配置文件。

    这在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) 是可能的,但是可选:可以直接使用foofoo::foo 目标而不使用任何find_package()

    【讨论】:

      【解决方案2】:

      你参考的示例项目是可以做到的:

      #Bar
      find_package(foo 0.1.2 CONFIG REQUIRED)
      
      #Baz
      find_package(bar CONFIG REQUIRED)
      

      因为lib/foosrc/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/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
          ...
      

      现在有了明显的意义。要修复它,您需要填写缺失的 CMake 代码在external/notmylib_a/CMakeLists.txt 中生成notmylib_a-config.cmake

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-19
        • 2013-09-30
        • 1970-01-01
        • 2017-08-28
        • 2022-06-17
        相关资源
        最近更新 更多