Mat*_*oob 5 c++ dependencies cmake dependency-management
我有一个名为MYLIBS的包,由两个库lib1和lib2组成,我想通过包的配置文件导出它们。项目结构如下:
\n\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Lib1\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 CMakeLists.txt\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 lib1-class.cpp\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 lib1-class.h\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 lib2\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 CMakeLists.txt\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 lib2-class.cpp\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 lib2-class.h\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 cmake\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 LIBSConfig.cmake.in\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 CMakeLists.txt\nRun Code Online (Sandbox Code Playgroud)\n\n在lib2中我有:
\n\nadd_library(lib2\n STATIC\n ${SOURCE_FILES}\n )\ntarget_include_directories(lib2 PRIVATE /path/to/lib1)\ntarget_link_libraries(lib2 PUBLIC lib1)\nadd_dependencies(lib2 lib1)\ninstall(\n TARGETS\n lib2\n DESTINATION\n lib/MYLIBS/lib2\n EXPORT\n lib2Exports\n)\ninstall(\n EXPORT\n lib2Exports\n DESTINATION\n lib/MYLIBS/lib2\n)\nRun Code Online (Sandbox Code Playgroud)\n\n与 lib1 相同,只是 lib1 没有add_dependencies()和target_include/link(),因为它没有 。
在我的配置文件模板中,我有:
\n\n@PACKAGE_INIT@\n## PROJECT_LIBRARIES is filled-in during the package build. in this case : lib1,lib2\nset(@PROJECT_NAME@_LIBRARIES @PROJECT_LIBRARIES@)\n\n## The public variables to be used by the client project:\n#PROJECT_NAME_INCLUDE_DIRS is all the include paths\n#PROJECT_NAME_LIBRARIES is the name of all the libraries\n\nunset(@PROJECT_NAME@_INCLUDE_DIRS)\nforeach(INCLUDE_DIR ${INCLUDE_DIRS})\n set_and_check(@PROJECT_NAME@_INCLUDE_DIR ${INCLUDE_DIR})\n list(APPEND @PROJECT_NAME@_INCLUDE_DIRS ${@PROJECT_NAME@_INCLUDE_DIR})\nendforeach()\n\n## PACKAGE_PACKAGE_DIRNAME_include is filled-in during the package build\nforeach(lib ${@PROJECT_NAME@_LIBRARIES})\n list(APPEND INCLUDE_DIRS @PACKAGE_PACKAGE_DIRNAME_include@/${lib})\nendforeach(lib)\n\n# Looks up the information about the exported targets in this package\nforeach(lib ${@PROJECT_NAME@_LIBRARIES})\n if(NOT TARGET ${lib})\n include(@PACKAGE_PACKAGE_DIRNAME_lib@/${lib}/${lib}Exports.cmake)\n endif()\nendforeach(lib)\nRun Code Online (Sandbox Code Playgroud)\n\n因此,我一一检查库的导出文件并包含它们。问题是我必须按照正确的顺序执行此操作,即先 lib1,然后 lib2,否则在读取配置文件时会出现错误FindPackage()。
我不太确定传递依赖项将如何工作。由于这些库是从同一个导出文件中导出的,考虑到我们知道依赖项的导出文件将位于系统上的位置,include()是否有一种方法可以告诉 CMake 配置文件或lib2的导出文件中的依赖项?
我可以看到 target_link_libraries() 有一个 PUBLIC 选项。我应该如何使用它?有什么帮助吗?
\n首先,您可以删除该add_dependencies行。请参阅target_link_libraries 和 add_dependency。
其次,你有
target_include_directories(lib2 PRIVATE /path/to/lib1)
Run Code Online (Sandbox Code Playgroud)
但这应该是不需要的。相反,删除它,并将其添加到lib1:
target_include_directories(lib1 PUBLIC /path/to/lib1)
Run Code Online (Sandbox Code Playgroud)
不过,这些只是清理工作。
您没有发布错误,并且您的帖子中缺少许多其他重要信息,所以我做了一些猜测。
我猜这个错误是类似的
The following imported targets are referenced, but are missing: lib2
Run Code Online (Sandbox Code Playgroud)
您将lib1和导出lib2到两个单独的“导出集” -lib1Exports和中lib2Exports。将它们放入一个“导出集”中可以解决问题,并且是最简单的方法,至少在两个目标的示例中是这样。
我想您知道这一点,但您没有这样做,因为您的构建系统的规模大于两个目标。但是,这直接导致您的问题 - 这意味着您必须管理“导出集”之间的顺序依赖性。
这与目标之间的依赖关系无关。“导出集”是具有独立依赖图的不同“单元”。CMake 无法帮助您管理它。您必须管理“导出集”之间的依赖关系。问题是您当前没有管理或表达这些依赖关系。有关表达这些依赖关系的选项,请参阅下文。
target_link_libraries(PUBLIC)对你没有帮助。请阅读传递使用要求中了解相关内容。
如果您将其与预处理器文件进行类比,您可能会看到您的选择。想起来lib2_private.h哪个没有#include lib1_private.h。Aalllibs.h需要以include正确的顺序来处理这两个。因为_private标头是私有的,并且客户端总是会包含这些标alllibs.h头,所以这是可行的。在这种方法中,您可以在一个位置管理整个依赖关系树。
另一种方法是创建lib2_internal.h包含
#include "lib1_private.h"
#include "lib2_private.h"
Run Code Online (Sandbox Code Playgroud)
其中lib1_internal.h包含
#include "lib1_private.h"
Run Code Online (Sandbox Code Playgroud)
在这种方法中,您可以管理靠近依赖项的依赖项,因此您将有多个位置来指定总依赖项树的子集。可以alllibs.h使用
#include "lib1_internal.h"
#include "lib2_internal.h"
Run Code Online (Sandbox Code Playgroud)
或者
#include "lib2_internal.h"
#include "lib1_internal.h"
Run Code Online (Sandbox Code Playgroud)
并且顺序并不重要。
带有循环的配置文件是alllibs.h- 它是客户端包含的唯一文件。你们可以完全在那里管理订单吗?是的,如果您可以管理变量内的顺序@PROJECT_NAME@_LIBRARIES。顺便说一句,你应该这样称呼@PROJECT_NAME@_EXPORT_SETS。如果您不明白为什么,请再看看我上面所说的关于它是一个不同的“单位”的内容。
您没有提供太多信息,但我猜您正在用多个填充该信息
list(APPEND MYPROJ_EXPORT_SETS fooExports)
Run Code Online (Sandbox Code Playgroud)
调用,也许在某些宏中。因此,该订单不容易维护,因为它是一个单一的set()调用。
因此,表达“导出集”依赖项的选项是:
MYPROJ_EXPORT_SETS,并将配置文件中的循环替换为考虑到这些依赖关系的更复杂的内容。(1) 可能是最有意义的,但您可能还必须退后一步,更加仔细地思考您正在创建的抽象/包装器,这些抽象/包装器导致您来到这里。
| 归档时间: |
|
| 查看次数: |
5469 次 |
| 最近记录: |