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
?
Based on the excellent answer by @Hikke, I wrote two macros to simplify using external projects.
Code
Explanation
The first macro creates the external project, which does the entire external build step, while the second step sets the necessary dependencies and defines the interface. Separating the two is important, because most projects have more than one interface/library.
Example
Say I have GoogleTest as a submodule in my project, located in the
googletest
subfolder. I can use the following interface to define thegtest
andgtest_main
macros, very similar to how Googletest itself does it.I can then link my target to googletest much like before:
This should provide sufficient boilerplate to simplify the actual external build process, even with CMake-driven projects.
As @Tsyvarev said, in your case
ExternalProject_Add
is better thanadd_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 thetarget_link_libraries()
command while target created byExternalProject_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()
.