如何在cmake中使用COMPONENTS配置项目 [英] How to configure project with COMPONENTS in cmake

查看:230
本文介绍了如何在cmake中使用COMPONENTS配置项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用cmake创建一个项目项目,该项目的访问方式类似于Poco所使用的方式.我发现以Poco为例,比较拥挤且难以理解,因此我试图创建一个没有宏的最小版本,以便我能看到发生了什么.我在这里为此示例构建了一个存储库.

I want to create a project of projects using cmake which is accessible in a similar manner to that used by Poco. I find that using Poco as an example is crowded and difficult to follow so I am trying to create a minimal version, without macros so that I can see what is going on. I have constructed a repository for this example here.

https://github.com/markeastwood82/nomnoms

这个,以及下面写的,是我最好的猜测,这是在经过数天的阅读/使用现代CMake"后,如何解决这个问题的最佳答案,除了它不能完全起作用.本质上,我有一个库 noms ,其中包含组件 fruit veg ,我希望它们可以从应用程序 munch 动态链接.我可以安装 noms 库,但无法通过 munch 找到它.有人可以帮我把这东西放在一起吗?

This, and what is written below is currently my best guess at how to solve this problem after some days of reading up / grappling with "modern CMake", except that it doesn't quite work. Essentially I have a library noms with components fruit and veg which I want link dynamically from an application munch. I can install the noms library, but cannot find it with munch. Can someone please help me to put this thing together?

这两个项目的结构如下:

The two projects are structured are as follows:

noms
|---- CMakeLists.txt
+---- fruit
|     |---- CMakeLists.txt
|     |---- fruit-config.cmake.in
|     +---- src
|     |     |----apple.cpp
|     |
|     +---- include/noms/fruit
|           |----apple.h
|
+---- veg
      |---- CMakeLists.txt
      |---- veg-config.cmake.in
      +---- src
      |     |---- asparagus.cpp
      |
      +---- include/noms/veg
            |---- asparagus.h

munch
|---- CmakeLists.txt
+---- src
      |---- main.cpp

文件 noms/CMakeLists.txt 包含以下内容.

cmake_minimum_required(VERSION 3.0)
set(project noms)
set(version 1.0.0)

project(${project})

add_subdirectory(fruit)
add_subdirectory(veg)

# UPDATE: implement advice from Tsyvarev

configure_file(${project}-config.cmake
  "${CMAKE_BINARY_DIR}/${project}-config.cmake"
  @ONLY
)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
  "${CMAKE_BINARY_DIR}/${project}-config-version.cmake"
  VERSION ${version}
  COMPATIBILITY AnyNewerVersion
)

install(
  FILES
    "${CMAKE_BINARY_DIR}/${project}-config.cmake"
  DESTINATION lib/cmake/${project}
)

文件 noms/fruit/CMakeLists.txt (与 noms/veg/CMakeLists.txt 几乎相同)是

set(component fruit)

add_library(${component} SHARED src/apple.cpp)

# namespaced alias
add_library(${project}::${component} ALIAS ${component})

target_include_directories(${component}
  PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>
)

install(TARGETS ${component} EXPORT ${component}-targets
  COMPONENT ${component}
  LIBRARY DESTINATION lib
  ARCHIVE DESTINATION lib
  RUNTIME DESTINATION bin
  INCLUDES DESTINATION include
)

install(EXPORT ${component}-targets
  FILE "${project}-${component}-targets.cmake"
  NAMESPACE ${project}::
  DESTINATION lib/cmake/${project}
  COMPONENT ${component}
)

# This seems like a kludge, but it does place the file in the correct location
# on my machine (Ubuntu 18.04). Idea taken from Poco
configure_file("${component}-config.cmake.in"
  "${CMAKE_BINARY_DIR}/${project}-${component}-config.cmake"
  @ONLY
)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
  "${CMAKE_BINARY_DIR}/${project}-${component}-config-version.cmake"
  VERSION ${version}
  COMPATIBILITY AnyNewerVersion
)

install(
  FILES
    "${CMAKE_BINARY_DIR}/${project}-${component}-config.cmake"
    "${CMAKE_BINARY_DIR}/${project}-${component}-config-version.cmake"
  DESTINATION lib/cmake/${project}
  COMPONENT ${component}
)

# DESTINATION will be automatically prefixed by ${CMAKE_INSTALL_PREFIX}
install(
  DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include
  COMPONENT ${component}
  DESTINATION ${CMAKE_INSTALL_PREFIX}
)

最后, noms/fruit/fruit-config.cmake.in 的文件(与 noms/veg/veg-config.cmake 几乎相同)是

Finally, the file for noms/fruit/fruit-config.cmake.in (and almost identical for noms/veg/veg-config.cmake) is

include(${CMAKE_CURRENT_LIST_DIR}/noms-fruit-config-version.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/noms-fruit-config-targets.cmake)

对于项目 munch ,文件 munch/CMakeLists.txt 只是

cmake_minimum_required(VERSION 3.0)
set(project munch)

find_package(noms REQUIRED COMPONENTS fruit)

add_executable(${project} src/main.cpp)

target_include_directories(${project}
  PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:$include>
)

target_link_libraries(${project}
  PUBLIC
    noms::fruit
)

在安装 noms 之后,我尝试构建 munch ,但是cmake找不到 noms-config.cmake 文件.我不知道它应该包含什么,也不知道我应该在哪里真正放置它.我也不确定在 noms/< food-type>/CMakeLists.txt 中使用 configure_file 的方法是否合适,因为这似乎不是必需的.这里的例子

After installing noms I try to build munch, however cmake can't find the noms-config.cmake file. I don't know what it should contain, nor where I should really put it. I am also not sure it the method of using configure_file in noms/<food-type>/CMakeLists.txt is appropriate, given this does not seem to be required in the example here

https://github.com/boostcon/cppnow_presentations_2017/blob/master/05-19-2017_friday/effective_cmake__daniel_pfeifer__cppnow_05-19-2017.pdf

我的问题与此处提出的问题基本相同,目前尚未答复(接受的答案不正确,正如我在该主题中所评论的).实际上,公平地说,由于该线程已经使用了6年,所以在编写本文时可能是正确的,但似乎并未使用现在推荐的xxx-config.cmake方法.

My question is essentially the same as was asked here, which is currently unanswered (the accepted answer is incorrect, as I have commented in that thread). Actually to be fair, since that thread is 6 years old, it may have been correct at the time of writing, but does not appear to utilize the xxx-config.cmake method that is now recommended.

如何在CMAKE中导出带有组件的库?

请随时向我提起我犯的任何错误,或者可以做得更好的任何事情.谢谢

Please feel free to pull me up on any mistakes I have made, or anything that could be done better. Thanks

*更新*

除了上面更新的 noms/CMakeLists.txt 文件之外,我还根据以下@Tsyvarev的建议实施了以下 noms/noms-config.cmake 文件...

In addition to the updated noms/CMakeLists.txt file above, I have implemented the following noms/noms-config.cmake file as per advice from @Tsyvarev below ...

foreach(component ${noms_FIND_COMPONENTS})
    include(${CMAKE_CURRENT_LIST_DIR}/noms-${component}-config.cmake)
endforeach()

生成的代码现在可以工作了,谢谢!

The resulting code now works, thankyou!


推荐答案

CMake不会自动处理 COMPONENTS 列表.它将任务留给 noms-config.cmake 脚本,该脚本会在发出命令时被搜索并执行

CMake doesn't process COMPONENTS list automatically. It leaves that mission to noms-config.cmake script, which is searched and executed when one issues the command

find_package(noms COMPONENTS fruit veg)

find_package 文档中:

在配置模式下, find_package 自动处理 REQUIRED QUIET [version] 选项,但保留给程序包配置文件,以对程序包有意义的方式处理组件.

In Config mode find_package handles REQUIRED, QUIET, and [version] options automatically but leaves it to the package configuration file to handle components in a way that makes sense for the package.

在此配置文件中,您可以从 noms_FIND_COMPONENTS 变量中提取请求的组件列表(通过 find_package() COMPONENTS 选项提供),并执行适当的操作.例如:

Inside this config file, you may extract list of requested components (given via COMPONENTS option to find_package()) from the noms_FIND_COMPONENTS variable, and perform appropriate actions. For example:

noms-config.cmake :

foreach(component ${noms_FIND_COMPONENTS})
  # For requested component, execute its "config" script
  include(${CMAKE_CURRENT_LIST_DIR}/${component}-config.cmake)
endforeach()

这意味着,您将把脚本 noms-config.cmake 安装到另一个 .cmake lib/cmake/noms 子目录中.>您已经在项目中安装的脚本.

This implies, that you will install the script noms-config.cmake to lib/cmake/noms subdirectory, near the other .cmake scripts you have already installed in your project.

这篇关于如何在cmake中使用COMPONENTS配置项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆