C++:包括目录,但只允许一个文件夹可见(对于 Eigen)
C++: Include directory, but only allow one folder to be visible (for Eigen)
假设有人想要将一个大型 open-source 项目作为子模块包含在存储库 (myrepo
) 中。对于此示例,我们以 Eigen 为例。没问题,我可以
git submodule add https://gitlab.com/libeigen/eigen.git
这会创建一个 eigen
子目录,其中包含很多子文件夹:
myrepo/
eigen/
bench
blas
ci
cmake
debug
demos
doc
Eigen
failtest
lapack
scripts
test
...
然而,为了使用 Eigen 库,真正需要的只是文件夹 myrepo/eigen/Eigen
的内容。所以我们只希望该文件夹对 compiler/linker 可见。但是,为了清楚起见,我更希望包含该文件夹内的文件,例如 myrepo/eigen/Eigen/Dense
,如
#include <Eigen/Dense>
两个明显的次优解是
添加myrepo/eigen
作为包含目录,包含
等文件
#include <Eigen/Dense>
将myrepo/eigen/Eigen
添加为包含目录,并包含
等文件
#include <Dense>
这两种方法都有明显的缺点。具体来说,
使用 myrepo/eigen
作为包含目录会将所有其他文件暴露给 compiler/linker。由于 repo 的大小以及其中包含的所有其他文件,我觉得这是命名空间冲突或类似问题的定时炸弹。例如,现在编译器看到有一个 test/
子文件夹,其内容现在是免费游戏。
包括 headers 而没有 Eigen
序言是我认为代码清晰度的灾难。
#include <Dense> // ¯\_(ツ)_/¯ Where did this come from???
我知道的唯一其他选择是分叉或复制原始存储库并删除所有我想排除的东西。
我主要关心的是将 Eigen 添加为子模块。因此,如果有 best-practice 将其作为子模块包含在内的建议,我也很感兴趣。我知道有一个与此主题相关的未解决问题:https://gitlab.com/libeigen/eigen/-/issues/1133
虽然编译器只会看到明确提供给他的文件,但 CMake 会从子模块文件夹中获取 CMakeLists.txt
并执行可能很混乱的构建步骤。
CMake 是一个非常强大的构建系统,因此它可以让您以优雅的方式处理这些问题。 CMake 能够将外部项目作为库包含在内。这与简单的 add_subdirectory()
不同。对于外部项目,CMake 实际上会为该项目创建另一个构建实例,并会使用构建步骤来下载、配置、构建和安装项目,然后构建才能开始在主要目标上工作。
有了外部构建,您可以构建库并将其安装在一个临时文件夹中(相对于您的源,或相对于您的构建文件夹)。这样,您就可以只使用来自外部项目的构建过程的产品。
这里值得一提的是,外部项目可以使用不同的构建系统,而不是必须的 CMake,这使得它更加强大。
您可以使用我为 Eigen 库准备的这个小演示作为外部项目将其添加到您的构建中。
该项目有 eigen
作为由 git submodule add https://gitlab.com/libeigen/eigen.git
初始化的项目根目录中的子模块
CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(EigenTest)
include(ExternalProject)
set(CMAKE_CXX_STANDARD 17)
set(EIGEN_INCLUDE eigen_install)
ExternalProject_Add(eigen
SOURCE_DIR ${CMAKE_SOURCE_DIR}/eigen
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} -DINCLUDE_INSTALL_DIR=${EIGEN_INCLUDE}
)
ExternalProject_Get_Property(eigen install_dir)
add_executable(EigenTest main.cpp)
add_dependencies(EigenTest eigen)
target_include_directories(EigenTest PRIVATE ${install_dir})
target_include_directories(EigenTest PRIVATE ${CMAKE_BINARY_DIR}/${EIGEN_INCLUDE})
main.cpp
#include <iostream>
#include <Eigen/Dense>
using Eigen::MatrixXd;
int main() {
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
std::cout << m << std::endl;
return 0;
}
这会在构建目标中创建一个名为 eigen_install
的文件夹,其中将包含构建库的最终产品。请注意,在我的简单示例中,您应该避免使用 eigen
作为目标,因为在构建库期间,CMake 在构建目标中将创建一个 eigen
文件夹。您可以通过 ExternalProject
的额外配置来控制它,但这超出了这个问题的范围。
中详细了解 ExternalProject
模块的附加功能
使用 git submodule
和 CMake 的 ExternalProject
两个强大的概念,您可以完全控制构建过程,只需选择要构建的外部项目的哪个分支以及使用哪种配置参数。同时,您将保持所需的构建分离(源代码分离)。
您可以创建一个单独的空目录 include
并将软 link Eigen
指向 myrepo/eigen/Eigen
。然后将 include
添加为搜索目录,而不是 myrepo/eigen
.
Git “按原样”跟踪软件 link,将 link 的路径存储在存储库中,并在克隆时重新创建 link。它不会尝试验证 link 是否有效。
只要:
- link 是作为同一存储库中 file/directory 的相对路径给出的
- 存储库克隆在能够容纳软 links
的文件系统上
一切都会按预期进行。
如果您无法完成其他答案,例如您的文件系统不支持链接,您可以将“Eigen”目录复制到一个单独的目录
file(COPY
${CMAKE_CURRENT_SOURCE_DIR}/lib/eigen/Eigen
${CMAKE_BUILD_FILES_DIRECTOR}/lib/Eigen
)
// And then link to that folder
include_directories(${CMAKE_BUILD_FILES_DIRECTOR}/lib/Eigen)
我没有尝试过这段代码,但理论上应该可以。它应该有点健壮,即使它有点 hacky。
Suppose one wants to include a large open-source project as a submodule
However, for the purpose of using the Eigen library, all one really needs is the contents of the folder
您要么希望将整个项目包含为子模块,要么不希望。子模块专门用于包含整个源代码树。如果您不想逐字包含整个源代码树,请不要使用子模块。
3rd 方库的常用方法是克隆自己的 repo,构建可安装的工件(public headers 和静态 and/or 动态库),然后安装它们在一些第 3 方图书馆区域。然后你编译并 link 你的代码来对抗它们。第 3 方库是您的构建系统引用的外部依赖项,而不是您自己的存储库的一部分。
我想分享一下我在上一个项目中是如何解决类似问题的——希望对你有用。我的要求是相似的——只公开 headers 和 libs 打算公开的第三方项目的开发人员。我的项目本身使用 cmake,但这不是必需的。
我在我的 repo 的根目录下创建了一个 deps 文件夹,并在里面放了一个 CMakeLists.txt。这不是构建主项目,而是拉下我关心的依赖项,构建它们(他们的开发人员打算构建的方式),并安装它们以供我的项目使用。看起来像这样:
myrepo/
deps/
CMakeLists.txt
与@jordanvrtanoski 类似,我使用了 ExternalProject 功能,但我写了一个宏,这让我更简洁一些。我最初与 add_subdirectory
作斗争,最终我找到了他的建议来避免 add_subdirectory
声音 :)。与@jordanvrtanoski 不同,我更喜欢对依赖项使用单独的 CMakeLists.txt,即使我的 top-level 项目是基于 cmake 的。否则,我发现 cmake 会做一些检查,确认依赖项已正确安装,并从我的内部开发循环中抢走时间......我还发现,在内部循环之外安装依赖项可以让你可靠地做 find_package
在 cmake 中,不用担心在 top-level 项目中分别指定 include 和 lib 目录。
这是其中的一个片段 CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(deps)
include(ExternalProject)
function(install NAME GIT_REPO GIT_TAG)
ExternalProject_Add(
${NAME}
GIT_REPOSITORY ${GIT_REPO}
GIT_TAG ${GIT_TAG}
PREFIX ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}
${ARGN}
CMAKE_ARGS
--config ${CMAKE_BUILD_TYPE}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>
-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/install
)
endfunction()
install(gflags
https://github.com/gflags/gflags.git
v2.2.0
CMAKE_ARGS
-DREGISTER_INSTALL_PREFIX=FALSE
-DGFLAGS_BUILD_TESTING=FALSE)
install(glog
https://github.com/google/glog.git
v0.4.0
DEPENDS gflags
CMAKE_ARGS
-DBUILD_TESTING=FALSE)
您可以通过以下方式触发安装:
cmake -DCMAKE_BUILD_TYPE=Debug --log-level=VERBOSE -G "NMake Makefiles" ..
cmake --build . --config Debug
请注意,您可以分别进行调试和发布构建,并且工件最终位于 deps
下的单独文件夹中。
我希望这里有一些要拆开的东西,但都是有充分理由的。您可以看到,一旦宏不受影响,安装 gflags
的代码片段就非常少了。它为 cmake 指定了 repo、标签和一些 gflags-specific 选项。安装 glog
的以下步骤同样简单,但我将其作为传递依赖项的示例包含在内...您可以看到它声明了对 gflags
的依赖项,这很重要...因为 glog
可以在有或没有 gflags
支持的情况下安装,我想要后者。
另一个需要注意的更普遍的事情是宏覆盖了依赖项的 CMAKE_INSTALL_PREFIX
,因此它被安装在 myrepo/deps/Debug/install/...
之类的地方。安装本身会创建 include
和 lib
,有时还会在下面创建 bin
文件夹,具体取决于原始开发人员的意图。
当你编译 myrepo
时,你需要将编译器指向安装目录,具体告诉它在 myrepo/deps/Debug/install/include
中查找 headers 并在 myrepo/deps/Debug/install/libs
中查找库。如何执行此操作取决于您用于主项目的构建系统。如果是 cmake(像我的),这对我有用:
...
set(CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/deps/${CMAKE_BUILD_TYPE}/install)
find_package(gflags REQUIRED NO_MODULE)
find_package(glog REQUIRED NO_MODULE)
add_binary(mybinary
...)
target_link_libraries(mybinary
glog::glog)
我希望这对你有用,我真的在寻找解决过这个问题的其他人的反馈。我发现 C/C++ 中的整个依赖基础结构比为 Java(例如 Maven)或 JavaScript(例如 NPM)或 Python(例如 PyPI),考虑到它已经存在了多久,这确实有点令人惊讶。
我想 Eigen 在它的安装脚本中会在 .../deps/Debug/include/Eigen
下创建 Eigen 目录,你的梦想就会成真:)
请注意,此方法不使用 git 子模块,但依赖项的源代码最终会被 ExternalProject
模块提取并包含在 .../deps/Debug/src
下...所以你仍然可以去那里检查它们。如果您选择在 .../deps/CMakeLists.txt
中使用不同的标签或 rev 并如上所述重新运行安装部分,则可以轻松更新依赖项的修订版。
一些离别的想法和花絮,有些重要,但不值得在主要论述中占有一席之地...
- 如果你需要安装一些特殊的东西,你可以放弃我的宏,它不基于 cmake,不存储在 git,甚至使用预构建的二进制文件......该宏旨在解决对我来说最常见的快乐路径,但在所有其他情况下你可以直接使用
ExternalProject_Add
。
有一次我不得不在 Windows 上为 OpenSSL 执行此操作,我在我的 deps/CMakeLists.txt
:
中使用了这个片段
ExternalProject_Add(
openssl
URL https://github.com/CristiFati/Prebuilt-Binaries/raw/master/OpenSSL/v1.1.1/OpenSSL-1.1.1i-Win-pc064.zip
PREFIX ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E echo installing from `<SOURCE_DIR>/OpenSSL/1.1.1i` to `${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/install`
COMMAND ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/OpenSSL/1.1.1i/include ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/install/include
COMMAND ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/OpenSSL/1.1.1i/lib ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/install/lib
COMMAND ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/OpenSSL/1.1.1i/bin ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/install/bin
)
- 我很幸运
googletest
但它更喜欢静态库,他们的 cmake 脚本做了一些漂亮的 low-level 手术来注入正确的编译器选项来做那些当你有一个大的时候会混淆的事情一组依赖项,所以我必须向它传递一个标志以容忍共享库:
install(googletest
https://github.com/google/googletest.git
release-1.10.0
CMAKE_ARGS
#FIXME: figure out how to make all of them static!!!
-Dgtest_force_shared_crt=ON)
- 我的待办事项列表中的一件事是尝试将此技术应用于容器并使用标准安装目录,而不是像本例中那样被覆盖的目录。我会在这些日子里完成它。
如果您有任何问题,请告诉我!
假设有人想要将一个大型 open-source 项目作为子模块包含在存储库 (myrepo
) 中。对于此示例,我们以 Eigen 为例。没问题,我可以
git submodule add https://gitlab.com/libeigen/eigen.git
这会创建一个 eigen
子目录,其中包含很多子文件夹:
myrepo/
eigen/
bench
blas
ci
cmake
debug
demos
doc
Eigen
failtest
lapack
scripts
test
...
然而,为了使用 Eigen 库,真正需要的只是文件夹 myrepo/eigen/Eigen
的内容。所以我们只希望该文件夹对 compiler/linker 可见。但是,为了清楚起见,我更希望包含该文件夹内的文件,例如 myrepo/eigen/Eigen/Dense
,如
#include <Eigen/Dense>
两个明显的次优解是
添加
等文件myrepo/eigen
作为包含目录,包含#include <Eigen/Dense>
将
等文件myrepo/eigen/Eigen
添加为包含目录,并包含#include <Dense>
这两种方法都有明显的缺点。具体来说,
使用
myrepo/eigen
作为包含目录会将所有其他文件暴露给 compiler/linker。由于 repo 的大小以及其中包含的所有其他文件,我觉得这是命名空间冲突或类似问题的定时炸弹。例如,现在编译器看到有一个test/
子文件夹,其内容现在是免费游戏。包括 headers 而没有
Eigen
序言是我认为代码清晰度的灾难。#include <Dense> // ¯\_(ツ)_/¯ Where did this come from???
我知道的唯一其他选择是分叉或复制原始存储库并删除所有我想排除的东西。
我主要关心的是将 Eigen 添加为子模块。因此,如果有 best-practice 将其作为子模块包含在内的建议,我也很感兴趣。我知道有一个与此主题相关的未解决问题:https://gitlab.com/libeigen/eigen/-/issues/1133
虽然编译器只会看到明确提供给他的文件,但 CMake 会从子模块文件夹中获取 CMakeLists.txt
并执行可能很混乱的构建步骤。
CMake 是一个非常强大的构建系统,因此它可以让您以优雅的方式处理这些问题。 CMake 能够将外部项目作为库包含在内。这与简单的 add_subdirectory()
不同。对于外部项目,CMake 实际上会为该项目创建另一个构建实例,并会使用构建步骤来下载、配置、构建和安装项目,然后构建才能开始在主要目标上工作。
有了外部构建,您可以构建库并将其安装在一个临时文件夹中(相对于您的源,或相对于您的构建文件夹)。这样,您就可以只使用来自外部项目的构建过程的产品。
这里值得一提的是,外部项目可以使用不同的构建系统,而不是必须的 CMake,这使得它更加强大。
您可以使用我为 Eigen 库准备的这个小演示作为外部项目将其添加到您的构建中。
该项目有 eigen
作为由 git submodule add https://gitlab.com/libeigen/eigen.git
CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(EigenTest)
include(ExternalProject)
set(CMAKE_CXX_STANDARD 17)
set(EIGEN_INCLUDE eigen_install)
ExternalProject_Add(eigen
SOURCE_DIR ${CMAKE_SOURCE_DIR}/eigen
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} -DINCLUDE_INSTALL_DIR=${EIGEN_INCLUDE}
)
ExternalProject_Get_Property(eigen install_dir)
add_executable(EigenTest main.cpp)
add_dependencies(EigenTest eigen)
target_include_directories(EigenTest PRIVATE ${install_dir})
target_include_directories(EigenTest PRIVATE ${CMAKE_BINARY_DIR}/${EIGEN_INCLUDE})
main.cpp
#include <iostream>
#include <Eigen/Dense>
using Eigen::MatrixXd;
int main() {
MatrixXd m(2,2);
m(0,0) = 3;
m(1,0) = 2.5;
m(0,1) = -1;
m(1,1) = m(1,0) + m(0,1);
std::cout << m << std::endl;
return 0;
}
这会在构建目标中创建一个名为 eigen_install
的文件夹,其中将包含构建库的最终产品。请注意,在我的简单示例中,您应该避免使用 eigen
作为目标,因为在构建库期间,CMake 在构建目标中将创建一个 eigen
文件夹。您可以通过 ExternalProject
的额外配置来控制它,但这超出了这个问题的范围。
ExternalProject
模块的附加功能
使用 git submodule
和 CMake 的 ExternalProject
两个强大的概念,您可以完全控制构建过程,只需选择要构建的外部项目的哪个分支以及使用哪种配置参数。同时,您将保持所需的构建分离(源代码分离)。
您可以创建一个单独的空目录 include
并将软 link Eigen
指向 myrepo/eigen/Eigen
。然后将 include
添加为搜索目录,而不是 myrepo/eigen
.
Git “按原样”跟踪软件 link,将 link 的路径存储在存储库中,并在克隆时重新创建 link。它不会尝试验证 link 是否有效。 只要:
- link 是作为同一存储库中 file/directory 的相对路径给出的
- 存储库克隆在能够容纳软 links 的文件系统上
一切都会按预期进行。
如果您无法完成其他答案,例如您的文件系统不支持链接,您可以将“Eigen”目录复制到一个单独的目录
file(COPY
${CMAKE_CURRENT_SOURCE_DIR}/lib/eigen/Eigen
${CMAKE_BUILD_FILES_DIRECTOR}/lib/Eigen
)
// And then link to that folder
include_directories(${CMAKE_BUILD_FILES_DIRECTOR}/lib/Eigen)
我没有尝试过这段代码,但理论上应该可以。它应该有点健壮,即使它有点 hacky。
Suppose one wants to include a large open-source project as a submodule
However, for the purpose of using the Eigen library, all one really needs is the contents of the folder
您要么希望将整个项目包含为子模块,要么不希望。子模块专门用于包含整个源代码树。如果您不想逐字包含整个源代码树,请不要使用子模块。
3rd 方库的常用方法是克隆自己的 repo,构建可安装的工件(public headers 和静态 and/or 动态库),然后安装它们在一些第 3 方图书馆区域。然后你编译并 link 你的代码来对抗它们。第 3 方库是您的构建系统引用的外部依赖项,而不是您自己的存储库的一部分。
我想分享一下我在上一个项目中是如何解决类似问题的——希望对你有用。我的要求是相似的——只公开 headers 和 libs 打算公开的第三方项目的开发人员。我的项目本身使用 cmake,但这不是必需的。
我在我的 repo 的根目录下创建了一个 deps 文件夹,并在里面放了一个 CMakeLists.txt。这不是构建主项目,而是拉下我关心的依赖项,构建它们(他们的开发人员打算构建的方式),并安装它们以供我的项目使用。看起来像这样:
myrepo/
deps/
CMakeLists.txt
与@jordanvrtanoski 类似,我使用了 ExternalProject 功能,但我写了一个宏,这让我更简洁一些。我最初与 add_subdirectory
作斗争,最终我找到了他的建议来避免 add_subdirectory
声音 :)。与@jordanvrtanoski 不同,我更喜欢对依赖项使用单独的 CMakeLists.txt,即使我的 top-level 项目是基于 cmake 的。否则,我发现 cmake 会做一些检查,确认依赖项已正确安装,并从我的内部开发循环中抢走时间......我还发现,在内部循环之外安装依赖项可以让你可靠地做 find_package
在 cmake 中,不用担心在 top-level 项目中分别指定 include 和 lib 目录。
这是其中的一个片段 CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(deps)
include(ExternalProject)
function(install NAME GIT_REPO GIT_TAG)
ExternalProject_Add(
${NAME}
GIT_REPOSITORY ${GIT_REPO}
GIT_TAG ${GIT_TAG}
PREFIX ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}
${ARGN}
CMAKE_ARGS
--config ${CMAKE_BUILD_TYPE}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded$<$<CONFIG:Debug>:Debug>
-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/install
)
endfunction()
install(gflags
https://github.com/gflags/gflags.git
v2.2.0
CMAKE_ARGS
-DREGISTER_INSTALL_PREFIX=FALSE
-DGFLAGS_BUILD_TESTING=FALSE)
install(glog
https://github.com/google/glog.git
v0.4.0
DEPENDS gflags
CMAKE_ARGS
-DBUILD_TESTING=FALSE)
您可以通过以下方式触发安装:
cmake -DCMAKE_BUILD_TYPE=Debug --log-level=VERBOSE -G "NMake Makefiles" ..
cmake --build . --config Debug
请注意,您可以分别进行调试和发布构建,并且工件最终位于 deps
下的单独文件夹中。
我希望这里有一些要拆开的东西,但都是有充分理由的。您可以看到,一旦宏不受影响,安装 gflags
的代码片段就非常少了。它为 cmake 指定了 repo、标签和一些 gflags-specific 选项。安装 glog
的以下步骤同样简单,但我将其作为传递依赖项的示例包含在内...您可以看到它声明了对 gflags
的依赖项,这很重要...因为 glog
可以在有或没有 gflags
支持的情况下安装,我想要后者。
另一个需要注意的更普遍的事情是宏覆盖了依赖项的 CMAKE_INSTALL_PREFIX
,因此它被安装在 myrepo/deps/Debug/install/...
之类的地方。安装本身会创建 include
和 lib
,有时还会在下面创建 bin
文件夹,具体取决于原始开发人员的意图。
当你编译 myrepo
时,你需要将编译器指向安装目录,具体告诉它在 myrepo/deps/Debug/install/include
中查找 headers 并在 myrepo/deps/Debug/install/libs
中查找库。如何执行此操作取决于您用于主项目的构建系统。如果是 cmake(像我的),这对我有用:
...
set(CMAKE_PREFIX_PATH ${CMAKE_SOURCE_DIR}/deps/${CMAKE_BUILD_TYPE}/install)
find_package(gflags REQUIRED NO_MODULE)
find_package(glog REQUIRED NO_MODULE)
add_binary(mybinary
...)
target_link_libraries(mybinary
glog::glog)
我希望这对你有用,我真的在寻找解决过这个问题的其他人的反馈。我发现 C/C++ 中的整个依赖基础结构比为 Java(例如 Maven)或 JavaScript(例如 NPM)或 Python(例如 PyPI),考虑到它已经存在了多久,这确实有点令人惊讶。
我想 Eigen 在它的安装脚本中会在 .../deps/Debug/include/Eigen
下创建 Eigen 目录,你的梦想就会成真:)
请注意,此方法不使用 git 子模块,但依赖项的源代码最终会被 ExternalProject
模块提取并包含在 .../deps/Debug/src
下...所以你仍然可以去那里检查它们。如果您选择在 .../deps/CMakeLists.txt
中使用不同的标签或 rev 并如上所述重新运行安装部分,则可以轻松更新依赖项的修订版。
一些离别的想法和花絮,有些重要,但不值得在主要论述中占有一席之地...
- 如果你需要安装一些特殊的东西,你可以放弃我的宏,它不基于 cmake,不存储在 git,甚至使用预构建的二进制文件......该宏旨在解决对我来说最常见的快乐路径,但在所有其他情况下你可以直接使用
ExternalProject_Add
。
有一次我不得不在 Windows 上为 OpenSSL 执行此操作,我在我的 deps/CMakeLists.txt
:
ExternalProject_Add(
openssl
URL https://github.com/CristiFati/Prebuilt-Binaries/raw/master/OpenSSL/v1.1.1/OpenSSL-1.1.1i-Win-pc064.zip
PREFIX ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E echo installing from `<SOURCE_DIR>/OpenSSL/1.1.1i` to `${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/install`
COMMAND ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/OpenSSL/1.1.1i/include ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/install/include
COMMAND ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/OpenSSL/1.1.1i/lib ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/install/lib
COMMAND ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/OpenSSL/1.1.1i/bin ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/install/bin
)
- 我很幸运
googletest
但它更喜欢静态库,他们的 cmake 脚本做了一些漂亮的 low-level 手术来注入正确的编译器选项来做那些当你有一个大的时候会混淆的事情一组依赖项,所以我必须向它传递一个标志以容忍共享库:
install(googletest
https://github.com/google/googletest.git
release-1.10.0
CMAKE_ARGS
#FIXME: figure out how to make all of them static!!!
-Dgtest_force_shared_crt=ON)
- 我的待办事项列表中的一件事是尝试将此技术应用于容器并使用标准安装目录,而不是像本例中那样被覆盖的目录。我会在这些日子里完成它。
如果您有任何问题,请告诉我!