How to configure project with COMPONENTS in cmake(如何在 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?
两个项目的结构如下:
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 包含以下内容.
The file noms/CMakeLists.txt contains the following.
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 几乎相同)是
The file noms/fruit/CMakeLists.txt (and almost identical for noms/veg/CMakeLists.txt) is
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_packagehandlesREQUIRED,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 安装到 lib/cmake/noms 子目录,靠近另一个 .cmake 您已经在项目中安装的脚本.
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 配置项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何在 cmake 中使用 COMPONENTS 配置项目
基础教程推荐
- 常量变量在标题中不起作用 2021-01-01
- 如何通过C程序打开命令提示符Cmd 2022-12-09
- 如何检查GTK+3.0中的小部件类型? 2022-11-30
- 静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么? 2021-01-01
- 我有静态或动态 boost 库吗? 2021-01-01
- 如何将 std::pair 的排序 std::list 转换为 std::map 2022-01-01
- 如何在 C++ 中初始化静态常量成员? 2022-01-01
- 这个宏可以转换成函数吗? 2022-01-01
- C++结构和函数声明。为什么它不能编译? 2022-11-07
- 在 C++ 中计算滚动/移动平均值 2021-01-01
