【问题标题】:Use CppADCodeGen with CMake FetchContent or ExternalProject将 CppADCodeGen 与 CMake FetchContent 或 ExternalProject 一起使用
【发布时间】:2021-12-09 15:25:13
【问题描述】:

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

也就是说,这是我的问题。我想在使用 CMake FetchContent 的项目中使用 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 来获取Eigen。所以我决定使用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)

然后,为了使用Eigen,我必须将${CMAKE_BINARY_DIR}/eigen/include/eigen3 添加到target_include_directories 命令。这与我使用FetchContent 时形成对比,我只需要将Eigen3::Eigen 添加到target_link_libraries 命令。 ExternalProject 无法使用这种方法:这种说法正确吗?如果没有,我该如何实现?

【问题讨论】:

  • 问题是CppADCodeGen 需要已经安装的CppAD 版本(我们可以在CppADCodeGen 的CMakeLists.txt 中的FIND_PACKAGE 语句中看到它)。要快速解决此问题,您可以在重新加载 cmake 之前手动安装 CppAD。对于更强大的解决方案,我建议使用更复杂的依赖管理系统,例如 conan 或使用 cmake 的 ExternalProject mofule 安装项目。
  • @dlivshen 谢谢你的回答。我怀疑这个问题与CppAD 没有在系统范围内安装有关。但是,这是我想避免的:我希望用户只需要 CMake、编译器和 Git 来处理我的项目。如果您声称 ExternalProject 是实现我想要的唯一可能的解决方案,那么,如果您提交一个干净、有效的“现代 CMake”答案,我将非常乐意接受它!
  • @dlivshen 仅供参考,我为这个问题开始了 50 声望赏金!
  • 很抱歉我有一些忙碌的日子延迟回复.. 希望对您有所帮助。

标签: c++ c git cmake autodiff


【解决方案1】:

问题概述

从您提供的输出中可以看出,有两个问题:

  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 来实现的。

  • 我们确保cppadcodgen 成功找到CppAD,方法是将CPPAD_HOME 缓存变量设置为包含目录(即${CMAKE_BINARY_DIR}/cppad/include),并将此目标设置为在使用@ 安装CppAD 之后运行987654347@ 选项。

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

  • 最后,我们通过设置CMAKE_INSTALL_PREFIX 变量将cppadcodgen 安装到构建目录中。

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

更多关于ExternalProject的信息可以在Cmake的documentation中找到。

使用依赖

为了使用依赖,我们必须进行一些修改。 我们以CppADCodeGenwiki page的主文件为例,尝试用我们的解决方案编译它:

ma​​in.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
)

CMakeLists.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

解决方案基于this 发帖。

【讨论】:

  • 非常感谢您的精彩回答!我已经测试了这段代码,要在不同的目标中使用 CppADCodeGen 我必须将 ${CMAKE_BINARY_DIR}/cppad/include${CMAKE_BINARY_DIR}/cppadcodegen/include 添加到他们的 target_include_directories 命令中。它是否正确?我以为我应该只需要将cppadcodegen 添加到他们的target_link_libraries 命令中,但事实并非如此:确实,当我运行CMake 时,它​​找不到包含目录(而当我通过target_include_directories 添加它们时它确实如此)如上)!
  • 另外,当我将cppadcodegen 添加到target_link_libraries 时,我收到此错误:[build] /usr/bin/ld: cannot find -lcppadcodegen。换句话说,通过target_include_directories 的方法是否正确?或者应该target_link_libraries 是要走的路,但我在其他地方犯了错误?
  • 查看我编辑的答案,我希望它能更好地解释问题。
  • 您的回答完美!我曾尝试使用 ExternalProject_Add 对 Eigen 库重复相同的过程,但我不确定我是否正确执行。我已经编辑了我的问题:请确认我的理解是否正确?
猜你喜欢
  • 1970-01-01
  • 2018-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-08
  • 2019-01-07
  • 1970-01-01
相关资源
最近更新 更多