我正在尝试以最干净、最现代的 cmake 方式将外部依赖项添加到我的新 cmake 项目中。\n我想在配置期间下载这些依赖项。我的问题是来自外部依赖项的所有目标始终都是导入的。这会垃圾邮件我在例如 Clion 中的配置,我希望默认情况下更干净,但正如你所看到的,我有几个来自 gtest、googlebenchmark、eigen 和 spdlog 的无用目标,如下图所示。该项目应在 Windows 和 Linux 上编译。
\n\n所以我的问题是如何防止这种情况发生?
\n我观看了几个现代 cmake 视频,例如\n https://www.youtube.com/watch?v=eC9-iRN2b04以及https://cliutils.gitlab.io/modern-cmake/的来源。
\n我的项目文件夹结构如下
\n.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 CMakeLists.txt\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Ikarus\n| \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 CMakeLists.txt\n| \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 addexternalLibs.cmake\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 Ikarus\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 [...]\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 problems\n| \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 CMakeLists.txt\n| \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 [.cpp files]\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 tests\n| \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 CMakeLists.txt\n| \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 [.cpp files]\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 benchmarks\n| \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 CMakeLists.txt\n| \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 [.cpp files]\nRun Code Online (Sandbox Code Playgroud)\n我有一个顶级CMakeLists.txt如下
cmake_minimum_required(VERSION 3.16)\nproject(Ikarus)\n\nadd_subdirectory(Ikarus)\nadd_subdirectory(problems)\nadd_subdirectory(tests)\nadd_subdirectory(benchmarks)\nRun Code Online (Sandbox Code Playgroud)\nIkarus在我想要构建的文件夹中,它应该由、和Ikarus_lib中定义的目标使用。problemstestsbenchmarks
该文件Ikarus/CMakeLists.txt如下所示
file(GLOB_RECURSE IKARUS_CPP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} CONFIGURE_DEPENDS *.cpp )\n\n\nadd_library(${PROJECT_NAME}_lib STATIC)\ntarget_sources(${PROJECT_NAME}_lib PRIVATE ${IKARUS_CPP_SOURCES})\n\ninclude(addexternalLibs.cmake)\n\ntarget_include_directories(${PROJECT_NAME}_lib PUBLIC src)\n\ntarget_link_libraries(${PROJECT_NAME}_lib PUBLIC Eigen3::Eigen\n PUBLIC spdlog::spdlog)\nRun Code Online (Sandbox Code Playgroud)\n现在我想谈谈Ikarus/addexternalLibs.cmake导入外部依赖项的文件的内容。在我导入 googletest 和 googlebenchmark 的基准测试和测试中也会出现类似的困难,但我认为我会将自己限制在 Ikarus_lib 情况下,因为困难是相同的。
由于我想在配置期间下载我的依赖项,我使用https://cmake.org/cmake/help/latest/module/FetchContent.html找到了很好的解决方案
\n结果是Ikarus/addexternalLibs.cmake:
include(FetchContent)\n\nmessage("Configure Eigen: ")\n\nFetchContent_Declare(\n eigen\n GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git\n GIT_TAG 3.4\n GIT_SHALLOW TRUE\n GIT_PROGRESS TRUE\n)\noption(EIGEN_BUILD_DOC OFF)\noption(BUILD_TESTING OFF)\noption(EIGEN_LEAVE_TEST_IN_ALL_TARGET OFF)\noption(EIGEN_BUILD_PKGCONFIG OFF)\nFetchContent_MakeAvailable(eigen)\n\nmessage("====================================")\nmessage("Configure spdlog: ")\n\nFetchContent_Declare(\n spdlog\n GIT_REPOSITORY https://github.com/gabime/spdlog.git\n GIT_TAG v1.8.5\n GIT_SHALLOW TRUE\n GIT_PROGRESS TRUE\n)\noption(SPDLOG_BUILD_SHARED OFF)\noption(SPDLOG_BUILD_ALL OFF)\nFetchContent_MakeAvailable(spdlog)\nRun Code Online (Sandbox Code Playgroud)\n这个解决方案有效,我设法使用选项停用一些目标EIGEN_BUILD_DOC OFF...。但我仍然有很多不同的无用目标,如上图所示,无法使用包的选项来停用它们。
我尝试了其他一些方法,例如使用EXCLUDE_FROM_ALL https://cmake.org/cmake/help/latest/prop_tgt/EXCLUDE_FROM_ALL.html如下
FetchContent_Declare(\n eigen\n GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git\n GIT_TAG 3.4\n GIT_SHALLOW TRUE\n GIT_PROGRESS TRUE\n)\noption(EIGEN_BUILD_DOC OFF)\noption(BUILD_TESTING OFF)\noption(EIGEN_LEAVE_TEST_IN_ALL_TARGET OFF)\noption(EIGEN_BUILD_PKGCONFIG OFF)\n\nFetchContent_GetProperties(eigen)\nif(NOT eigen_POPULATED)\n FetchContent_Populate(Eigen)\n add_subdirectory(${eigen_SOURCE_DIR} ${eigen_BINARY_DIR} EXCLUDE_FROM_ALL)\nendif()\nRun Code Online (Sandbox Code Playgroud)\n这也有效,但也添加了我不想要的所有目标。因此,EXCLUDE_FROM_ALL它并不像我认为的那样工作。
另一种使用方法EXCLUDE_FROM_ALL可能是
include(FetchContent)\n\nmessage("Configure Eigen: ")\n\nFetchContent_Declare(\n eigen\n GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git\n GIT_TAG 3.4\n GIT_SHALLOW TRUE\n GIT_PROGRESS TRUE\n)\noption(EIGEN_BUILD_DOC OFF)\noption(BUILD_TESTING OFF)\noption(EIGEN_LEAVE_TEST_IN_ALL_TARGET OFF)\noption(EIGEN_BUILD_PKGCONFIG OFF)\nFetchContent_MakeAvailable(eigen)\nset_target_properties(eigen PROPERTIES EXCLUDE_FROM_ALL TRUE)\nRun Code Online (Sandbox Code Playgroud)\n这也不会改变行为。
\n我也尝试CPMAddPackage过https://github.com/cpm-cmake/CPM.cmake
CPMAddPackage(\n GITLAB_REPOSITORY libeigen/eigen\n GIT_TAG 3.4\n OPTIONS "EIGEN_BUILD_DOC NO"\n "BUILD_TESTING NO"\n "EIGEN_LEAVE_TEST_IN_ALL_TARGET YES"\n "EIGEN_BUILD_PKGCONFIG NO"\n)\nRun Code Online (Sandbox Code Playgroud)\n这也有效,但也添加了所有目标。
\n所以现在我不知道还能尝试什么,我想我只会保留目标并将它们从我的 Clion 配置界面中删除,并希望它们不会再次出现。但我仍然想了解我错过了什么。我认为这是一个常见问题,解决方案应该很容易?
\n此外,我知道我可以下载例如 eigen 并用于include_directories(...)自动添加没有目标的标头。但一方面,这不是https://www.youtube.com/watch?v=eC9-iRN2b04中宣传的现代 cmake ,其中使用include_directories被称为反模式,人们应该“以模块的方式思考”。另一方面,这对于非标头的包没有帮助。
那么如何优雅地解决这个问题呢?另外,我很感激对我对 Cmake 的(糟糕)使用的所有其他评论。谢谢!
\n