Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
290 views
in Technique[技术] by (71.8m points)

c++ - Build external library only once with CMake

My C++ projects includes the source code of a third-party library (currently as a git submodule).

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.

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.

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.

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 ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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})

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...