Search code examples
c++visual-studioboostcmakemulti-configuration

Compile Boost with multi-configuration with CMake


I have a project which depends on the Boost library (and others). I created a CMakeLists to automatically download and compile dependencies with ExternalProject_Add.

I want to support multi-configuration (Release and Debug). So, for my other libraries I defined a CMAKE_BUILD_TYPE at the beginning of my CMakeLists. I propagate it by dependencies with -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} in the ExternalProject_Add command.

It works well on Windows and Linux.

For Boost however, based on the configuration I need to compile with variant=debug or variant=release. I created a if(${CMAKE_BUILD_TYPE) MATCHES Debug) statement and set the variant based on that requirement.

For Linux this works well but on Windows it works only if I change the CMAKE_BUILD_TYPE variable during the cmake. When I try to change the configuration in VS it doesn't change the CMAKE_BUILD_TYPE variable.

Is it possible to detect the configuration selected in VS in my CMakeLists ?

Thank you.

#-----------------------------------------------------------------------------
# Boost
#-----------------------------------------------------------------------------

message(STATUS "Installing Boost library.")

set(BOOST_BOOTSTRAP_COMMAND)
if(WIN32)
  set(BOOST_BOOTSTRAP_COMMAND bootstrap.bat)
  set(BOOST_B2_COMMAND b2.exe)
elseif(UNIX )
  set(BOOST_BOOTSTRAP_COMMAND ./bootstrap.sh)
  set(BOOST_B2_COMMAND ./b2)
else()
  # MacOSX
  set(BOOST_BOOTSTRAP_COMMAND ./bootstrap.sh)
  set(BOOST_B2_COMMAND ./b2)
endif()

set(BOOST_BUILD_TYPE variant=release)
if (${CMAKE_BUILD_TYPE} MATCHES Debug)
  set(BOOST_BUILD_TYPE variant=debug)
endif(${CMAKE_BUILD_TYPE} MATCHES Debug)

set(BOOST_INSTALL_DIR ${PROJECT_BINARY_DIR}/deps/boost-install)
ExternalProject_Add(boost
  SOURCE_DIR "${PROJECT_BINARY_DIR}/deps/boost"
  BUILD_IN_SOURCE 1
  GIT_REPOSITORY "${git_protocol}://github.com/boostorg/boost"
  GIT_TAG "5ec478a570bdc71c5d4854e7165a8b3f4fa82ad9"
  CONFIGURE_COMMAND ${BOOST_BOOTSTRAP_COMMAND}
  BUILD_COMMAND ${BOOST_B2_COMMAND} headers COMMAND ${BOOST_B2_COMMAND} install
    link=static
    ${BOOST_BUILD_TYPE}
    --prefix=${BOOST_INSTALL_DIR}
    --with-filesystem
    --with-program_options
    --with-system
    --with-thread
    -j8
  INSTALL_COMMAND ""
)

Solution

  • When CMake is being run, it is not possible to know what build type the user will choose at build time when using a multi-configuration generator (Visual Studio or Xcode). The user makes that choice after CMake has finished the configure and generate stage (i.e. after the cmake command completes). The user can build more than one build type too, so there is not a concept of a single build type with those generators.

    One option may be to define a custom command which does the relevant build of boost as a build-time task rather than using ExternalProject. This is probably the closest to what you seem to be wanting to achieve. You can still have the source downloaded at configure time during the CMake run, a technique that is mentioned here with googletest as the example. That answer provides a link to an article which goes into more detail as well as a fully general implementation available on github which would potentially be suitable for your situation.