Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building Boost as an ExternalProject_Add and either FindBoost or export the results

Tags:

cmake

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?

Boost

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 )
like image 283
Cameron Lowell Palmer Avatar asked Oct 19 '17 07:10

Cameron Lowell Palmer


1 Answers

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.

like image 156
boorg Avatar answered Nov 05 '22 18:11

boorg