使用CMake仅构建一次外部库 [英] Build external library only once with CMake
问题描述
我的C ++项目包含第三方库的源代码(当前作为git子模块)。
My C++ projects includes the source code of a third-party library (currently as a git submodule).
此库是由我们的主要CMakelist添加到项目中的通过使用 add_subdirectory
,然后将该库与主要目标链接。
This library is added to the project by our main CMakelists through the use of add_subdirectory
, and then the library is linked with the main target.
以下是简化版本我当前的Cmake文件中的文件:
Here is a reduced version of my current Cmake file :
add_subdirectory(foo)
set(FOO_LIBRARY ${CMAKE_CURRENT_SOURCE_DIR}/libfoo/libfoo.so)
add_executable(target main.cpp)
add_dependencies(target foo)
target_link_libraries(target ${FOO_LIBRARY})
该库需要很长时间才能构建,并且由于我不更改其代码,因此只需要构建一次(每个构建配置)。但是,当我清理并重建代码时,也会清理库文件并重新编译它们。
This library takes a long time to build and, since I don't change its code I need it built only once (per build configuration). But when I clean and rebuild my code it also cleans the library files and recompile them.
我试图设置属性 CLEAN_NO_CUSTOM
在库目录中,但根据文档仅适用于自定义命令目标。
I have tried to set the property CLEAN_NO_CUSTOM
in the library's directory, but according to the documentation it only works for custom command targets.
CMake中是否存在一种机制,可以通过该机制指定仅一次生成该库目标,或者替代地不被清理
吗?
Is there a mechanism in CMake through which it is possible to specify that this library target needs to be generated only once, or alternatively not cleaned by make clean
?
推荐答案
正如@Tsyvarev所说,在您的案例 ExternalProject_Add
比 add_subdirectory
更好。当您希望项目成为构建系统的重要组成部分时, add_subdirectory
很好,因为它创建的目标可以在 target_link_libraries()
命令,而 ExternalProject_Add
创建的目标则不能。
As @Tsyvarev said, in your case ExternalProject_Add
is better than add_subdirectory
. add_subdirectory
is good when you want project to be essential part of your build system because target it creates can be used in in the right-hand-side of the target_link_libraries()
command while target created by ExternalProject_Add
cannot.
我在一个项目中使用的方法。您尝试找到所需的库并仅在找不到时才构建它。我使用INTERFACE库将FOO_EXTERNAL转换为 target_link_libraries()
可接受的目标。
Here is the approach I used in one of my projects. You try to find required library and build it only if it was not found. I use INTERFACE library to turn FOO_EXTERNAL into a target acceptable by target_link_libraries()
.
add_library(foo INTERFACE)
find_package(foo ${FOO_VER})
if(NOT foo_FOUND)
include(ExternalProject)
include(GNUInstallDirs)
ExternalProject_Add(FOO_EXTERNAL
SOURCE_DIR "${FOO_SOURCE_DIR}"
BINARY_DIR "${FOO_BINARY_DIR}"
INSTALL_DIR "${FOO_INSTALL_DIR}"
CMAKE_ARGS "-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}"
"-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}"
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
"-DCMAKE_INSTALL_PREFIX=${FOO_INSTALL_DIR}"
)
add_dependencies(foo FOO_EXTERNAL)
set(foo_LIBRARY
"${FOO_INSTALL_DIR}/${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}foo${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(foo_INCLUDE_DIR "${FOO_INSTALL_DIR}/include")
endif()
target_link_libraries(foo INTERFACE ${foo_LIBRARY})
target_include_directories(foo INTERFACE ${foo_INCLUDE_DIR})
这篇关于使用CMake仅构建一次外部库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!