如何使用CMake创建软件包

8
.
+-- MyPack
|   +-- Lib1
|   |   +-- include
|   |   |   +-- Lib1.h
|   |   +-- src
|   |   |   +-- Lib2.cpp
|   |   +-- CMakeLists.txt
|   +-- Lib2
|   |   +-- include
|   |   |   +-- Lib2.h
|   |   +-- src
|   |   |   +-- Lib2.cpp
|   |   +-- CMakeLists.txt
|   +-- CMakeLists.txt
+-- SubProject1
|   +-- CMakeLists.txt
+-- SubProject2
|   +-- CMakeLists.txt
+-- CMakeLists.txt

大家好。

我对CMake还不熟悉,正在尝试实现以下功能。 考虑我的C++项目的目录树如下:

我有一个目录(假设为“MyPack”),其中包含多个子目录(Lib1、Lib2...),每个子目录代表我编写的一个C++库。

如何设置所有内容,以便在其他子项目中编写find_package(MyPack)

每个子项目都是独立的项目,不依赖于其他子项目,但只依赖于“MyPack”中的库。


将包导出到MyPack中,然后使用-DCMAKE_PREFIX_PATH=../../MyPack - Guillaume Racicot
1个回答

14
你的绘图有点混乱,因为在Lib2之后有一个CMakeLists.txt,它不属于任何文件夹... 不管怎样,是MyPack
  • Lib1和Lib2?
  • Lib1/Lib2/Subproj1/Subproj2?

在第二种情况下:

顶层目录的CMakeLists.txt可以让你访问Lib1和Lib2的目标,如果你有类似这样的东西,你可以在SubProject1和SubProject2中使用它们:

project(MyPack)
add_subdirectory(Lib1) # Building Lib1
add_subdirectory(Lib2) # Building Lib2
add_subdirectory(SubProject1) # you can use Lib1 & Lib2 targets here
add_subdirectory(SubProject2) # you can use Lib1 & Lib2 targets here

如果是第一种情况,MyPack 只是 Lib1 和 Lib2:
使用 find_package(MyPack) 意味着你需要创建一个 Config 文件并安装() 你的项目。
project(MyPack)
add_subdirectory(Lib1)
add_subdirectory(Lib2)

在Lib1/CMakeLists.txt文件中:
add_library(lib1 "")
add_library(MyPack::lib1 ALIAS lib1)
[...]
include(GNUInstallDirs)
install( 
  TARGETS lib1
  EXPORT MyPackTargets
  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
  )

在Lib2/CMakeLists.txt中:
add_library(lib2 "")
add_library(MyPack::lib2 ALIAS lib2)
[...]
include(GNUInstallDirs)
install( 
  TARGETS lib2
  EXPORT MyPackTargets
  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
  )

现在你在导出的MyPackTargets中有lib1和lib2。你还需要安装这个导出。在上述之后的任何地方都可以。
install(
  EXPORT MyPackTargets
  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyPack
  NAMESPACE MyPack::
  FILE MyPackTargets.cmake # Not sure if this is still needed
  )

include(CMakePackageConfigHelpers)
configure_package_config_file( 
  "Config.cmake.in" 
  "MyPackConfig.cmake"
  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyPack
  PATH_VARS
    CMAKE_INSTALL_LIBDIR
  )

write_basic_package_version_file(
  ${CMAKE_CURRENT_BINARY_DIR}/MyPackConfigVersion.cmake
  VERSION 1.0.0
  COMPATIBILITY SameMajorVersion
  )

### Install Config and ConfigVersion files
install(
  FILES "${CMAKE_CURRENT_BINARY_DIR}/MyPackConfig.cmake"
        "${CMAKE_CURRENT_BINARY_DIR}/MyPackConfigVersion.cmake"
  DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/MyPack"
  )


创建一个名为Config.cmake.in的文件。
@PACKAGE_INIT@
include( "${CMAKE_CURRENT_LIST_DIR}/MyPackTargets.cmake" )

现在,如果你构建并安装了你的项目 MyPack,其他项目中的 find_package(MyPack) 应该能找到它并导入你创建的目标。
这里有一些文档: https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html

https://blog.kitware.com/cmake-superbuilds-git-submodules/


谢谢!我仍然不能按照我的意愿使其工作。首先,正如您所理解的那样,情况是第一个。我在lib1-2/CMakeLists.txt中放置了您建议的代码,导出了MyPackTargets。之后,我在MyPack/中创建了Config.cmake.in和CMakeLists.txt,在其中添加了两个库的子目录,并放置了您建议的代码(安装MyPackTargets)。最后,在项目文件夹(MyPack之外)中运行“cmake .”,它会找到MyPack包,但找不到MyPack/MyPackTargets.cmake,这是由MyPack/MyPackConfig.cmake包含的。有进一步的建议吗? - r.stagi
你的项目能够找到MyPack包配置是一个好兆头。现在看起来Config.cmake.in中的路径不正确,你应该尝试将其调整为安装文件夹中MyPackTargets.cmake的位置。 - Alkalyne
问题是我找不到任何MyPackTargets.cmake文件。顺便说一下,我解决了在MyPack的CMakeLists.txt中为所有库添加add_subdirectory,并在我的项目的CMakeLists.txt中添加add_subdirectory(MyPack)(其中包含“MyPack”)。我不得不删除find_package指令,现在它可以正常工作了。也许这不是最好的做法,但我能做我想做的事情。所以谢谢! - r.stagi
你主要采用了我之前解释的第二种解决方案 - 因为你拥有所有源代码,所以可以访问构建树内部的目标。对于你最初的问题,MyPackTargets.cmake 应该通过 install(Export) 安装。检查一下这个命令是否在正确的位置执行(你可以检查 install_manifest.txt 来查看文件的安装位置)。 - Alkalyne
1
我相信应该是“TARGETS”而不是“TARGET”,除了这个笔误之外,解决方案非常棒。谢谢! - Kjell Hedström

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接