CMake:如何build立外部项目并包括他们的目标

我有一个项目A导出一个静态库作为目标:

install(TARGETS alib DESTINATION lib EXPORT project_a-targets) install(EXPORT project_a-targets DESTINATION lib/alib) 

现在我想使用项目A作为项目B的外部项目,并包含其构build的目标:

 ExternalProject_Add(project_a URL ...project_a.tar.gz PREFIX ${CMAKE_CURRENT_BINARY_DIR}/project_a CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> ) include(${CMAKE_CURRENT_BINARY_DIR}/lib/project_a/project_a-targets.cmake) 

问题是当项目B的CMakeLists运行时,包含文件还不存在。

有没有办法让包括依赖外部项目正在build设?

我想你在这里混合了两种不同的范例。

如您所述,高度灵活的ExternalProject模块在构build时运行它的命令,所以您不能直接使用Project A的导入文件,因为它只是在安装了Project A之后才创build的。

如果要include项目A的导入文件,则必须在调用项目B的CMakeLists.txt之前手动安装项目find_library find_package这种方式添加的任何其他第三方依赖项或通过find_file / find_library / find_package

如果你想使用ExternalProject_Add ,你需要在CMakeLists.txt中添加如下内容:

 ExternalProject_Add(project_a URL ...project_a.tar.gz PREFIX ${CMAKE_CURRENT_BINARY_DIR}/project_a CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> ) include(${CMAKE_CURRENT_BINARY_DIR}/lib/project_a/project_a-targets.cmake) ExternalProject_Get_Property(project_a install_dir) include_directories(${install_dir}/include) add_dependencies(project_b_exe project_a) target_link_libraries(project_b_exe ${install_dir}/lib/alib.lib) 

这个post有一个合理的答案:

CMakeLists.txt.in

 cmake_minimum_required(VERSION 2.8.2) project(googletest-download NONE) include(ExternalProject) ExternalProject_Add(googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG master SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src" BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" ) 

CMakeLists.txt

 # Download and unpack googletest at configure time configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt) execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download ) execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download ) # Prevent GoogleTest from overriding our compiler/linker options # when building with Visual Studio set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # Add googletest directly to our build. This adds # the following targets: gtest, gtest_main, gmock # and gmock_main add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src ${CMAKE_BINARY_DIR}/googletest-build) # The gtest/gmock targets carry header search path # dependencies automatically when using CMake 2.8.11 or # later. Otherwise we have to add them here ourselves. if (CMAKE_VERSION VERSION_LESS 2.8.11) include_directories("${gtest_SOURCE_DIR}/include" "${gmock_SOURCE_DIR}/include") endif() # Now simply link your own targets against gtest, gmock, # etc. as appropriate 

但是,这看起来很诡异。 我想提出一个替代解决scheme – 使用Git子模块。

 cd MyProject/dependencies/gtest git submodule add https://github.com/google/googletest.git cd googletest git checkout release-1.8.0 cd ../../.. git add * git commit -m "Add googletest" 

然后在MyProject/dependencies/gtest/CMakeList.txt你可以这样做:

 cmake_minimum_required(VERSION 3.3) if(TARGET gtest) # To avoid diamond dependencies; may not be necessary depending on you project. return() endif() add_subdirectory("googletest") 

我还没有广泛的尝试过,但似乎更清洁。

编辑:这种方法有一个缺点:子目录可能运行你不想要的install()命令。 这篇文章有一个方法来禁用他们,但它是越野车,并没有为我工作。

编辑2:如果使用add_subdirectory("googletest" EXCLUDE_FROM_ALL)则表示默认情况下不会使用子目录中的install()命令。

您也可以在二级make过程中强制构build相关目标

看到我的答案在一个相关的话题。