【发布时间】:2018-07-27 19:17:14
【问题描述】:
我正在开发使用一些第三方库的项目。我可以克隆它们并将它们作为git submodule 放入我的项目中,并使用add_subdirectory 在我的项目中使用它们。但是编译这些库需要很多时间,而且我无法在我的项目中管理cmake 变量,而install() 命令使我的包包含许多我不需要的东西。
那么在我的项目中使用第三方库的正确方法是什么。我不能告诉客户将这些库安装为我的项目的依赖项。
【问题讨论】:
我正在开发使用一些第三方库的项目。我可以克隆它们并将它们作为git submodule 放入我的项目中,并使用add_subdirectory 在我的项目中使用它们。但是编译这些库需要很多时间,而且我无法在我的项目中管理cmake 变量,而install() 命令使我的包包含许多我不需要的东西。
那么在我的项目中使用第三方库的正确方法是什么。我不能告诉客户将这些库安装为我的项目的依赖项。
【问题讨论】:
回答这个问题需要涵盖几个方面,您会发现以下两个部分:
如果您正在考虑集成不在项目范围内的库,第一步是确保所有库都提供配置文件包。
配置文件包通常包含FooConfig.cmake、FooConfigVersion.cmake 和FooTargets.cmake 等文件。
一般来说,如果库 Foo 已经在使用 CMake 并且已经提供了配置文件包,那么使用 -DFoo_DIR:PATH=/path/to/build-or-install-dir/ 配置您的项目允许您从自己的项目中调用 find_package(Foo REQUIRED)。这将导入您可以链接到您自己的库或可执行文件的 CMake 目标。
现在,如果库 Foo 尚未使用 CMake,则有以下选择:
案例一:
Foo 已经在使用 CMake案例 2:
Foo不使用 CMakeFoo 的维护者愿意过渡到 CMake(或者至少在他们当前的构建系统旁边有 CMakeLists.txt)案例 3:
Foo 不使用 CMakeFoo 的维护者不想过渡到 CMake案例 4:
(1) 库 Foo 不 使用 CMake
(2) 和Foo 的维护者不想(或尚未准备好)过渡到 CMake。
(3)当前的构建系统运行不好,或者库很难用更广泛的编译器构建,或者不支持交叉编译
action:创建一个名为 foo-cmake-buildsystem 的项目(最好在 GitHub 上),允许通过以下任一方式构建库
python-cmake-buildsystem的项目案例 5:
Foo 的维护者不想转换,或者无法维护替代构建系统,或者系统上已经有库FindFoo.cmake 来创建导入的目标。
FindOpenSSL.cmake、FindGit.cmake、...的情况要了解有关配置文件包的更多信息,请参阅https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html
如果库Foo 是:
然后,ExternalProject CMake 模块将允许您从自己的项目中下载、配置、构建……这些项目。
实现这一点的方法很少。
这是一个运行良好的系统:您可以设置一个 2 级构建系统,我们称之为:SuperBuild。
为了支持SuperBuild 方法,您的 CMakeLists.txt 可以具有以下结构:
project(AwesomeProject)
[...]
option(Awesome_ENABLE_EXTRA "Enable more awesome stuff" OFF)
option(AwesomeProject_SUPERBUILD "Build ${PROJECT_NAME} and the projects it depends on." ON)
[...]
if(AwesomeProject_SUPERBUILD)
include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake")
return()
endif()
find_package(Foo REQUIRED)
add_library(AwesomeLib ....)
target_library_libraries(AwesomeLib PUBLIC Foo)
[...]
那么,在SuperBuild.cmake 文件中,你大概会有这两个调用:
ExternalProject_Add(Foo
GIT_REPOSITORY "git://github.com/Foo/Foo"
GIT_TAG "123456"
SOURCE_DIR ${CMAKE_BINARY_DIR}/Foo
BINARY_DIR ${CMAKE_BINARY_DIR}/Foo-build
CMAKE_CACHE_ARGS
-DFOO_ENABLE_BAR:BOOL=1
INSTALL_COMMAND ""
)
ExternalProject_Add(AwesomeProject
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
BINARY_DIR ${CMAKE_BINARY_DIR}/AwesomeProject-build
DOWNLOAD_COMMAND ""
UPDATE_COMMAND ""
CMAKE_CACHE_ARGS
-Foo_DIR:PATH=${CMAKE_BINARY_DIR}/Foo-build
-DAwesome_ENABLE_EXTRA:BOOL=${Awesome_ENABLE_EXTRA}
INSTALL_COMMAND ""
)
这意味着您通常的构建树现在将在子目录AwesomeProject-build 中找到。
注意Foo-build和AwesomeProject-build是两个独立的构建树,它们之间的链接
就是上面讨论的配置文件包。
这可以通过使用-Foo_DIR:PATH=${CMAKE_BINARY_DIR}/Foo-build 配置AwesomeProject 子项目来实现
和调用find_package(Foo REQUIRED)。
如果您使用 VisualStudio 之类的工具,您可以打开在这些子目录中的任何一个中找到的解决方案文件。
了解更多关于外部项目的信息:https://cmake.org/cmake/help/latest/module/ExternalProject.html
还有更多细节,但我希望这能让您更好地了解什么是可能的。
【讨论】: