I have a number of external dependencies I'd like to pull into my project with ExternalProject_Add
. The trick is to export the include directories and resulting statically linked libraries in the cleanest way possible.
Is it possible to make FindBoost
dependent on the ExternalProject_Add
or at least make the project pull in the libraries and and headers using target_link_libraries
?
include( ExternalProject )
set( boost_URL "http://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.bz2" )
set( boost_SHA1 "9f1dd4fa364a3e3156a77dc17aa562ef06404ff6" )
set( boost_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/third_party/boost )
set( boost_INCLUDE_DIR ${boost_INSTALL}/include )
set( boost_LIB_DIR ${boost_INSTALL}/lib )
ExternalProject_Add( external_boost
PREFIX boost
URL ${boost_URL}
URL_HASH SHA1=${boost_SHA1}
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ./bootstrap.sh
--with-libraries=filesystem
--with-libraries=system
--with-libraries=date_time
--prefix=<INSTALL_DIR>
BUILD_COMMAND
./b2 install link=static variant=release threading=multi runtime-link=static
INSTALL_COMMAND ""
INSTALL_DIR ${boost_INSTALL} )
set( boost_LIBRARY_SUFFIX .a )
add_library( boost::date_time STATIC IMPORTED )
set_property( TARGET boost::date_time PROPERTY IMPORTED_LOCATION ${boost_LIB_DIR}/libboost_date_time${boost_LIBRARY_SUFFIX} )
set_property( TARGET boost::date_time PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${boost_INCLUDE_DIR} )
add_dependencies( boost::date_time external_boost )
add_library( boost::system STATIC IMPORTED )
set_property( TARGET boost::system PROPERTY IMPORTED_LOCATION ${boost_LIB_DIR}/libboost_system${boost_LIBRARY_SUFFIX} )
set_property( TARGET boost::system PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${boost_INCLUDE_DIR} )
add_dependencies( boost::system external_boost )
add_library( boost::filesystem STATIC IMPORTED )
set_property( TARGET boost::filesystem PROPERTY IMPORTED_LOCATION ${boost_LIB_DIR}/libboost_filesystem${boost_LIBRARY_SUFFIX} )
set_property( TARGET boost::filesystem PROPERTY INTERFACE_LINK_LIBRARIES boost::system )
set_property( TARGET boost::filesystem PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${boost_INCLUDE_DIR} )
add_dependencies( boost::filesystem external_boost )
The ExternalProject_Add
creates a target that will drive pulling an external project. This means that downloading, building and installing of an external project happens during a build step. As a consequence external project's properties are not known at configure step, so you cannot directly depend (or find_package) on it.
The solution is to use the so called super build. The idea is to use find_package
in your project for dependencies as if they were installed on the system. Then you create another CMakeLists.txt which contains ExternalProject_Add
instructions for all dependencies and for your project.
When you invoke cmake on super build's CMakeLists.txt it will only setup a build system for downloading and building all the projects but do nothing yet. When you invoke build, the projects are downloaded, configured, built and intstalled one by one. So when it comes to your project all dependencies will be already installed and the configure step will succeed.
Example of super build can be found here (I did not try it, but at least you can get the idea): https://github.com/Sarcasm/cmake-superbuild. Note, that last instruction in cmake/SuperBuild.cmake is ExternalProject_Add for main CMakeLists.txt (aka your project).
See also the CMake documentation at https://cmake.org/cmake/help/v3.10/module/ExternalProject.html for how to define dependencies on an ExternalProject level.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With