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相关目标
看到我的答案在一个相关的话题。