将 CppADCodeGen 与 CMake FetchContent 或 ExternalProject 结合使用



我不擅长CMake,我找不到关于如何使用其FetchContent功能的良好解释。事实上,大多数存储库似乎需要不同的处理方式,而这种处理的规则超出了我的理解。

也就是说,这是我的问题。我想使用 CMakeFetchContent在我的项目中使用CppADCodeGen。这是我的代码:

include(FetchContent)
message(STATUS "Fetching eigen...")
FetchContent_Declare(
eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG 3.4.0
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE)
option(EIGEN_BUILD_DOC OFF)
option(BUILD_TESTING OFF)
option(EIGEN_LEAVE_TEST_IN_ALL_TARGET OFF)
option(EIGEN_BUILD_PKGCONFIG OFF)
FetchContent_MakeAvailable(eigen)
message(STATUS "Fetching cppad...")
FetchContent_Declare(
cppad
GIT_REPOSITORY https://github.com/coin-or/CppAD.git
GIT_TAG 20210000.8
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE)
FetchContent_MakeAvailable(cppad)
message(STATUS "Fetching cppadcodgen...")
FetchContent_Declare(
cppadcodgen
GIT_REPOSITORY https://github.com/joaoleal/CppADCodeGen.git
GIT_TAG v2.4.3
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE)
FetchContent_MakeAvailable(cppadcodgen)

这是输出和我得到的错误:

[cmake] Not searching for unused variables given on the command line.
[cmake] -- The C compiler identification is GNU 11.1.0
[cmake] -- The CXX compiler identification is GNU 11.1.0
[cmake] -- Detecting C compiler ABI info
[cmake] -- Detecting C compiler ABI info - done
[cmake] -- Check for working C compiler: /bin/x86_64-linux-gnu-gcc-11 - skipped
[cmake] -- Detecting C compile features
[cmake] -- Detecting C compile features - done
[cmake] -- Detecting CXX compiler ABI info
[cmake] -- Detecting CXX compiler ABI info - done
[cmake] -- Check for working CXX compiler: /bin/x86_64-linux-gnu-g++-11 - skipped
[cmake] -- Detecting CXX compile features
[cmake] -- Detecting CXX compile features - done
[cmake] -- Fetching eigen...
[cmake] -- Performing Test EIGEN_COMPILER_SUPPORT_CPP11
[cmake] -- Performing Test EIGEN_COMPILER_SUPPORT_CPP11 - Success
[cmake] -- Performing Test COMPILER_SUPPORT_std=cpp03
[cmake] -- Performing Test COMPILER_SUPPORT_std=cpp03 - Success
[cmake] -- Performing Test standard_math_library_linked_to_automatically
[cmake] -- Performing Test standard_math_library_linked_to_automatically - Success
[cmake] -- Standard libraries to link to explicitly: none
[cmake] -- Performing Test COMPILER_SUPPORT_WERROR
[cmake] -- Performing Test COMPILER_SUPPORT_WERROR - Success
[cmake] -- Performing Test COMPILER_SUPPORT_pedantic
[cmake] -- Performing Test COMPILER_SUPPORT_pedantic - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wall
[cmake] -- Performing Test COMPILER_SUPPORT_Wall - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wextra
[cmake] -- Performing Test COMPILER_SUPPORT_Wextra - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wundef
[cmake] -- Performing Test COMPILER_SUPPORT_Wundef - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wcastalign
[cmake] -- Performing Test COMPILER_SUPPORT_Wcastalign - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wcharsubscripts
[cmake] -- Performing Test COMPILER_SUPPORT_Wcharsubscripts - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wnonvirtualdtor
[cmake] -- Performing Test COMPILER_SUPPORT_Wnonvirtualdtor - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wunusedlocaltypedefs
[cmake] -- Performing Test COMPILER_SUPPORT_Wunusedlocaltypedefs - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wpointerarith
[cmake] -- Performing Test COMPILER_SUPPORT_Wpointerarith - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wwritestrings
[cmake] -- Performing Test COMPILER_SUPPORT_Wwritestrings - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wformatsecurity
[cmake] -- Performing Test COMPILER_SUPPORT_Wformatsecurity - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wshorten64to32
[cmake] -- Performing Test COMPILER_SUPPORT_Wshorten64to32 - Failed
[cmake] -- Performing Test COMPILER_SUPPORT_Wlogicalop
[cmake] -- Performing Test COMPILER_SUPPORT_Wlogicalop - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wenumconversion
[cmake] -- Performing Test COMPILER_SUPPORT_Wenumconversion - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wcpp11extensions
[cmake] -- Performing Test COMPILER_SUPPORT_Wcpp11extensions - Failed
[cmake] -- Performing Test COMPILER_SUPPORT_Wdoublepromotion
[cmake] -- Performing Test COMPILER_SUPPORT_Wdoublepromotion - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wshadow
[cmake] -- Performing Test COMPILER_SUPPORT_Wshadow - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wnopsabi
[cmake] -- Performing Test COMPILER_SUPPORT_Wnopsabi - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wnovariadicmacros
[cmake] -- Performing Test COMPILER_SUPPORT_Wnovariadicmacros - Success
[cmake] -- Performing Test COMPILER_SUPPORT_Wnolonglong
[cmake] -- Performing Test COMPILER_SUPPORT_Wnolonglong - Success
[cmake] -- Performing Test COMPILER_SUPPORT_fnochecknew
[cmake] -- Performing Test COMPILER_SUPPORT_fnochecknew - Success
[cmake] -- Performing Test COMPILER_SUPPORT_fnocommon
[cmake] -- Performing Test COMPILER_SUPPORT_fnocommon - Success
[cmake] -- Performing Test COMPILER_SUPPORT_fstrictaliasing
[cmake] -- Performing Test COMPILER_SUPPORT_fstrictaliasing - Success
[cmake] -- Performing Test COMPILER_SUPPORT_wd981
[cmake] -- Performing Test COMPILER_SUPPORT_wd981 - Failed
[cmake] -- Performing Test COMPILER_SUPPORT_wd2304
[cmake] -- Performing Test COMPILER_SUPPORT_wd2304 - Failed
[cmake] -- Performing Test COMPILER_SUPPORT_STRICTANSI
[cmake] -- Performing Test COMPILER_SUPPORT_STRICTANSI - Failed
[cmake] -- Performing Test COMPILER_SUPPORT_Qunusedarguments
[cmake] -- Performing Test COMPILER_SUPPORT_Qunusedarguments - Failed
[cmake] -- Performing Test COMPILER_SUPPORT_ansi
[cmake] -- Performing Test COMPILER_SUPPORT_ansi - Success
[cmake] -- Performing Test COMPILER_SUPPORT_OPENMP
[cmake] -- Performing Test COMPILER_SUPPORT_OPENMP - Success
[cmake] -- Looking for a Fortran compiler
[cmake] -- Looking for a Fortran compiler - /usr/bin/f95
[cmake] -- The Fortran compiler identification is GNU 9.3.0
[cmake] -- Detecting Fortran compiler ABI info
[cmake] -- Detecting Fortran compiler ABI info - done
[cmake] -- Check for working Fortran compiler: /usr/bin/f95 - skipped
[cmake] -- Checking whether /usr/bin/f95 supports Fortran 90
[cmake] -- Checking whether /usr/bin/f95 supports Fortran 90 - yes
[cmake] -- Found unsuitable Qt version "5.12.8" from /usr/bin/qmake
[cmake] -- Qt4 not found, so disabling the mandelbrot and opengl demos
[cmake] -- Found CHOLMOD: /usr/include/suitesparse  
[cmake] -- Found UMFPACK: /usr/include/suitesparse  
[cmake] -- Found KLU: /usr/include/suitesparse  
[cmake] -- Performing Test SUPERLU_HAS_GLOBAL_MEM_USAGE_T
[cmake] -- Performing Test SUPERLU_HAS_GLOBAL_MEM_USAGE_T - Success
[cmake] -- Performing Test SUPERLU_HAS_CLEAN_ENUMS
[cmake] -- Performing Test SUPERLU_HAS_CLEAN_ENUMS - Success
[cmake] -- Performing Test SUPERLU_HAS_GLOBALLU_T
[cmake] -- Performing Test SUPERLU_HAS_GLOBALLU_T - Success
[cmake] -- Found SuperLU: /usr/include/superlu (found suitable version "5.0", minimum required is "4.0") 
[cmake] -- Checking for one of the modules 'hwloc'
[cmake] -- Performing Test HAVE_HWLOC_PARENT_MEMBER
[cmake] -- Performing Test HAVE_HWLOC_PARENT_MEMBER - Success
[cmake] -- Performing Test HAVE_HWLOC_CACHE_ATTR
[cmake] -- Performing Test HAVE_HWLOC_CACHE_ATTR - Success
[cmake] -- Performing Test HAVE_HWLOC_OBJ_PU
[cmake] -- Performing Test HAVE_HWLOC_OBJ_PU - Success
[cmake] -- Looking for hwloc_bitmap_free in hwloc
[cmake] -- Looking for hwloc_bitmap_free in hwloc - found
[cmake] -- A version of Pastix has been found but pastix_nompi.h does not exist in the include directory. Because Eigen tests require a version without MPI, we disable the Pastix backend.
[cmake] -- 
[cmake] -- Configured Eigen 3.4.0
[cmake] -- 
[cmake] -- Available targets (use: make TARGET):
[cmake] -- ---------+--------------------------------------------------------------
[cmake] -- Target   |   Description
[cmake] -- ---------+--------------------------------------------------------------
[cmake] -- install  | Install Eigen. Headers will be installed to:
[cmake] --          |     <CMAKE_INSTALL_PREFIX>/<INCLUDE_INSTALL_DIR>
[cmake] --          |   Using the following values:
[cmake] --          |     CMAKE_INSTALL_PREFIX: /usr/local
[cmake] --          |     INCLUDE_INSTALL_DIR:  include/eigen3
[cmake] --          |   Change the install location of Eigen headers using:
[cmake] --          |     cmake . -DCMAKE_INSTALL_PREFIX=yourprefix
[cmake] --          |   Or:
[cmake] --          |     cmake . -DINCLUDE_INSTALL_DIR=yourdir
[cmake] -- doc      | Generate the API documentation, requires Doxygen & LaTeX
[cmake] -- blas     | Build BLAS library (not the same thing as Eigen)
[cmake] -- uninstall| Remove files installed by the install target
[cmake] -- ---------+--------------------------------------------------------------
[cmake] -- 
[cmake] -- Fetching cppad...
[cmake] CMake Deprecation Warning at build/_deps/cppad-src/CMakeLists.txt:20 (CMAKE_MINIMUM_REQUIRED):
[cmake]   Compatibility with CMake < 2.8.12 will be removed from a future version of
[cmake]   CMake.
[cmake] 
[cmake]   Update the VERSION argument <min> value or use a ...<max> suffix to tell
[cmake]   CMake that the project does not need compatibility with older versions.
[cmake] 
[cmake] 
[cmake] CMake Warning (dev) at build/_deps/cppad-src/CMakeLists.txt:35 (PROJECT):
[cmake]   Policy CMP0048 is not set: project() command manages VERSION variables.
[cmake]   Run "cmake --help-policy CMP0048" for policy details.  Use the cmake_policy
[cmake]   command to set the policy and suppress this warning.
[cmake] 
[cmake]   The following variable(s) would be set to empty:
[cmake] 
[cmake]     PROJECT_VERSION
[cmake]     PROJECT_VERSION_MAJOR
[cmake]     PROJECT_VERSION_MINOR
[cmake]     PROJECT_VERSION_PATCH
[cmake] This warning is for project developers.  Use -Wno-dev to suppress it.
[cmake] 
[cmake] -- Performing Test cppad_cplusplus_201100_ok
[cmake] -- Performing Test cppad_cplusplus_201100_ok - Success
[cmake] -- cppad_cplusplus_201100_ok = 1
[cmake] -- cmake_install_datadir = share
[cmake] -- cmake_install_docdir = NOTFOUND
[cmake] -- cmake_install_includedirs = include
[cmake] -- cmake_install_libdirs = lib
[cmake] -- cppad_prefix = /usr/local
[cmake] -- cppad_postfix = NOTFOUND
[cmake] -- cppad_cxx_flags = 
[cmake] -- cppad_profile_flag = NOTFOUND
[cmake] -- cppad_testvector = cppad
[cmake] -- cppad_max_num_threads = 48
[cmake] -- cppad_tape_id_type = unsigned int
[cmake] -- cppad_tape_addr_type = unsigned int
[cmake] -- cppad_debug_which = debug_all
[cmake] -- include_eigen = false
[cmake] -- include_adolc = false
[cmake] -- include_ipopt = false
[cmake] -- include_cppadcg = false
[cmake] -- colpack_prefix = NOTFOUND
[cmake] -- sacado_prefix = NOTFOUND
[cmake] -- fadbad_prefix = NOTFOUND
[cmake] -- CMAKE_CXX_FLAGS_DEBUG = -g
[cmake] -- CMAKE_CXX_FLAGS_RELEASE = -O3 -DNDEBUG
[cmake] -- Found OpenMP_C: -fopenmp (found version "4.5") 
[cmake] -- Found OpenMP_CXX: -fopenmp (found version "4.5") 
[cmake] -- Found OpenMP: TRUE (found version "4.5")  
[cmake] -- Found Boost: /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake (found version "1.71.0") found components: thread 
[cmake] -- boost_prefix = /usr
[cmake] -- Found /usr/include
[cmake] -- Found /usr/lib
[cmake] -- Performing Test compiler_has_conversion_warn
[cmake] -- Performing Test compiler_has_conversion_warn - Success
[cmake] -- compiler_has_conversion_warn = 1
[cmake] -- cppad_boostvector = 0
[cmake] -- cppad_cppadvector = 1
[cmake] -- cppad_eigenvector = 0
[cmake] -- cppad_stdvector = 0
[cmake] -- cppad_cplusplus_201100_ok = 1
[cmake] -- Performing Test cppad_has_gettimeofday
[cmake] -- Performing Test cppad_has_gettimeofday - Success
[cmake] -- cppad_has_gettimeofday = 1
[cmake] -- Performing Test cppad_tape_id_type_is_unsigned
[cmake] -- Performing Test cppad_tape_id_type_is_unsigned - Success
[cmake] -- cppad_tape_id_type_is_unsigned = 1
[cmake] -- Performing Test cppad_tape_addr_type_is_unsigned
[cmake] -- Performing Test cppad_tape_addr_type_is_unsigned - Success
[cmake] -- cppad_tape_addr_type_is_unsigned = 1
[cmake] -- Performing Test cppad_max_num_threads_is_integer_ge_4
[cmake] -- Performing Test cppad_max_num_threads_is_integer_ge_4 - Success
[cmake] -- Performing Test cppad_has_mkstemp
[cmake] -- Performing Test cppad_has_mkstemp - Success
[cmake] -- cppad_has_mkstemp = 1
[cmake] -- Performing Test cppad_has_tmpnam_s
[cmake] -- Performing Test cppad_has_tmpnam_s - Failed
[cmake] -- cppad_has_tmpnam_s = 0
[cmake] -- soversion = 712.8
[cmake] -- Not Windows system so building shared cppad_lib
[cmake] -- make check_example_abs_normal: available
[cmake] -- make check_example_atomic_two: available
[cmake] -- make check_example_atomic_three: available
[cmake] -- make check_example_chkpoint_two: available
[cmake] -- make check_example_graph: available
[cmake] -- make check_example_general: available
[cmake] -- make check_example_get_started: available
[cmake] -- make check_example_json: available
[cmake] -- make check_example_multi_thread_openmp: available
[cmake] -- pthread library path = /usr/lib/x86_64-linux-gnu/libpthread.so
[cmake] -- Looking for pthread_barrier_wait in pthread
[cmake] -- Looking for pthread_barrier_wait in pthread - found
[cmake] -- make check_example_multi_thread_pthread: available
[cmake] -- Performing Test boost_multi_thread_ok
[cmake] -- Performing Test boost_multi_thread_ok - Success
[cmake] -- make check_example_multi_thread_bthread: available
[cmake] -- make check_example_multi_thread: available
[cmake] -- make check_example_optimize: available
[cmake] -- make check_example_print_for: available
[cmake] -- make check_example_sparse: available
[cmake] -- make check_example_utility: available
[cmake] -- make check_example: available
[cmake] -- make check_introduction: available
[cmake] -- make check_test_more_deprecated_atomic_two: available
[cmake] -- make check_test_more_deprecated_chkpoint_one: available
[cmake] -- make check_test_more_deprecated: available
[cmake] -- make check_det_by_minor_c: available
[cmake] -- make check_det_by_minor_cpp: available
[cmake] -- make check_test_more_compare_c: available
[cmake] -- make check_test_more_debug_rel: available
[cmake] -- make check_test_more_cppad_for_tmb: available
[cmake] -- make check_test_more_general: available
[cmake] -- make check_test_more: available
[cmake] -- make check_speed_cppad: available
[cmake] -- make check_speed_double: available
[cmake] -- make check_speed_example: available
[cmake] -- make check_speed_program: available
[cmake] -- make check_speed_xpackage: available
[cmake] -- make check_speed: available
[cmake] -- make check: avialable
[cmake] CMake Error at build/_deps/cppad-src/CMakeLists.txt:452 (ADD_CUSTOM_TARGET):
[cmake]   ADD_CUSTOM_TARGET cannot create target "uninstall" because another target
[cmake]   with the same name already exists.  The existing target is a custom target
[cmake]   created in source directory
[cmake]   "project/build/_deps/eigen-src".  See documentation for
[cmake]   policy CMP0002 for more details.
[cmake] 
[cmake] 
[cmake] -- Fetching cppadcodgen...
[cmake] CMake Deprecation Warning at build/_deps/cppadcodgen-src/CMakeLists.txt:18 (CMAKE_MINIMUM_REQUIRED):
[cmake]   Compatibility with CMake < 2.8.12 will be removed from a future version of
[cmake]   CMake.
[cmake] 
[cmake]   Update the VERSION argument <min> value or use a ...<max> suffix to tell
[cmake]   CMake that the project does not need compatibility with older versions.
[cmake] 
[cmake] 
[cmake] CMake Warning (dev) at build/_deps/cppadcodgen-src/CMakeLists.txt:20 (PROJECT):
[cmake]   Policy CMP0048 is not set: project() command manages VERSION variables.
[cmake]   Run "cmake --help-policy CMP0048" for policy details.  Use the cmake_policy
[cmake]   command to set the policy and suppress this warning.
[cmake] 
[cmake]   The following variable(s) would be set to empty:
[cmake] 
[cmake]     PROJECT_VERSION
[cmake]     PROJECT_VERSION_MAJOR
[cmake]     PROJECT_VERSION_MINOR
[cmake]     PROJECT_VERSION_PATCH
[cmake] This warning is for project developers.  Use -Wno-dev to suppress it.
[cmake] 
[cmake] -- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1") 
[cmake] -- Found CppAD: project/build/_deps/cppad-src/include (Required is at least version "20200000.1") 
[cmake] CMake Error at build/_deps/cppadcodgen-src/cmake/FindCppAD.cmake:86 (FILE):
[cmake]   FILE STRINGS file
[cmake]   "project/build/_deps/cppadcodgen-src/CPPAD_INCLUDE_DIR-NOTFOUND/cppad/configure.hpp"
[cmake]   cannot be read.
[cmake] Call Stack (most recent call first):
[cmake]   build/_deps/cppadcodgen-src/CMakeLists.txt:42 (FIND_PACKAGE)
[cmake] 
[cmake] 
[cmake] CMake Error at build/_deps/cppadcodgen-src/cmake/FindCppAD.cmake:99 (MESSAGE):
[cmake]   Found CppAD version '' but at least version '20200000.1' is required
[cmake] Call Stack (most recent call first):
[cmake]   build/_deps/cppadcodgen-src/CMakeLists.txt:42 (FIND_PACKAGE)
[cmake] 
[cmake] 
[cmake] -- Configuring incomplete, errors occurred!

有人能够在他们的机器上实现上述目标吗?如果是,他们会分享他们是如何做到的吗?在上面的错误消息中有几个错误,我已经尝试了一些解决方案,但没有一个奏效 - 我不会列出它们,因为它们没有用提及!

编辑

@dlivshen 当我将我的库与一个更大的项目集成时,由于目标名称冲突,我遇到了更多问题。这是因为我用FetchContent来获得特征。所以我决定使用ExternalProject获取它,为此,我将这些行添加到您在解决方案中提出的CMakeLists.txt.in文件中:

ExternalProject_Add(
eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG 3.4.0
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
CMAKE_CACHE_ARGS
-DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_BINARY_DIR}/eigen
-DEIGEN_BUILD_DOC
OFF
-DBUILD_TESTING
OFF
-DEIGEN_LEAVE_TEST_IN_ALL_TARGET
OFF
-DEIGEN_BUILD_PKGCONFIG
OFF)

然后,为了使用特征,我必须向target_include_directories命令添加${CMAKE_BINARY_DIR}/eigen/include/eigen3。这与我使用FetchContent时形成鲜明对比,在target_link_libraries命令中,我只需要向Eigen3::Eigen添加。这种方法在ExternalProject中是不可能的:这个说法正确吗?如果没有,我该如何实现它?

问题概述

如您提供的输出所示,存在 2 个问题:

  1. 可能CppADeigen之间存在目标名称冲突。他们都有uninstall目标。可以在这里看到:
[cmake] CMake Error at build/_deps/cppad-src/CMakeLists.txt:452 (ADD_CUSTOM_TARGET):
[cmake]   ADD_CUSTOM_TARGET cannot create target "uninstall" because another target
[cmake]   with the same name already exists.  The existing target is a custom target
[cmake]   created in source directory
[cmake]   "project/build/_deps/eigen-src".  
  1. cppadcodgen需要已安装的CppAD版本。从错误消息中可以看出,它告诉我们找到了无效版本:
[cmake] CMake Error at build/_deps/cppadcodgen-src/cmake/FindCppAD.cmake:99 (MESSAGE):
[cmake]   Found CppAD version '' but at least version '20200000.1' is required
[cmake] Call Stack (most recent call first):
[cmake]   build/_deps/cppadcodgen-src/CMakeLists.txt:42 (FIND_PACKAGE)

溶液

不幸的是,目前我们不能使用FetchContent来处理这些问题,因为:

  1. 没有任何机制可以让我们区分冲突的目标(例如,"命名空间"前缀可能是一种解决方案,然后可能有 2 个目标eigen:uninstallcppad:uninstall)。
  2. 我们无法在配置步骤中构建依赖目标。

相反,我们将使用ExternalProject模块。这是一个可能的解决方案:

include(FetchContent)
message(STATUS "Fetching eigen...")
FetchContent_Declare(
eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG 3.4.0
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE)
option(EIGEN_BUILD_DOC OFF)
option(BUILD_TESTING OFF)
option(EIGEN_LEAVE_TEST_IN_ALL_TARGET OFF)
option(EIGEN_BUILD_PKGCONFIG OFF)
FetchContent_MakeAvailable(eigen)
include(ExternalProject)
ExternalProject_Add(cppad
GIT_REPOSITORY    https://github.com/coin-or/CppAD.git
GIT_TAG           20210000.8
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
CMAKE_CACHE_ARGS -Dcppad_prefix:STRING=${CMAKE_BINARY_DIR}/cppad
)
ExternalProject_Add(cppadcodgen
GIT_REPOSITORY    https://github.com/joaoleal/CppADCodeGen.git
GIT_TAG           v2.4.3
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
CMAKE_CACHE_ARGS -DCPPAD_HOME:STRING=${CMAKE_BINARY_DIR}/cppad/include -DGOOGLETEST_GIT:BOOL=ON -DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_BINARY_DIR}/cppadcodegen
DEPENDS cppad
)

我使用了以下命令来测试它:

mkdir cmake-build
cd !$
cmake ..
cmake --build .

解释

大多数参数与FetchContent中使用的完全相同。唯一的区别是:

  • 我们将cppad安装到构建目录而不是系统范围的目录,因此整个过程将是独立的。这是通过在CMAKE_CACHE_ARGS选项中将cppad_prefix缓存变量设置为${CMAKE_BINARY_DIR}/cppad来实现的。

  • 通过将CPPAD_HOME缓存变量设置为 include 目录(${CMAKE_BINARY_DIR}/cppad/include),并将此目标设置为使用DEPENDS选项安装CppAD后运行,确保cppadcodgen成功查找CppAD

  • cppadcodgen也设置了测试目标,如果找不到Google测试,它将失败。 幸运的是,他们提供了一个选项,可以使用我们设置为ONGOOGLETEST_GIT选项下载Google测试。

  • 最后,我们通过设置变量来设置在构建目录中安装cppadcodgenCMAKE_INSTALL_PREFIX

请注意,我没有碰过eigen因为我不知道确切的用法是什么,而且它并没有使构建失败。如果需要,可以很容易地修改它以ExternalProject如上面写的那样。

有关ExternalProject的更多信息可以在 Cmake 的文档中找到。

使用依赖项

为了使用依赖项,我们必须执行一些修改。 让我们以 wiki 页面CppADCodeGen主文件为例,并尝试使用我们的解决方案对其进行编译:

主.cpp

#include <iosfwd>
#include <vector>
#include <cppad/cg.hpp>
using namespace CppAD;
using namespace CppAD::cg;
int main() {
// use a special object for source code generation
typedef CG<double> CGD;
typedef AD<CGD> ADCG;
/***************************************************************************
*                               the model
**************************************************************************/
// independent variable vector
CppAD::vector<ADCG> x(2);
x[0] = 2.;
x[1] = 3.;
Independent(x);
// dependent variable vector 
CppAD::vector<ADCG> y(1);
// the model
ADCG a = x[0] / 1. + x[1] * x[1];
y[0] = a / 2;
ADFun<CGD> fun(x, y); // the model tape
/***************************************************************************
*                        Generate the C source code
**************************************************************************/
/**
* start the special steps for source code generation for a Jacobian
*/
CodeHandler<double> handler;
CppAD::vector<CGD> indVars(2);
handler.makeVariables(indVars);
CppAD::vector<CGD> jac = fun.SparseJacobian(indVars);
LanguageC<double> langC("double");
LangCDefaultVariableNameGenerator<double> nameGen;
std::ostringstream code;
handler.generateCode(code, langC, jac, nameGen);
std::cout << code.str();
}

请注意,ExternalProject_Add命令在构建时运行,我们希望在 Cmake 重新加载期间已经找到我们的依赖项。所以不幸的是,我们将不得不做一个肮脏的技巧来强制ExternalProject_Add在 Cmake 重新加载时间上运行:

  1. 我们将ExternalProject_Add命令移动到帮助程序CMakeLists.txt.in文件中。
  2. 我们将配置CMakeLists.txt.in,以便库的输出路径将保留在我们的构建目录中。
  3. 我们将调用execute_process(在 cmake 重新加载时运行)来执行帮助程序的构建过程CMakeLists.txt.in
  4. 我们将找到我们的库并使用它们。请注意,我们不能使用现代 Cmake 目标语法,因为整个过程是在子进程中运行的,我们无法访问创建的目标。但即使我们没有在子进程中运行它,ExternalProject目标的类型也是实用程序,不能在target_link_libraries等命令中使用。因此,我们将使用为依赖项创建的自定义路径,并将它们传递给target_link_librariestarget_include_directories命令。

最终结果如下所示:

CMakeLists.txt.in

cmake_minimum_required(VERSION 2.8)
project(deps-download NONE)
include(ExternalProject)
ExternalProject_Add(cppad
GIT_REPOSITORY    https://github.com/coin-or/CppAD.git
GIT_TAG           20210000.8
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
CMAKE_CACHE_ARGS -Dcppad_prefix:STRING=${CMAKE_BINARY_DIR}/cppad
)
ExternalProject_Add(cppadcodgen
GIT_REPOSITORY    https://github.com/joaoleal/CppADCodeGen.git
GIT_TAG           v2.4.3
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
CMAKE_CACHE_ARGS -DCPPAD_HOME:STRING=${CMAKE_BINARY_DIR}/cppad/include -DGOOGLETEST_GIT:BOOL=ON -DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_BINARY_DIR}/cppadcodegen
DEPENDS cppad
)

CMakeList.txt

include(FetchContent)
message(STATUS "Fetching eigen...")
FetchContent_Declare(
eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG 3.4.0
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE)
option(EIGEN_BUILD_DOC OFF)
option(BUILD_TESTING OFF)
option(EIGEN_LEAVE_TEST_IN_ALL_TARGET OFF)
option(EIGEN_BUILD_PKGCONFIG OFF)
FetchContent_MakeAvailable(eigen)
# Configure the helper CMakeLists with the dependencies
configure_file(CMakeLists.txt.in ${CMAKE_BINARY_DIR}/deps-build/CMakeLists.txt)
# Build it
execute_process(COMMAND ${CMAKE_COMMAND} .
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps-build)
execute_process(COMMAND ${CMAKE_COMMAND} --build .
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps-build)       
# Find cppad_lib's path
find_library(cppad_lib cppad_lib HINTS ${CMAKE_BINARY_DIR}/cppad/lib REQUIRED)

# Create our target
add_executable(main
main.cpp)

target_link_libraries(main ${cppad_lib})
target_include_directories(main PUBLIC 
${CMAKE_BINARY_DIR}/cppad/include
${CMAKE_BINARY_DIR}/cppadcodegen/include)

和以前一样,我使用以下命令对其进行了测试:

mkdir cmake-build
cd !$
cmake ..
cmake --build .
./main

解决方案基于这篇文章。