diff --git a/modules/boost/boost.cmake b/modules/boost/boost.cmake index 4389187..5b758f0 100644 --- a/modules/boost/boost.cmake +++ b/modules/boost/boost.cmake @@ -1,32 +1,18 @@ #.rst: # -# Boost libraries detection and automatic build-up. -# Minimum required version of Boost and required components have to -# be specified separately in ``custom/boost_version-components.cmake`` -# By "required components" we here mean compiled Boost libraries. -# This modules downloads the .zip archive from sourceforge at project -# bootstrap. +# Detect, build, and link Boost libraries. +# This modules downloads the .zip archive from SourceForge +# Autocmake update time. +# # Your autocmake.cfg should look like this:: # -# [custom] -# source: custom/boost_version-components.cmake -# # [boost] +# {'major': 1, 'minor': 59, 'patch': 0, 'components': 'chrono;timer;system'} # source: https://github.com/scisoft/autocmake/raw/master/modules/boost/boost.cmake -# fetch: http://sourceforge.net/projects/boost/files/boost/1.58.0/boost_1_58_0.zip # -# The ``custom/boost_version-components.cmake`` should look like this:: -# -# set(BOOST_MINIMUM_REQUIRED 1.58.0) -# list(APPEND BOOST_COMPONENTS_REQUIRED chrono timer system) -# -# Caveats: -# -# #. cross-dependencies between required components are not checked for. -# For example, Boost.Timer depends on Boost.Chrono and Boost.System thus you -# should ask explicitly for all three -# #. the project admin has to make sure that ``BOOST_MINIMUM_REQUIRED`` and the -# ``fetch`` directive point to the same version of Boost +# Cross-dependencies between required components are not checked for. +# For example, Boost.Timer depends on Boost.Chrono and Boost.System thus you +# should ask explicitly for all three. # # Dependencies:: # @@ -35,17 +21,19 @@ # # Variables used:: # -# BOOST_MINIMUM_REQUIRED - Minimum required version of Boost, set in ``custom/boost_version-components.cmake`` +# BOOST_MINIMUM_REQUIRED - Minimum required version of Boost # BOOST_COMPONENTS_REQUIRED - Components (compiled Boost libraries) required # PROJECT_SOURCE_DIR # PROJECT_BINARY_DIR # CMAKE_BUILD_TYPE # MPI_FOUND # -# Variables set:: -# # autocmake.cfg configuration:: # +# major=1 +# minor=48 +# patch=0 +# components='' # fetch: https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_unpack.cmake # https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_userconfig.cmake # https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_configure.cmake @@ -53,17 +41,20 @@ # https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_install.cmake # https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_headers.cmake # https://github.com/scisoft/autocmake/raw/master/modules/boost/boost_cleanup.cmake +# http://sourceforge.net/projects/boost/files/boost/%(major)s.%(minor)s.%(patch)s/boost_%(major)s_%(minor)s_%(patch)s.zip # docopt: --boost-headers= Include directories for Boost [default: '']. # --boost-libraries= Library directories for Boost [default: '']. # --build-boost= Deactivate Boost detection and build on-the-fly [default: OFF]. -# define: '-DBOOST_INCLUDEDIR="%s"' % arguments['--boost-headers'] -# '-DBOOST_LIBRARYDIR="%s"' % arguments['--boost-libraries'] -# '-DFORCE_CUSTOM_BOOST="%s"' % arguments['--build-boost'] +# define: '-DBOOST_INCLUDEDIR="{0}"'.format(arguments['--boost-headers']) +# '-DBOOST_LIBRARYDIR="{0}"'.format(arguments['--boost-libraries']) +# '-DFORCE_CUSTOM_BOOST="{0}"'.format(arguments['--build-boost']) +# '-DBOOST_MINIMUM_REQUIRED="%(major)s.%(minor)s.%(patch)s"' +# '-DBOOST_COMPONENTS_REQUIRED="%(components)s"' # FIXME Maintainer should be able to choose between fail (end-user has to satisfy dependency # on its own) and soft-fail (self-build of Boost) # Underscore-separated version number -string(REGEX REPLACE "\\." "_" BOOSTVER ${BOOST_MINIMUM_REQUIRED}) +string(REGEX REPLACE "\\." "_" BOOSTVER ${BOOST_MINIMUM_REQUIRED}) # Where the Boost .zip archive is located set(BOOST_ARCHIVE_LOCATION ${CMAKE_CURRENT_LIST_DIR}) set(BOOST_ARCHIVE boost_${BOOSTVER}.zip) @@ -82,12 +73,12 @@ if(FORCE_CUSTOM_BOOST) # Just to avoid unused variable warning from CMake set(BOOST_INCLUDEDIR "") set(BOOST_LIBRARYDIR "") -else(FORCE_CUSTOM_BOOST) +else() find_package(Boost ${BOOST_MINIMUM_REQUIRED} COMPONENTS "${BOOST_COMPONENTS_REQUIRED}") if(NOT Boost_FOUND) set(BUILD_CUSTOM_BOOST TRUE) - endif(NOT Boost_FOUND) -endif(FORCE_CUSTOM_BOOST) + endif() +endif() if(BUILD_CUSTOM_BOOST) ## Preliminary work @@ -112,7 +103,8 @@ if(BUILD_CUSTOM_BOOST) string(TOLOWER ${CMAKE_BUILD_TYPE} type) include(${CMAKE_CURRENT_LIST_DIR}/boost_unpack.cmake) include(${CMAKE_CURRENT_LIST_DIR}/boost_userconfig.cmake) - if(BOOST_COMPONENTS_REQUIRED) + + if(NOT BOOST_COMPONENTS_REQUIRED STREQUAL "") # Non-empty list. Compiled libraries needed # Transform the ;-separated list to a ,-separated list (digested by the Boost build toolchain!) string(REPLACE ";" "," b2_needed_components "${BOOST_COMPONENTS_REQUIRED}") @@ -125,12 +117,13 @@ if(BUILD_CUSTOM_BOOST) include(${CMAKE_CURRENT_LIST_DIR}/boost_configure.cmake) include(${CMAKE_CURRENT_LIST_DIR}/boost_build.cmake) include(${CMAKE_CURRENT_LIST_DIR}/boost_install.cmake) - else(BOOST_COMPONENTS_REQUIRED) + else() # Empty list. Header-only libraries needed # Just unpack to known location message(STATUS " No libraries required, installing headers") include(${CMAKE_CURRENT_LIST_DIR}/boost_headers.cmake) - endif(BOOST_COMPONENTS_REQUIRED) + endif() + include(${CMAKE_CURRENT_LIST_DIR}/boost_cleanup.cmake) add_custom_target(custom_boost DEPENDS ${CUSTOM_BOOST_LOCATION}/boost.cleanedup) # 4. Set all variables related to Boost that find_package would have set @@ -142,6 +135,7 @@ if(BUILD_CUSTOM_BOOST) set(Boost_LIB_VERSION ${Boost_MAJOR_VERSION}_${Boost_MINOR_VERSION}) set(Boost_INCLUDE_DIR ${CUSTOM_BOOST_LOCATION}/include CACHE PATH "Boost include directory" FORCE) set(Boost_LIBRARY_DIR ${CUSTOM_BOOST_LOCATION}/lib CACHE PATH "Boost library directory" FORCE) + foreach(_component ${BOOST_COMPONENTS_REQUIRED}) string(TOUPPER ${_component} _COMP) set(Boost_${_COMP}_FOUND TRUE) @@ -150,11 +144,14 @@ if(BUILD_CUSTOM_BOOST) set(Boost_${_COMP}_LIBRARY_RELEASE ${Boost_LIBRARY_DIR}/${Boost_${_COMP}_LIBRARY} CACHE FILEPATH "Boost ${_component} library (release)" FORCE) list(APPEND Boost_LIBRARIES ${Boost_${_COMP}_LIBRARY}) endforeach() + set(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) set(Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR}) if(CMAKE_SYSTEM_NAME MATCHES "Linux") list(APPEND Boost_LIBRARIES rt) endif() -endif(BUILD_CUSTOM_BOOST) +endif() + include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) + link_directories(${Boost_LIBRARY_DIRS}) diff --git a/test/boost_header_only/cmake/autocmake.cfg b/test/boost_header_only/cmake/autocmake.cfg index 595629c..f67ddec 100644 --- a/test/boost_header_only/cmake/autocmake.cfg +++ b/test/boost_header_only/cmake/autocmake.cfg @@ -5,12 +5,9 @@ min_cmake_version: 2.8 [cxx] source: ../../../modules/cxx.cmake -[custom] -source: custom/boost_version-components.cmake - [boost] +defaults: {'major': 1, 'minor': 48, 'patch': 0} source: ../../../modules/boost/boost.cmake -fetch: http://sourceforge.net/projects/boost/files/boost/1.48.0/boost_1_48_0.zip [default_build_paths] source: ../../../modules/default_build_paths.cmake diff --git a/test/boost_header_only/cmake/custom/boost_version-components.cmake b/test/boost_header_only/cmake/custom/boost_version-components.cmake deleted file mode 100644 index 5489eae..0000000 --- a/test/boost_header_only/cmake/custom/boost_version-components.cmake +++ /dev/null @@ -1,2 +0,0 @@ -set(BOOST_MINIMUM_REQUIRED 1.48.0) -list(APPEND BOOST_COMPONENTS_REQUIRED) diff --git a/test/boost_libs/cmake/autocmake.cfg b/test/boost_libs/cmake/autocmake.cfg index d9cbbc3..ac17fe3 100644 --- a/test/boost_libs/cmake/autocmake.cfg +++ b/test/boost_libs/cmake/autocmake.cfg @@ -5,12 +5,9 @@ min_cmake_version: 2.8 [cxx] source: ../../../modules/cxx.cmake -[custom] -source: custom/boost_version-components.cmake - [boost] +defaults: {'major': 1, 'minor': 59, 'patch': 0, 'components': 'chrono;timer;system'} source: ../../../modules/boost/boost.cmake -fetch: http://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.zip [default_build_paths] source: ../../../modules/default_build_paths.cmake diff --git a/test/boost_libs/cmake/custom/boost_version-components.cmake b/test/boost_libs/cmake/custom/boost_version-components.cmake deleted file mode 100644 index ab231a1..0000000 --- a/test/boost_libs/cmake/custom/boost_version-components.cmake +++ /dev/null @@ -1,2 +0,0 @@ -set(BOOST_MINIMUM_REQUIRED 1.59.0) -list(APPEND BOOST_COMPONENTS_REQUIRED chrono timer system) diff --git a/test/boost_libs/src/CMakeLists.txt b/test/boost_libs/src/CMakeLists.txt index 3bdd776..e038c8e 100644 --- a/test/boost_libs/src/CMakeLists.txt +++ b/test/boost_libs/src/CMakeLists.txt @@ -1,5 +1,13 @@ add_executable(example example.cpp) + if(BUILD_CUSTOM_BOOST) add_dependencies(example custom_boost) endif() -target_link_libraries(example ${Boost_TIMER_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_SYSTEM_LIBRARY}) + +set(_libs ${Boost_TIMER_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_SYSTEM_LIBRARY}) + +if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(_libs ${_libs} rt) +endif() + +target_link_libraries(example ${_libs}) diff --git a/test/boost_mpi_libs/cmake/autocmake.cfg b/test/boost_mpi_libs/cmake/autocmake.cfg index 1da33a1..222e715 100644 --- a/test/boost_mpi_libs/cmake/autocmake.cfg +++ b/test/boost_mpi_libs/cmake/autocmake.cfg @@ -8,12 +8,9 @@ source: ../../../modules/cxx.cmake [mpi] source: ../../../modules/mpi.cmake -[custom] -source: custom/boost_version-components.cmake - [boost] +defaults: {'major': 1, 'minor': 59, 'patch': 0, 'components': 'mpi;serialization'} source: ../../../modules/boost/boost.cmake -fetch: http://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.zip [default_build_paths] source: ../../../modules/default_build_paths.cmake diff --git a/test/boost_mpi_libs/cmake/custom/boost_version-components.cmake b/test/boost_mpi_libs/cmake/custom/boost_version-components.cmake deleted file mode 100644 index cad6774..0000000 --- a/test/boost_mpi_libs/cmake/custom/boost_version-components.cmake +++ /dev/null @@ -1,2 +0,0 @@ -set(BOOST_MINIMUM_REQUIRED 1.59.0) -list(APPEND BOOST_COMPONENTS_REQUIRED mpi serialization) diff --git a/test/boost_mpi_libs/src/CMakeLists.txt b/test/boost_mpi_libs/src/CMakeLists.txt index cbb29ef..fc63d15 100644 --- a/test/boost_mpi_libs/src/CMakeLists.txt +++ b/test/boost_mpi_libs/src/CMakeLists.txt @@ -1,5 +1,7 @@ add_executable(example example.cpp) + if(BUILD_CUSTOM_BOOST) add_dependencies(example custom_boost) endif() + target_link_libraries(example ${Boost_MPI_LIBRARY} ${Boost_SERIALIZATION_LIBRARY} ${MPI_CXX_LIBRARIES}) diff --git a/test/boost_python_libs/cmake/autocmake.cfg b/test/boost_python_libs/cmake/autocmake.cfg index c5289ca..0088d4d 100644 --- a/test/boost_python_libs/cmake/autocmake.cfg +++ b/test/boost_python_libs/cmake/autocmake.cfg @@ -11,12 +11,9 @@ source: ../../../modules/python_interpreter.cmake [python_libs] source: ../../../modules/python_libs.cmake -[custom] -source: custom/boost_version-components.cmake - [boost] +defaults: {'major': 1, 'minor': 56, 'patch': 0, 'components': 'python'} source: ../../../modules/boost/boost.cmake -fetch: http://sourceforge.net/projects/boost/files/boost/1.56.0/boost_1_56_0.zip [default_build_paths] source: ../../../modules/default_build_paths.cmake diff --git a/test/boost_python_libs/cmake/custom/boost_version-components.cmake b/test/boost_python_libs/cmake/custom/boost_version-components.cmake deleted file mode 100644 index 6cee3f4..0000000 --- a/test/boost_python_libs/cmake/custom/boost_version-components.cmake +++ /dev/null @@ -1,2 +0,0 @@ -set(BOOST_MINIMUM_REQUIRED 1.56.0) -list(APPEND BOOST_COMPONENTS_REQUIRED python) diff --git a/test/boost_python_libs/src/CMakeLists.txt b/test/boost_python_libs/src/CMakeLists.txt index 538ef38..23a33db 100644 --- a/test/boost_python_libs/src/CMakeLists.txt +++ b/test/boost_python_libs/src/CMakeLists.txt @@ -1,5 +1,7 @@ add_executable(example example.cpp) + if(BUILD_CUSTOM_BOOST) add_dependencies(example custom_boost) endif() + target_link_libraries(example ${Boost_PYTHON_LIBRARY} ${PYTHON_LIBRARIES}) diff --git a/test/test.py b/test/test.py index 7131d43..d968b3d 100644 --- a/test/test.py +++ b/test/test.py @@ -170,21 +170,17 @@ def test_python_libs_custom(): configure_build_and_exe('python_libs_custom', 'python setup.py --cxx=g++ --python={}'.format(python_executable)) -@skip_always def test_boost_header_only(): configure_build_and_exe('boost_header_only', 'python setup.py --cxx=g++') -@skip_always def test_boost_libs(): configure_build_and_exe('boost_libs', 'python setup.py --cxx=g++') -@skip_always def test_boost_mpi_libs(): configure_build_and_exe('boost_mpi_libs', 'python setup.py --cxx=g++ --mpi') -@skip_always def test_boost_python_libs(): configure_build_and_exe('boost_python_libs', 'python setup.py --cxx=g++') diff --git a/update.py b/update.py index c64ae74..9a55f23 100644 --- a/update.py +++ b/update.py @@ -3,13 +3,14 @@ import os import sys import datetime +import ast from collections import OrderedDict, namedtuple # we do not use the nicer sys.version_info.major # for compatibility with Python < 2.7 if sys.version_info[0] > 2: from io import StringIO - from configparser import RawConfigParser + from configparser import ConfigParser import urllib.request class URLopener(urllib.request.FancyURLopener): @@ -18,7 +19,7 @@ if sys.version_info[0] > 2: sys.exit(-1) else: from StringIO import StringIO - from ConfigParser import RawConfigParser + from ConfigParser import ConfigParser import urllib class URLopener(urllib.FancyURLopener): @@ -231,7 +232,7 @@ def gen_cmakelists(project_name, min_cmake_version, relative_path, modules): # ------------------------------------------------------------------------------ -def prepend_or_set(config, section, option, value): +def prepend_or_set(config, section, option, value, defaults): """ If option is already set, then value is prepended. If option is not set, then it is created and set to value. @@ -239,7 +240,7 @@ def prepend_or_set(config, section, option, value): """ if value: if config.has_option(section, option): - value += '\n%s' % config.get(section, option) + value += '\n%s' % config.get(section, option, 0, defaults) config.set(section, option, value) return config @@ -287,12 +288,17 @@ def fetch_modules(config, relative_path): sys.stderr.write("ERROR: %s does not exist\n" % src) sys.exit(-1) + if config.has_option(section, 'defaults'): + defaults = ast.literal_eval(config.get(section, 'defaults')) + else: + defaults = {} + # we infer config from the module documentation with open(file_name, 'r') as f: - config_docopt, config_define, config_export, config_fetch = parse_cmake_module(f.read()) - config = prepend_or_set(config, section, 'docopt', config_docopt) - config = prepend_or_set(config, section, 'define', config_define) - config = prepend_or_set(config, section, 'export', config_export) + config_docopt, config_define, config_export, config_fetch = parse_cmake_module(f.read(), defaults) + config = prepend_or_set(config, section, 'docopt', config_docopt, defaults) + config = prepend_or_set(config, section, 'define', config_define, defaults) + config = prepend_or_set(config, section, 'export', config_export, defaults) if config_fetch: for src in config_fetch.split('\n'): dst = os.path.join(fetch_dst_directory, os.path.basename(src)) @@ -377,7 +383,7 @@ def main(argv): # read config file print('- parsing autocmake.cfg') - config = RawConfigParser(dict_type=OrderedDict) + config = ConfigParser(dict_type=OrderedDict) config.read('autocmake.cfg') if not config.has_option('project', 'name'): @@ -425,7 +431,7 @@ def make_executable(path): # ------------------------------------------------------------------------------ -def parse_cmake_module(s_in): +def parse_cmake_module(s_in, defaults={}): config_docopt = None config_define = None @@ -456,18 +462,18 @@ def parse_cmake_module(s_in): autocmake_entry = '[foo]\n' + autocmake_entry buf = StringIO(autocmake_entry) - config = RawConfigParser(dict_type=OrderedDict) + config = ConfigParser(dict_type=OrderedDict) config.readfp(buf) for section in config.sections(): if config.has_option(section, 'docopt'): - config_docopt = config.get(section, 'docopt') + config_docopt = config.get(section, 'docopt', 0, defaults) if config.has_option(section, 'define'): - config_define = config.get(section, 'define') + config_define = config.get(section, 'define', 0, defaults) if config.has_option(section, 'export'): - config_export = config.get(section, 'export') + config_export = config.get(section, 'export', 0, defaults) if config.has_option(section, 'fetch'): - config_fetch = config.get(section, 'fetch') + config_fetch = config.get(section, 'fetch', 0, defaults) return config_docopt, config_define, config_export, config_fetch