具有冗余依赖项的子模块的 CMake 项目
CMake projects with submodules that have redudant dependencies
我有以下项目结构:
root-project/
|-> CMakeLists.txt
|-> src/
|-> foo.cpp
|-> include/
|-> foo.hpp
|-> test/
|-> test_foo.cpp
|-> googletest/
|-> CMakeLists.txt
|-> ...
|-> libs/
|-> my-lib/
|-> CMakeLists.txt
|-> src/
|-> bar.cpp
|-> include/
|-> bar.hpp
|-> test/
|-> test_bar.cpp
|-> googletest/
|-> CMakeLists.txt
|-> ...
root-project
构建了一个名为 foo
的可执行文件,它依赖于库 my-lib
。 root-project
和 my-lib
都使用 googletest
进行测试,它包含在 git-submodule
.
中
我已经接受了使用 git-submodule
会有多余的 googletest
目录的事实。然而,问题是简单地使用 add_subdirectory
连接整个项目将最终得到多个 gtest
目标。
我的问题:有没有办法让 root-project
构建 my-lib
并且只看到目标 my-lib
而不是测试目标googletest
? (即,在构建期间冗余 googletest
可以是 "hidden" 吗?)
我的第二个问题:鉴于我的 CMake 菜鸟身份,我是否以有缺陷的方式组织了这些项目?是否有更受欢迎的方式来组织避免此问题的项目?欢迎提出建设性的 CMake 建议!
我不确定这是否是这种情况下的最佳做法,但我最终在我的项目中所做的是编写一个 cmake 模块 gtest.cmake
以将 gtest 添加到我的项目中。在该模块中,我检查它是否已经添加,如果是,我只是重新使用生成的 ${gtest_SOURCE_DIR}
变量:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.3)
project(myProject CXX)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake")
include(gtest)
# myTarget definition
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
target_link_libraries(myTarget gtest gtest_main)
cmake/gtest.cmake:
if(gtest_SOURCE_DIR)
message(STATUS "gtest variables already defined. Skipping.")
else()
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/external/gtest")
endif()
编辑:
我对测试目标所做的通常是使用 add_executable
的 EXCLUDE_FROM_ALL
属性 从常规构建中排除它们。您还可以将该标志用于 add_subdirectory
,这样只有当您想要 运行 测试时,您才可以包含 gtest。例如,您可以在 CMakeLists.txt:
中写这样的内容
# set ${TESTS_SOURCE_FILES} with the source files of your tests
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
add_executable(${PROJECT_NAME}_tests EXCLUDE_FROM_ALL ${TESTS_SOURCE_FILES})
target_link_libraries(${PROJECT_NAME}_tests gtest gtest_main)
并让你的 cmake/gtest.cmake
写成这样:
if(gtest_SOURCE_DIR)
message(STATUS "gtest variables already defined. Skipping.")
else()
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/external/gtest" EXCLUDE_FROM_ALL)
endif()
然后,只有当您 make
明确测试目标时,通过 运行ning make myProject_tests
它将只构建它需要的测试目标。
希望对您有所帮助!
我有以下项目结构:
root-project/
|-> CMakeLists.txt
|-> src/
|-> foo.cpp
|-> include/
|-> foo.hpp
|-> test/
|-> test_foo.cpp
|-> googletest/
|-> CMakeLists.txt
|-> ...
|-> libs/
|-> my-lib/
|-> CMakeLists.txt
|-> src/
|-> bar.cpp
|-> include/
|-> bar.hpp
|-> test/
|-> test_bar.cpp
|-> googletest/
|-> CMakeLists.txt
|-> ...
root-project
构建了一个名为 foo
的可执行文件,它依赖于库 my-lib
。 root-project
和 my-lib
都使用 googletest
进行测试,它包含在 git-submodule
.
我已经接受了使用 git-submodule
会有多余的 googletest
目录的事实。然而,问题是简单地使用 add_subdirectory
连接整个项目将最终得到多个 gtest
目标。
我的问题:有没有办法让 root-project
构建 my-lib
并且只看到目标 my-lib
而不是测试目标googletest
? (即,在构建期间冗余 googletest
可以是 "hidden" 吗?)
我的第二个问题:鉴于我的 CMake 菜鸟身份,我是否以有缺陷的方式组织了这些项目?是否有更受欢迎的方式来组织避免此问题的项目?欢迎提出建设性的 CMake 建议!
我不确定这是否是这种情况下的最佳做法,但我最终在我的项目中所做的是编写一个 cmake 模块 gtest.cmake
以将 gtest 添加到我的项目中。在该模块中,我检查它是否已经添加,如果是,我只是重新使用生成的 ${gtest_SOURCE_DIR}
变量:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.3)
project(myProject CXX)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake")
include(gtest)
# myTarget definition
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
target_link_libraries(myTarget gtest gtest_main)
cmake/gtest.cmake:
if(gtest_SOURCE_DIR)
message(STATUS "gtest variables already defined. Skipping.")
else()
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/external/gtest")
endif()
编辑:
我对测试目标所做的通常是使用 add_executable
的 EXCLUDE_FROM_ALL
属性 从常规构建中排除它们。您还可以将该标志用于 add_subdirectory
,这样只有当您想要 运行 测试时,您才可以包含 gtest。例如,您可以在 CMakeLists.txt:
# set ${TESTS_SOURCE_FILES} with the source files of your tests
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
add_executable(${PROJECT_NAME}_tests EXCLUDE_FROM_ALL ${TESTS_SOURCE_FILES})
target_link_libraries(${PROJECT_NAME}_tests gtest gtest_main)
并让你的 cmake/gtest.cmake
写成这样:
if(gtest_SOURCE_DIR)
message(STATUS "gtest variables already defined. Skipping.")
else()
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/external/gtest" EXCLUDE_FROM_ALL)
endif()
然后,只有当您 make
明确测试目标时,通过 运行ning make myProject_tests
它将只构建它需要的测试目标。
希望对您有所帮助!