【问题标题】:How to use find_package after add_subdirectoryadd_subdirectory 后如何使用 find_package
【发布时间】:2021-09-22 16:37:55
【问题描述】:

我正在尝试将第三方包导入我的项目。所以我一直在关注:

但这失败了:

/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)

【问题讨论】:

  • CMake 项目不能使用配置文件(通过find_package),该文件是在同一项目中使用install(EXPORT) 创建的。该配置文件仅在安装项目后可用(例如,使用make install)。您的主要CMakeLists.txt 已经可以访问目标MyLib::MyLib,只需使用它即可。如果您不允许放弃find_package(MyLib) 呼叫,那么您可以准备“假”配置文件,它什么都不做(因为所有目标都已经可以访问)。
  • @Tsyvarev 您能否发表此评论作为答案。我不明白(根据您上面的评论)为什么this 有效?

标签: cmake


【解决方案1】:

错误信息不言自明:

您使用 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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2021-08-06
    • 1970-01-01
    相关资源
    最近更新 更多