From 83432b446167f28906e69090904a9be81aece528 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Sun, 16 Apr 2017 13:03:52 +0800 Subject: [PATCH] cmake: build boost as an external project Signed-off-by: Kefu Chai --- CMakeLists.txt | 73 +++---------- cmake/modules/BuildBoost.cmake | 184 +++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+), 60 deletions(-) create mode 100644 cmake/modules/BuildBoost.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 278524a072210..cc299cfaf7dbf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,12 @@ endif() if(POLICY CMP0065) cmake_policy(SET CMP0065 NEW) endif() - +if(POLICY CMP0051) + # cmake 3.1 and higher include generator expressions in SOURCES property, + # but i don't want to bother with stripping off the TARGET_OBJECTS elements + # from it. so let's stick with the old behavior now. + cmake_policy(SET CMP0051 OLD) +endif() list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules/") if(CMAKE_SYSTEM_NAME MATCHES "Linux") @@ -534,77 +539,25 @@ if(WITH_RADOSGW_BEAST_FRONTEND) list(APPEND BOOST_COMPONENTS coroutine context) endif() -if (WITH_SYSTEM_BOOST) +set(Boost_USE_MULTITHREADED ON) +# require minimally the bundled version +if(WITH_SYSTEM_BOOST) if(ENABLE_SHARED) set(Boost_USE_STATIC_LIBS OFF) else() set(Boost_USE_STATIC_LIBS ON) endif() + find_package(Boost 1.61 COMPONENTS ${BOOST_COMPONENTS} REQUIRED) else() - set(BOOST_CFLAGS "-fPIC -w") # check on arm, etc <---XXX set(BOOST_J 1 CACHE STRING "max jobs for Boost build") # override w/-DBOOST_J= - message(STATUS "BUILDING Boost Libraries at j ${BOOST_J}") - # 1. prep w/required components - set(BOOST_SOURCE_DIR "${PROJECT_SOURCE_DIR}/src/boost") - set(BOOST_PREFIX "${PROJECT_BINARY_DIR}/boost") - set(BOOST_BUILD "${PROJECT_BINARY_DIR}/boost-build") - list(APPEND BOOST_COMPONENTS ${BOOST_HEADER_COMPONENTS}) - string(REPLACE ";" "," BOOST_WITH_LIBS "${BOOST_COMPONENTS}") - execute_process(COMMAND "./bootstrap.sh" - "--prefix=${BOOST_PREFIX}" - "--with-libraries=${BOOST_WITH_LIBS}" - WORKING_DIRECTORY ${BOOST_SOURCE_DIR}) - set(BOOST_ROOT "${BOOST_PREFIX}") - set(b2 ./b2 - --build-dir=${BOOST_BUILD} -j${BOOST_J}) - if(CMAKE_VERBOSE_MAKEFILE) - list(APPEND b2 -d1) - else() - list(APPEND b2 -d0) - endif() - list(APPEND b2 - variant=release link=static threading=multi cxxflags=${BOOST_CFLAGS}) - if(NOT CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL CMAKE_SYSTEM_PROCESSOR) - # we are crosscompiling - if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) - set(b2_cc gcc) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL Clang) - set(b2_cc clang) - else() - message(SEND_ERROR "unknown compiler: ${CMAKE_CXX_COMPILER_ID}") - endif() - # edit the config.jam so, b2 will be able to use the specified toolset - execute_process( - COMMAND - sed -i - "s|using ${b2_cc} ;|using ${b2_cc} : ${CMAKE_SYSTEM_PROCESSOR} : ${CMAKE_CXX_COMPILER} ;|" - ${PROJECT_SOURCE_DIR}/src/boost/project-config.jam) - # use ${CMAKE_SYSTEM_PROCESSOR} as the version identifier of compiler - list(APPEND b2 toolset=${b2_cc}-${CMAKE_SYSTEM_PROCESSOR}) - endif() - # 2. install headers - execute_process(COMMAND - ${b2} - headers - WORKING_DIRECTORY ${BOOST_SOURCE_DIR}) - # 3. build and install libs - execute_process(COMMAND - ${b2} - install - WORKING_DIRECTORY ${BOOST_SOURCE_DIR}) - # 4. set hints for FindBoost.cmake set(Boost_USE_STATIC_LIBS ON) - set(Boost_NO_SYSTEM_PATHS ON) - include_directories(BEFORE ${BOOST_PREFIX}/include) - set(BOOST_ROOT ${BOOST_PREFIX}) - set(Boost_NO_SYSTEM_PATHS ON) + include(BuildBoost) + build_boost(1.63 + COMPONENTS ${BOOST_COMPONENTS} ${BOOST_HEADER_COMPONENTS}) endif() - set(Boost_USE_MULTITHREADED ON) -# require minimally the bundled version -find_package(Boost 1.61 COMPONENTS ${BOOST_COMPONENTS} REQUIRED) include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) include_directories(SYSTEM ${PROJECT_BINARY_DIR}/include) diff --git a/cmake/modules/BuildBoost.cmake b/cmake/modules/BuildBoost.cmake new file mode 100644 index 0000000000000..d6466b02d4320 --- /dev/null +++ b/cmake/modules/BuildBoost.cmake @@ -0,0 +1,184 @@ +# This module builds Boost +# executables are. It sets the following variables: +# +# Boost_FOUND : boolean - system has Boost +# Boost_LIBRARIES : list(filepath) - the libraries needed to use Boost +# Boost_INCLUDE_DIRS : list(path) - the Boost include directories +# +# Following hints are respected +# +# Boost_USE_STATIC_LIBS : boolean (default: OFF) +# Boost_USE_MULTITHREADED : boolean (default: OFF) +# BOOST_J: integer (defanult 1) + +function(do_build_boost version) + cmake_parse_arguments(Boost_BUILD "" "" COMPONENTS ${ARGN}) + set(boost_features "variant=release") + if(Boost_USE_MULTITHREADED) + list(APPEND boost_features "threading=multi") + else() + list(APPEND boost_features "threading=single") + endif() + if(Boost_USE_STATIC_LIBS) + list(APPEND boost_features "link=static") + else() + list(APPEND boost_features "link=shared") + endif() + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + list(APPEND boost_features "address-model=64") + else() + list(APPEND boost_features "address-model=32") + endif() + set(BOOST_CXXFLAGS "-fPIC -w") # check on arm, etc <---XXX + list(APPEND boost_features "cxxflags=${BOOST_CXXFLAGS}") + + string(REPLACE ";" "," boost_with_libs "${Boost_BUILD_COMPONENTS}") + # build b2 and prepare the project-config.jam for boost + set(configure_command + ./bootstrap.sh --prefix= + --with-libraries=${boost_with_libs}) + + set(b2 ./b2) + if(BOOST_J) + message(STATUS "BUILDING Boost Libraries at j ${BOOST_J}") + list(APPEND b2 -j${BOOST_J}) + endif() + if(CMAKE_VERBOSE_MAKEFILE) + list(APPEND b2 -d1) + else() + list(APPEND b2 -d0) + endif() + + if(NOT CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL CMAKE_SYSTEM_PROCESSOR) + # we are crosscompiling + if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) + set(b2_cc gcc) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL Clang) + set(b2_cc clang) + else() + message(SEND_ERROR "unknown compiler: ${CMAKE_CXX_COMPILER_ID}") + endif() + # edit the config.jam so, b2 will be able to use the specified toolset + execute_process( + COMMAND + sed -i + "s|using ${b2_cc} ;|using ${b2_cc} : ${CMAKE_SYSTEM_PROCESSOR} : ${CMAKE_CXX_COMPILER} ;|" + ${PROJECT_SOURCE_DIR}/src/boost/project-config.jam) + # use ${CMAKE_SYSTEM_PROCESSOR} as the version identifier of compiler + list(APPEND b2 toolset=${b2_cc}-${CMAKE_SYSTEM_PROCESSOR}) + endif() + + set(build_command + ${b2} headers stage + #"--buildid=ceph" # changes lib names--can omit for static + ${boost_features}) + set(install_command + ${b2} install) + set(boost_root_dir "${CMAKE_BINARY_DIR}/boost") + if(EXISTS "${PROJECT_SOURCE_DIR}/src/boost/libs/config/include/boost/config.hpp") + message(STATUS "boost already in src") + set(source_dir + SOURCE_DIR "${PROJECT_SOURCE_DIR}/src/boost") + elseif(version VERSION_GREATER 1.63) + message(FATAL_ERROR "Unknown BOOST_REQUESTED_VERSION: ${version}") + else() + message(STATUS "boost will be downloaded from sf.net") + set(boost_version 1.63.0) + set(boost_md5 1c837ecd990bb022d07e7aab32b09847) + string(REPLACE "." "_" boost_version_underscore ${boost_version} ) + set(boost_url http://downloads.sourceforge.net/project/boost/boost/${boost_version}/boost_${boost_version_underscore}.tar.bz2) + set(source_dir + URL ${boost_url} + URL_MD5 ${boost_md5}) + if(CMAKE_VERSION VERSION_GREATER 3.0) + list(APPEND source_dir DOWNLOAD_NO_PROGRESS 1) + endif() + endif() + # build all components in a single shot + include(ExternalProject) + ExternalProject_Add(Boost + ${source_dir} + CONFIGURE_COMMAND CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} ${configure_command} + BUILD_COMMAND CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} ${build_command} + BUILD_IN_SOURCE 1 + INSTALL_COMMAND ${install_command} + PREFIX "${boost_root_dir}") +endfunction() + +macro(build_boost version) + do_build_boost(version ${ARGN}) + ExternalProject_Get_Property(Boost install_dir) + set(Boost_INCLUDE_DIRS ${install_dir}/include) + set(Boost_INCLUDE_DIR ${install_dir}/include) + # create the directory so cmake won't complain when looking at the imported + # target + file(MAKE_DIRECTORY ${Boost_INCLUDE_DIRS}) + cmake_parse_arguments(Boost_BUILD "" "" COMPONENTS ${ARGN}) + foreach(c ${Boost_BUILD_COMPONENTS}) + string(TOUPPER ${c} upper_c) + if(Boost_USE_STATIC_LIBS) + add_library(Boost::${c} STATIC IMPORTED) + else() + add_library(Boost::${c} SHARED IMPORTED) + endif() + add_dependencies(Boost::${c} Boost) + if(Boost_USE_STATIC_LIBS) + set(Boost_${upper_c}_LIBRARY + ${install_dir}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}boost_${c}${CMAKE_STATIC_LIBRARY_SUFFIX}) + else() + set(Boost_${upper_c}_LIBRARY + ${install_dir}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}boost_${c}${CMAKE_SHARED_LIBRARY_SUFFIX}) + endif() + set_target_properties(Boost::${c} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}" + IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" + IMPORTED_LOCATION "${Boost_${upper_c}_LIBRARY}") + list(APPEND Boost_LIBRARIES ${Boost_${upper_c}_LIBRARY}) + endforeach() + + # for header-only libraries + if(CMAKE_VERSION VERSION_LESS 3.0) + # only ALIAS and INTERFACE target names allow ":" in it, but + # INTERFACE library is not allowed until cmake 3.1 + add_custom_target(Boost.boost DEPENDS Boost) + else() + add_library(Boost.boost INTERFACE IMPORTED) + set_target_properties(Boost.boost PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") + add_dependencies(Boost.boost Boost) + endif() + find_package_handle_standard_args(Boost DEFAULT_MSG + Boost_INCLUDE_DIRS Boost_LIBRARIES) + mark_as_advanced(Boost_LIBRARIES BOOST_INCLUDE_DIRS) +endmacro() + +function(maybe_add_boost_dep target) + get_target_property(imported ${target} IMPORTED) + if(imported) + return() + endif() + get_target_property(type ${target} TYPE) + if(NOT type MATCHES "OBJECT_LIBRARY|STATIC_LIBRARY|SHARED_LIBRARY|EXECUTABLE") + return() + endif() + get_target_property(sources ${target} SOURCES) + foreach(src ${sources}) + get_filename_component(ext ${src} EXT) + # assuming all cxx source files include boost header(s) + if(ext MATCHES ".cc|.cpp|.cxx") + add_dependencies(${target} Boost.boost) + return() + endif() + endforeach() +endfunction() + +# override add_library() to add Boost headers dependency +function(add_library target) + _add_library(${target} ${ARGN}) + maybe_add_boost_dep(${target}) +endfunction() + +function(add_executable target) + _add_executable(${target} ${ARGN}) + maybe_add_boost_dep(${target}) +endfunction() -- 2.39.5