diff --git a/CMake/BoostBuildSlave.cmake b/CMake/BoostBuildSlave.cmake new file mode 100644 index 000000000..26f63496b --- /dev/null +++ b/CMake/BoostBuildSlave.cmake @@ -0,0 +1,157 @@ +########################################################################## +# Boost Build Slave Support # +########################################################################## +# Copyright (C) 2008 Troy D. Straszheim # +# # +# Distributed under the Boost Software License, Version 1.0. # +# See accompanying file LICENSE_1_0.txt or copy at # +# http://www.boost.org/LICENSE_1_0.txt # +########################################################################## +option(BOOST_BUILD_SLAVE "Be a build slave, report build/testing" OFF) + +file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}" BOOST_BUILD_SLAVE_PYTHONPATH) + +if(BOOST_BUILD_SLAVE) + set(BOOST_BUILD_SLAVE_SUBMIT_URL "http://boost:boost@boost.resophonic.com/trac/login/xmlrpc" + CACHE STRING "URL to post regression testing results to.") + + file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}" BOOST_BUILD_SLAVE_PYTHONPATH) + + set(BOOST_BUILD_SLAVE_TIMEOUT 300 + CACHE STRING "Seconds until build slave times out any individual build step") + + set(BOOST_BUILD_SLAVE_DETAILS_FILE "slave-description.txt" + CACHE FILEPATH "Path to file, absolute or relative to build directory, containing descriptive text about the build (configuration peculiarities, etc) to be reported to the server") + + set(BOOST_BUILD_SLAVE_CONTACT_INFO "buildmeister@example.com" + CACHE STRING "Contact information regarding this build") + + set(BOOST_BUILD_SLAVE_HOSTNAME "" + CACHE STRING "If set, don't report what python determines to be the FQDN of this host, report this string instead.") + + set(BOOST_BUILD_SLAVE_SLEEP_DURATION "60" + CACHE STRING "Number of seconds to sleep between checks for updates from the repository.") + +endif(BOOST_BUILD_SLAVE) + +message(STATUS "Configuring test/compile drivers") + +if(CMAKE_VERBOSE_MAKEFILE) + set(BOOST_DRIVER_VERBOSE True) +else(CMAKE_VERBOSE_MAKEFILE) + set(BOOST_DRIVER_VERBOSE False) +endif(CMAKE_VERBOSE_MAKEFILE) + +# +# the programs that do the dirty work. +# +foreach(PYFILE boost_build_slave passthru marshal start finish info post classify) + configure_file(tools/build/CMake/${PYFILE}.py.in + ${BOOST_BUILD_SLAVE_PYTHONPATH}/${PYFILE}.py + @ONLY + ) +endforeach() + +if(WIN32) + configure_file(tools/build/CMake/windows_kill.py.in + ${BOOST_BUILD_SLAVE_PYTHONPATH}/kill_subprocess.py + COPYONLY + ) +else(WIN32) + configure_file(tools/build/CMake/unix_kill.py.in + ${BOOST_BUILD_SLAVE_PYTHONPATH}/kill_subprocess.py + COPYONLY + ) +endif(WIN32) + + +# +# the test driver is either marshal or passthru depending on whether +# you're in build slave mode or not. The compilation/link rules +# aren't modified if you're not in slave mode, BUUUT the tests still +# need a driver script that knows whether to expect failure or not +# and 'flips' the return status accordingly: thus passthru.py. +# +if(BOOST_BUILD_SLAVE) + file(TO_NATIVE_PATH ${BOOST_BUILD_SLAVE_PYTHONPATH}/marshal.py BOOST_TEST_DRIVER) + + configure_file(tools/build/CMake/run_continuous_slave.py.in + ${CMAKE_BINARY_DIR}/run_continuous_slave.py + @ONLY + ) + +else(BOOST_BUILD_SLAVE) + file(TO_NATIVE_PATH ${BOOST_BUILD_SLAVE_PYTHONPATH}/passthru.py BOOST_TEST_DRIVER) +endif(BOOST_BUILD_SLAVE) + +if(BOOST_BUILD_SLAVE) + # + # Redirect various build steps + # + + set(CMAKE_CXX_COMPILE_OBJECT + "\"${PYTHON_EXECUTABLE}\" \"${BOOST_TEST_DRIVER}\" cxx_compile_object ${CMAKE_CXX_COMPILE_OBJECT}" ) + + set(CMAKE_CXX_CREATE_SHARED_LIBRARY + "\"${PYTHON_EXECUTABLE}\" \"${BOOST_TEST_DRIVER}\" create_shared_library ${CMAKE_CXX_CREATE_SHARED_LIBRARY}") + + set(CMAKE_CXX_CREATE_STATIC_LIBRARY + "\"${PYTHON_EXECUTABLE}\" \"${BOOST_TEST_DRIVER}\" create_static_library ${CMAKE_CXX_CREATE_STATIC_LIBRARY}") + + set(CMAKE_CXX_LINK_EXECUTABLE + "\"${PYTHON_EXECUTABLE}\" \"${BOOST_TEST_DRIVER}\" link_executable ${CMAKE_CXX_LINK_EXECUTABLE}") + + # + # Custom targets for talking to the server via xmlrpc + # + + + # + # Get us a new build id from the server + # + file(TO_NATIVE_PATH ${BOOST_BUILD_SLAVE_PYTHONPATH}/start.py + BOOST_BUILD_SLAVE_START_PY) + add_custom_target(slave-start + COMMAND ${PYTHON_EXECUTABLE} ${BOOST_BUILD_SLAVE_START_PY} + COMMENT "Slave starting build" + ) + + # + # Tell server we're done... it'll update finish time in the db. + # + file(TO_NATIVE_PATH ${BOOST_BUILD_SLAVE_PYTHONPATH}/finish.py + BOOST_BUILD_SLAVE_FINISH_PY) + add_custom_target(slave-finish + COMMAND ${PYTHON_EXECUTABLE} ${BOOST_BUILD_SLAVE_FINISH_PY} + COMMENT "Slave finishing build" + ) + # + + # Local only: show what we report to server (our platform description, toolset, etc) + # + file(TO_NATIVE_PATH ${BOOST_BUILD_SLAVE_PYTHONPATH}/info.py + BOOST_BUILD_SLAVE_INFO_PY) + add_custom_target(slave-info + COMMAND ${PYTHON_EXECUTABLE} ${BOOST_BUILD_SLAVE_INFO_PY} + COMMENT "Print slave info" + ) +endif(BOOST_BUILD_SLAVE) + +# +# Used over in BoostTesting and BoostCore to attach xmlrpc submission rules +# to various intermediate build targets (libraries, test suites) +# + +file(TO_NATIVE_PATH ${BOOST_BUILD_SLAVE_PYTHONPATH}/post.py + BOOST_BUILD_SLAVE_POST_PY) +macro(boost_post_results PROJECT_NAME_ PARENT_TARGET BUILD_OR_TEST LOGDIR) + if(BOOST_BUILD_SLAVE) + add_custom_command(TARGET ${PARENT_TARGET} + POST_BUILD + COMMAND ${PYTHON_EXECUTABLE} ${BOOST_BUILD_SLAVE_POST_PY} ${PROJECT_NAME_} ${PARENT_TARGET} ${BUILD_OR_TEST} ${LOGDIR} + COMMENT "Submitting results for '${BUILD_OR_TEST}' of ${PARENT_TARGET} in ${PROJECT_NAME_}" + ) + set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${LOGDIR}/Log.marshal) + add_dependencies(test ${PARENT_TARGET}) + endif(BOOST_BUILD_SLAVE) +endmacro(boost_post_results PARENT_TARGET) diff --git a/CMake/BoostConfig.cmake b/CMake/BoostConfig.cmake new file mode 100644 index 000000000..fd0dd1ff9 --- /dev/null +++ b/CMake/BoostConfig.cmake @@ -0,0 +1,161 @@ +########################################################################## +# Boost Configuration Support # +########################################################################## +# Copyright (C) 2007 Douglas Gregor # +# Copyright (C) 2007 Troy Straszheim # +# # +# Distributed under the Boost Software License, Version 1.0. # +# See accompanying file LICENSE_1_0.txt or copy at # +# http://www.boost.org/LICENSE_1_0.txt # +########################################################################## +# This module defines several variables that provide information about # +# the target compiler and platform. # +# # +# Variables defined: # +# # +# BOOST_TOOLSET: # +# The Boost toolset name, used by the library version mechanism to # +# encode the compiler and version into the name of the # +# library. This toolset name will correspond with Boost.Build # +# version 2's toolset name, including version number. # +# # +# MULTI_THREADED_COMPILE_FLAGS: # +# Compilation flags when building multi-threaded programs. # +# # +# MULTI_THREADED_LINK_FLAGS: # +# Linker flags when building multi-threaded programs. # +########################################################################## +include(CheckCXXSourceCompiles) + +# +# Python interpreter +# +include(FindPythonInterp) +message(STATUS "found python executable ${PYTHON_EXECUTABLE}") +include(FindPythonLibs) +message(STATUS "found python includes ${PYTHON_INCLUDE_PATH}") +message(STATUS "found python libs ${PYTHON_LIBRARIES}") + +# Toolset detection. +if (NOT BOOST_TOOLSET) + set(BOOST_TOOLSET "unknown") + if (MSVC60) + set(BOOST_TOOLSET "vc6") + elseif(MSVC70) + set(BOOST_TOOLSET "vc7") + elseif(MSVC71) + set(BOOST_TOOLSET "vc71") + elseif(MSVC80) + set(BOOST_TOOLSET "vc80") + elseif(MSVC90) + set(BOOST_TOOLSET "vc90") + elseif(MSVC) + set(BOOST_TOOLSET "vc") + elseif(BORLAND) + set(BOOST_TOOLSET "bcb") + elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) + # Execute GCC with the -dumpversion option, to give us a version string + execute_process( + COMMAND ${CMAKE_CXX_COMPILER} "-dumpversion" + OUTPUT_VARIABLE GCC_VERSION_STRING) + + # Match only the major and minor versions of the version string + string(REGEX MATCH "[0-9]+.[0-9]+" GCC_MAJOR_MINOR_VERSION_STRING + "${GCC_VERSION_STRING}") + + # Strip out the period between the major and minor versions + string(REGEX REPLACE "\\." "" BOOST_VERSIONING_GCC_VERSION + "${GCC_MAJOR_MINOR_VERSION_STRING}") + + # Set the GCC versioning toolset + set(BOOST_TOOLSET "gcc${BOOST_VERSIONING_GCC_VERSION}") + endif(MSVC60) +endif (NOT BOOST_TOOLSET) + +# Multi-threading support +if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") + set(MULTI_THREADED_COMPILE_FLAGS "-pthreads") + set(MULTI_THREADED_LINK_LIBS rt) +elseif(CMAKE_SYSTEM_NAME STREQUAL "BeOS") + # No threading options necessary for BeOS +elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSD") + set(MULTI_THREADED_COMPILE_FLAGS "-pthread") + set(MULTI_THREADED_LINK_LIBS pthread) +elseif(CMAKE_SYSTEM_NAME STREQUAL "DragonFly") + # DragonFly is FreeBSD bariant + set(MULTI_THREADED_COMPILE_FLAGS "-pthread") +elseif(CMAKE_SYSTEM_NAME STREQUAL "IRIX") + # TODO: GCC on Irix doesn't support multi-threading? +elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX") + # TODO: gcc on HP-UX does not support multi-threading? +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + # No threading options necessary for Mac OS X +elseif(UNIX) + # Assume -pthread and -lrt on all other variants + set(MULTI_THREADED_COMPILE_FLAGS "-pthread -D_REENTRANT") + set(MULTI_THREADED_LINK_FLAGS "") + set(MULTI_THREADED_LINK_LIBS pthread rt) +endif(CMAKE_SYSTEM_NAME STREQUAL "SunOS") + +# Setup DEBUG_COMPILE_FLAGS, RELEASE_COMPILE_FLAGS, DEBUG_LINK_FLAGS and +# and RELEASE_LINK_FLAGS based on the CMake equivalents +if(CMAKE_CXX_FLAGS_DEBUG) + if(MSVC) + # Eliminate the /MDd flag; we'll add it back when we need it + string(REPLACE "/MDd" "" CMAKE_CXX_FLAGS_DEBUG + "${CMAKE_CXX_FLAGS_DEBUG}") + endif(MSVC) + set(DEBUG_COMPILE_FLAGS "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "Compilation flags for debug libraries") +endif(CMAKE_CXX_FLAGS_DEBUG) +if(CMAKE_CXX_FLAGS_RELEASE) + if(MSVC) + # Eliminate the /MD flag; we'll add it back when we need it + string(REPLACE "/MD" "" CMAKE_CXX_FLAGS_RELEASE + "${CMAKE_CXX_FLAGS_RELEASE}") + endif(MSVC) + set(RELEASE_COMPILE_FLAGS "${CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "Compilation flags for release libraries") +endif(CMAKE_CXX_FLAGS_RELEASE) +if(CMAKE_SHARED_LINKER_FLAGS_DEBUG) + set(DEBUG_LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING "Linker flags for debug libraries") +endif(CMAKE_SHARED_LINKER_FLAGS_DEBUG) +if(CMAKE_SHARED_LINKER_FLAGS_RELEASE) + set(RELEASE_LINK_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}" CACHE STRING "Link flags for release libraries") +endif(CMAKE_SHARED_LINKER_FLAGS_RELEASE) + +# Set DEBUG_EXE_LINK_FLAGS, RELEASE_EXE_LINK_FLAGS +if (CMAKE_EXE_LINKER_FLAGS_DEBUG) + set(DEBUG_EXE_LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS_DEBUG}") +endif (CMAKE_EXE_LINKER_FLAGS_DEBUG) +if (CMAKE_EXE_LINKER_FLAGS_RELEASE) + set(RELEASE_EXE_LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +endif (CMAKE_EXE_LINKER_FLAGS_RELEASE) + +# Tweak the configuration and build types appropriately. +if(CMAKE_CONFIGURATION_TYPES) + # Limit CMAKE_CONFIGURATION_TYPES to Debug and Release + set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Semicolon-separate list of supported configuration types" FORCE) +else(CMAKE_CONFIGURATION_TYPES) + # Build in release mode by default + if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are Release or Debug" FORCE) + endif (NOT CMAKE_BUILD_TYPE) +endif(CMAKE_CONFIGURATION_TYPES) + +# Clear out the built-in C++ compiler and link flags for each of the +# configurations. +set(CMAKE_CXX_FLAGS_DEBUG "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_EXE_LINKER_FLAGS_DEBUG "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_CXX_FLAGS_RELEASE "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_EXE_LINKER_FLAGS_RELEASE "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_CXX_FLAGS_MINSIZEREL "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "" CACHE INTERNAL "Unused by Boost") +set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "" CACHE INTERNAL "Unused by Boost") diff --git a/CMake/BoostCore.cmake b/CMake/BoostCore.cmake new file mode 100644 index 000000000..0d77dddce --- /dev/null +++ b/CMake/BoostCore.cmake @@ -0,0 +1,1360 @@ +########################################################################## +# Core Functionality for Boost # +########################################################################## +# Copyright (C) 2007-2008 Douglas Gregor # +# Copyright (C) 2007 Troy Straszheim # +# # +# Distributed under the Boost Software License, Version 1.0. # +# See accompanying file LICENSE_1_0.txt or copy at # +# http://www.boost.org/LICENSE_1_0.txt # +########################################################################## +# Important developer macros in this file: # +# # +# boost_library_project: Defines a Boost library project (e.g., # +# Boost.Python). # +# # +# boost_add_library: Builds library binaries for Boost libraries # +# with compiled sources (e.g., boost_filesystem). # +# # +# boost_add_executable: Builds executables. # +########################################################################## + +add_custom_target(modularize) + +# Defines a Boost library project (e.g., for Boost.Python). Use as: +# +# boost_library_project(libname +# [SRCDIRS srcdir1 srcdir2 ...] +# [TESTDIRS testdir1 testdir2 ...] +# [DEPENDS lib1 lib2 ...] +# [DESCRIPTION description] +# [AUTHORS author1 author2 ...] +# [MAINTAINERS maint1 maint2 ...] +# [MODULARIZED]) +# +# where libname is the name of the library (e.g., Python, or +# Filesystem), srcdir1, srcdir2, etc, are subdirectories containing +# library sources (for Boost libraries that build actual library +# binaries), and testdir1, testdir2, etc, are subdirectories +# containing regression tests. DEPENDS lists the names of the other +# Boost libraries that this library depends on. If the dependencies +# are not satisfied (e.g., because the library isn't present or its +# build is turned off), this library won't be built. +# +# DESCRIPTION provides a brief description of the library, which can +# be used to summarize the behavior of the library for a user. AUTHORS +# lists the authors of the library, while MAINTAINERS lists the active +# maintainers. If MAINTAINERS is left empty, it is assumed that the +# authors are still maintaining the library. Both authors and maintainers +# should have their name followed by their current e-mail address in +# angle brackets, with -at- instead of the at sign, e.g., +# Douglas Gregor +# +# For libraries that build actual library binaries, this macro adds a +# option BUILD_BOOST_LIBNAME (which defaults to ON). When the option +# is ON, this macro will include the source subdirectories, and +# therefore, will build and install the library binary. +# +# For libraries that have regression tests, and when testing is +# enabled globally by the BUILD_TESTING option, this macro also +# defines the TEST_BOOST_LIBNAME option (defaults to ON). When ON, the +# generated makefiles/project files will contain regression tests for +# this library. +# +# Example: +# boost_library_project( +# Thread +# SRCDIRS src +# TESTDIRS test +# ) +macro(boost_library_project LIBNAME) + parse_arguments(THIS_PROJECT + "SRCDIRS;TESTDIRS;HEADERS;DOCDIRS;DESCRIPTION;AUTHORS;MAINTAINERS" + "MODULARIZED" + ${ARGN} + ) + + # Set THIS_PROJECT_DEPENDS_ALL to the set of all of its + # dependencies, its dependencies' dependencies, etc., transitively. + string(TOUPPER "BOOST_${LIBNAME}_DEPENDS" THIS_PROJECT_DEPENDS) + set(THIS_PROJECT_DEPENDS_ALL ${${THIS_PROJECT_DEPENDS}}) + set(ADDED_DEPS TRUE) + while (ADDED_DEPS) + set(ADDED_DEPS FALSE) + foreach(DEP ${THIS_PROJECT_DEPENDS_ALL}) + string(TOUPPER "BOOST_${DEP}_DEPENDS" DEP_DEPENDS) + foreach(DEPDEP ${${DEP_DEPENDS}}) + list(FIND THIS_PROJECT_DEPENDS_ALL ${DEPDEP} DEPDEP_INDEX) + if (DEPDEP_INDEX EQUAL -1) + list(APPEND THIS_PROJECT_DEPENDS_ALL ${DEPDEP}) + set(ADDED_DEPS TRUE) + endif() + endforeach() + endforeach() + endwhile() + + set(THIS_PROJECT_OKAY ON) + + if(FALSE) + # This really isn't the check we want to do, especially when we + # hit circular dependencies. For now, just enable all libraries to + # be built all the time, until we can implement proper subsetting + # behavior at the CMake level. + set(THIS_PROJECT_FAILED_DEPS "") + foreach(DEP ${THIS_PROJECT_DEPENDS_ALL}) + string(TOUPPER "BUILD_BOOST_${DEP}" BOOST_LIB_DEP) + if (NOT ${BOOST_LIB_DEP}) + set(THIS_PROJECT_OKAY OFF) + set(THIS_PROJECT_FAILED_DEPS "${THIS_PROJECT_FAILED_DEPS} ${DEP}\n") + endif (NOT ${BOOST_LIB_DEP}) + endforeach(DEP) + endif(FALSE) + + if (THIS_PROJECT_SRCDIRS) + # This Boost library has source directories, so provide an option + # BUILD_BOOST_LIBNAME that allows one to turn on/off building of + # the library. + if (NOT THIS_PROJECT_OKAY) + if (${BOOST_BUILD_LIB_OPTION}) + # The user explicitly turned on this library in a prior + # iteration, but it can no longer be built because one of the + # dependencies was turned off. Force this option off and + # complain about it. + set(${BOOST_BUILD_LIB_OPTION} OFF + CACHE BOOL "Build Boost.${LIBNAME} (prefer make targets, not this, to build individual libs)" FORCE) + message(SEND_ERROR + "Cannot build Boost.${LIBNAME} due to missing library dependencies:\n${THIS_PROJECT_FAILED_DEPS}") + endif (${BOOST_BUILD_LIB_OPTION}) + endif (NOT THIS_PROJECT_OKAY) + endif (THIS_PROJECT_SRCDIRS) + + if(THIS_PROJECT_OKAY) + string(TOLOWER "${LIBNAME}" libname) + string(TOUPPER "${LIBNAME}" ULIBNAME) + project(${LIBNAME}) + + if (THIS_PROJECT_MODULARIZED OR THIS_PROJECT_SRCDIRS) + # We only build a component group for modularized libraries or libraries + # that have compiled parts. + if (COMMAND cpack_add_component_group) + # Compute a reasonable description for this library. + if (THIS_PROJECT_DESCRIPTION) + set(THIS_PROJECT_DESCRIPTION "Boost.${LIBNAME}\n\n${THIS_PROJECT_DESCRIPTION}") + + if (THIS_PROJECT_AUTHORS) + list(LENGTH THIS_PROJECT_AUTHORS THIS_PROJECT_NUM_AUTHORS) + if (THIS_PROJECT_NUM_AUTHORS EQUAL 1) + set(THIS_PROJECT_DESCRIPTION "${THIS_PROJECT_DESCRIPTION}\n\nAuthor: ") + else() + set(THIS_PROJECT_DESCRIPTION "${THIS_PROJECT_DESCRIPTION}\n\nAuthors: ") + endif() + set(THIS_PROJECT_FIRST_AUTHOR TRUE) + foreach(AUTHOR ${THIS_PROJECT_AUTHORS}) + string(REGEX REPLACE " *-at- *" "@" AUTHOR ${AUTHOR}) + if (THIS_PROJECT_FIRST_AUTHOR) + set(THIS_PROJECT_FIRST_AUTHOR FALSE) + else() + set(THIS_PROJECT_DESCRIPTION "${THIS_PROJECT_DESCRIPTION}\n ") + endif() + set(THIS_PROJECT_DESCRIPTION "${THIS_PROJECT_DESCRIPTION}${AUTHOR}") + endforeach(AUTHOR) + endif (THIS_PROJECT_AUTHORS) + + if (THIS_PROJECT_MAINTAINERS) + list(LENGTH THIS_PROJECT_MAINTAINERS THIS_PROJECT_NUM_MAINTAINERS) + if (THIS_PROJECT_NUM_MAINTAINERS EQUAL 1) + set(THIS_PROJECT_DESCRIPTION "${THIS_PROJECT_DESCRIPTION}\nMaintainer: ") + else() + set(THIS_PROJECT_DESCRIPTION "${THIS_PROJECT_DESCRIPTION}\nMaintainers: ") + endif() + set(THIS_PROJECT_FIRST_MAINTAINER TRUE) + foreach(MAINTAINER ${THIS_PROJECT_MAINTAINERS}) + string(REGEX REPLACE " *-at- *" "@" MAINTAINER ${MAINTAINER}) + if (THIS_PROJECT_FIRST_MAINTAINER) + set(THIS_PROJECT_FIRST_MAINTAINER FALSE) + else() + set(THIS_PROJECT_DESCRIPTION "${THIS_PROJECT_DESCRIPTION}\n ") + endif() + set(THIS_PROJECT_DESCRIPTION "${THIS_PROJECT_DESCRIPTION}${MAINTAINER}") + endforeach(MAINTAINER) + endif (THIS_PROJECT_MAINTAINERS) + endif (THIS_PROJECT_DESCRIPTION) + + # Create a component group for this library + cpack_add_component_group(${libname} + DISPLAY_NAME "${LIBNAME}" + DESCRIPTION ${THIS_PROJECT_DESCRIPTION}) + endif () + endif () + + if (THIS_PROJECT_MODULARIZED) + # Add this module's include directory + include_directories("${Boost_SOURCE_DIR}/libs/${libname}/include") + + # Install this module's headers + install(DIRECTORY include/boost + DESTINATION ${BOOST_HEADER_DIR} + COMPONENT ${libname}_headers + PATTERN "CVS" EXCLUDE + PATTERN ".svn" EXCLUDE) + + if (COMMAND cpack_add_component) + # Determine the header dependencies + set(THIS_PROJECT_HEADER_DEPENDS) + foreach(DEP ${${THIS_PROJECT_DEPENDS}}) + string(TOLOWER ${DEP} dep) + if (${dep} STREQUAL "serialization") + # TODO: Ugly, ugly hack until the serialization library is modularized + elseif (${dep} STREQUAL "thread") + else() + list(APPEND THIS_PROJECT_HEADER_DEPENDS ${dep}_headers) + endif() + endforeach(DEP) + + # Tell CPack about the headers component + cpack_add_component(${libname}_headers + DISPLAY_NAME "Header files" + GROUP ${libname} + DEPENDS ${THIS_PROJECT_HEADER_DEPENDS}) + endif () + endif () + +#-- This is here to debug the modularize code + set(modularize_debug FALSE) + if (modularize_debug) + set(modularize_output ${Boost_BINARY_DIR}) + set(modularize_libs_dir "modularize") + else (modularize_debug) + set(modularize_output ${Boost_SOURCE_DIR}) + set(modularize_libs_dir "libs") + endif(modularize_debug) + # Modularization code + if(THIS_PROJECT_HEADERS) + set(${LIBNAME}-modularize-commands) + foreach(item ${THIS_PROJECT_HEADERS}) + if(EXISTS "${Boost_SOURCE_DIR}/boost/${item}") + if(IS_DIRECTORY "${Boost_SOURCE_DIR}/boost/${item}") + list(APPEND ${LIBNAME}-modularize-commands + COMMAND "${CMAKE_COMMAND}" -E copy_directory + "${Boost_SOURCE_DIR}/boost/${item}" + "${modularize_output}/${modularize_libs_dir}/${libname}/include/boost/${item}" + ) + if (NOT modularize_debug) + list(APPEND ${LIBNAME}-modularize-commands + COMMAND "${CMAKE_COMMAND}" -E remove_directory "${Boost_SOURCE_DIR}/boost/${item}" + ) + endif (NOT modularize_debug) + else(IS_DIRECTORY "${Boost_SOURCE_DIR}/boost/${item}") + list(APPEND ${LIBNAME}-modularize-commands + COMMAND "${CMAKE_COMMAND}" -E copy + "${Boost_SOURCE_DIR}/boost/${item}" + "${modularize_output}/${modularize_libs_dir}/${libname}/include/boost/${item}" + ) + if (NOT modularize_debug) + list(APPEND ${LIBNAME}-modularize-commands + COMMAND "${CMAKE_COMMAND}" -E remove "${Boost_SOURCE_DIR}/boost/${item}" + ) + endif (NOT modularize_debug) + + endif(IS_DIRECTORY "${Boost_SOURCE_DIR}/boost/${item}") + elseif(EXISTS "${Boost_SOURCE_DIR}/${modularize_libs_dir}/${libname}/include/boost/${item}") + # Okay; already modularized + else() + message(SEND_ERROR + "Header or directory boost/${item} does not exist. The HEADERS argument in ${Boost_SOURCE_DIR}/${modularize_libs_dir}/${libname}/CMakeLists.txt should be updated.") + endif() + endforeach(item) + + if (${LIBNAME}-modularize-commands) + set(${LIBNAME}-modularize-commands + # COMMAND "${CMAKE_COMMAND}" -E remove_directory "${modularize_output}/libs/${libname}/include" + COMMAND "${CMAKE_COMMAND}" -E make_directory + "${modularize_output}/${modularize_libs_dir}/${libname}/include/boost" + ${${LIBNAME}-modularize-commands} + ) + if (NOT modularize_debug) + set(${LIBNAME}-modularize-commands + COMMAND "${CMAKE_COMMAND}" -E remove_directory "${modularize_output}/${modularize_libs_dir}/${libname}/include" + ${${LIBNAME}-modularize-commands} + ) + endif (NOT modularize_debug) + add_custom_target(${LIBNAME}-modularize + ${${LIBNAME}-modularize-commands} + COMMENT "Modularizing ${LIBNAME} headers to project-local dir from monolithic boost dir" + ) + + if(THIS_PROJECT_MODULARIZED) + add_dependencies(modularize ${LIBNAME}-modularize) + endif(THIS_PROJECT_MODULARIZED) + endif() + endif(THIS_PROJECT_HEADERS) + + # For each of the modular libraries on which this project depends, + # add the include path for that library. + set(THIS_PROJECT_HAS_HEADER_DEPENDS FALSE) + foreach(DEP ${THIS_PROJECT_DEPENDS_ALL}) + include_directories("${modularize_output}/${modularize_libs_dir}/${DEP}/include") + endforeach(DEP) + + # TODO: is this still necessary? + if(NOT EXISTS ${CMAKE_BINARY_DIR}/bin/tests) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin/tests) + endif(NOT EXISTS ${CMAKE_BINARY_DIR}/bin/tests) + if(NOT EXISTS ${CMAKE_BINARY_DIR}/bin/tests/${PROJECT_NAME}) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/bin/tests/${PROJECT_NAME}) + endif(NOT EXISTS ${CMAKE_BINARY_DIR}/bin/tests/${PROJECT_NAME}) + + # Include each of the source directories + if(THIS_PROJECT_SRCDIRS) + foreach(SUBDIR ${THIS_PROJECT_SRCDIRS}) + add_subdirectory(${SUBDIR}) + endforeach(SUBDIR ${THIS_PROJECT_SRCDIRS}) + endif() + + if(BUILD_TESTING AND THIS_PROJECT_TESTDIRS) + # Testing is enabled globally and this project has some + # tests. So, include the tests + add_custom_target(${PROJECT_NAME}-test) + + add_dependencies(test ${PROJECT_NAME}-test) + + # the last argument here, the binary directory that the + # logs are in, has to match the binary directory + # passed to 'add_subdirectory', in the foreach() just below + boost_post_results(${PROJECT_NAME} ${PROJECT_NAME}-test + test + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-test) + + foreach(SUBDIR ${THIS_PROJECT_TESTDIRS}) + add_subdirectory(${SUBDIR} ${PROJECT_NAME}-test) + endforeach() + endif(BUILD_TESTING AND THIS_PROJECT_TESTDIRS) + + if (BUILD_DOCUMENTATION AND THIS_PROJECT_DOCDIRS) + foreach(SUBDIR ${THIS_PROJECT_DOCDIRS}) + add_subdirectory(${SUBDIR}) + endforeach(SUBDIR) + endif () + endif() +endmacro(boost_library_project) + +macro(boost_tool_project TOOLNAME) + parse_arguments(THIS_PROJECT + "DESCRIPTION;AUTHORS;MAINTAINERS" + "" + ${ARGN} + ) + + set(THIS_PROJECT_IS_TOOL TRUE) + + string(TOUPPER ${TOOLNAME} UTOOLNAME) + set(THIS_PROJECT_OKAY ON) + set(THIS_PROJECT_FAILED_DEPS "") + foreach(DEP ${BOOST_${UTOOLNAME}_DEPENDS}) + string(TOUPPER "BUILD_BOOST_${DEP}" BOOST_LIB_DEP) + if (NOT ${BOOST_LIB_DEP}) + set(THIS_PROJECT_OKAY OFF) + set(THIS_PROJECT_FAILED_DEPS "${THIS_PROJECT_FAILED_DEPS} ${DEP}\n") + endif (NOT ${BOOST_LIB_DEP}) + endforeach(DEP) + + option(BUILD_${UTOOLNAME} "Build ${TOOLNAME}" ON) + + if (NOT THIS_PROJECT_OKAY) + if (BUILD_${UTOOLNAME}) + # The user explicitly turned on this tool in a prior + # iteration, but it can no longer be built because one of the + # dependencies was turned off. Force this option off and + # complain about it. + set(BUILD_${UTOOLNAME} OFF CACHE BOOL "Build ${TOOLNAME}" FORCE) + message(SEND_ERROR "Cannot build ${TOOLNAME} due to missing library dependencies:\n${THIS_PROJECT_FAILED_DEPS}") + endif () + endif (NOT THIS_PROJECT_OKAY) + + if(BUILD_${UTOOLNAME} AND THIS_PROJECT_OKAY) + string(TOLOWER "${TOOLNAME}" toolname) + project(${TOOLNAME}) + + # Add this module's include directory + include_directories("${Boost_SOURCE_DIR}/libs/${toolname}/include") + + # For each of the modular libraries on which this project depends, + # add the include path for that library. + foreach(DEP ${BOOST_${UTOOLNAME}_DEPENDS}) + string(TOUPPER ${DEP} UDEP) + include_directories("${Boost_SOURCE_DIR}/libs/${DEP}/include") + endforeach(DEP) + endif() +endmacro(boost_tool_project) + +# TODO: Document me! (Here and on the Trac) +macro(boost_module LIBNAME) + parse_arguments(THIS_MODULE + "DEPENDS" + "" + ${ARGN} + ) + + # Export BOOST_${LIBNAME}_DEPENDS + string(TOUPPER "BOOST_${LIBNAME}_DEPENDS" THIS_MODULE_LIBNAME_DEPENDS) + set(${THIS_MODULE_LIBNAME_DEPENDS} ${THIS_MODULE_DEPENDS}) +endmacro(boost_module) + +# This macro is an internal utility macro that builds the name of a +# particular variant of a library +# +# boost_library_variant_target_name(feature1 feature2 ...) +# +# where feature1, feature2, etc. are the names of features to be +# included in this variant, e.g., MULTI_THREADED, DEBUG. +# +# This macro sets three macros: +# +# VARIANT_TARGET_NAME: The suffix that should be appended to the +# name of the library target to name this variant of the +# library. For example, this might be "-mt-static" for a static, +# multi-threaded variant. It should be used to name the CMake +# library target, e.g., boost_signals-mt-static. +# +# VARIANT_VERSIONED_NAME: The suffix that will be added to the name +# of the generated library, containing information about the +# particular version of the library and the toolset used to build +# this library. For example, this might be "-gcc41-mt-1_34" for the +# multi-threaded, release variant of the library in Boost 1.34.0 as +# compiled with GCC 4.1. If option BUILD_VERSIONED is OFF, this +# variable is set to the empty string. +# +# VARIANT_DISPLAY_NAME: The display name that describes this +# variant, e.g., "Debug, static, multi-threaded". +# +option(BUILD_VERSIONED "Add versioning information to names of built files" ON) + +macro(boost_library_variant_target_name) + set(VARIANT_TARGET_NAME "") + + # The versioned name starts with the full Boost toolset + if(BUILD_VERSIONED) + set(VARIANT_VERSIONED_NAME "-${BOOST_TOOLSET}") + else(BUILD_VERSIONED) + set(VARIANT_VERSIONED_NAME "") + endif(BUILD_VERSIONED) + + # Add -mt for multi-threaded libraries + list_contains(VARIANT_IS_MT MULTI_THREADED ${ARGN}) + if (VARIANT_IS_MT) + set(VARIANT_TARGET_NAME "${VARIANT_TARGET_NAME}-mt") + + # If we're creating versioned names, tack on "-mt" + set(VARIANT_VERSIONED_NAME "${VARIANT_VERSIONED_NAME}-mt") + endif (VARIANT_IS_MT) + + # Add -static for static libraries, -shared for shared libraries + list_contains(VARIANT_IS_STATIC STATIC ${ARGN}) + if (VARIANT_IS_STATIC) + set(VARIANT_TARGET_NAME "${VARIANT_TARGET_NAME}-static") + set(VARIANT_DISPLAY_NAME "Static") + else (VARIANT_IS_STATIC) + set(VARIANT_TARGET_NAME "${VARIANT_TARGET_NAME}-shared") + set(VARIANT_DISPLAY_NAME "Shared") + endif (VARIANT_IS_STATIC) + + # Add "multi-threaded" to the display name for multithreaded libraries. + if (VARIANT_IS_MT) + set(VARIANT_DISPLAY_NAME "${VARIANT_DISPLAY_NAME}, multi-threaded") + endif () + + # Compute the ABI tag, which depends on various kinds of options + set(VARIANT_ABI_TAG "") + + # Linking statically to the runtime library + list_contains(VARIANT_IS_STATIC_RUNTIME STATIC_RUNTIME ${ARGN}) + if (VARIANT_IS_STATIC_RUNTIME) + set(VARIANT_TARGET_NAME "${VARIANT_TARGET_NAME}-staticrt") + set(VARIANT_ABI_TAG "${VARIANT_ABI_TAG}s") + set(VARIANT_DISPLAY_NAME "${VARIANT_DISPLAY_NAME}, static runtime") + endif (VARIANT_IS_STATIC_RUNTIME) + + # Using the debug version of the runtime library. + # With Visual C++, this comes automatically with debug + if (MSVC) + list_contains(VARIANT_IS_DEBUG DEBUG ${ARGN}) + if (VARIANT_IS_DEBUG) + set(VARIANT_ABI_TAG "${VARIANT_ABI_TAG}g") + endif (VARIANT_IS_DEBUG) + endif (MSVC) + + # Add -pydebug for debug builds of Python + list_contains(VARIANT_IS_PYDEBUG PYTHON_DEBUG ${ARGN}) + if (VARIANT_IS_PYDEBUG) + set(VARIANT_TARGET_NAME "${VARIANT_TARGET_NAME}-pydebug") + set(VARIANT_ABI_TAG "${VARIANT_ABI_TAG}y") + set(VARIANT_DISPLAY_NAME "${VARIANT_DISPLAY_NAME}, Python debugging") + endif (VARIANT_IS_PYDEBUG) + + # TODO: STLport rather than default library + # TODO: STLport's deprecated iostreams + + # Add -debug for debug libraries + list_contains(VARIANT_IS_DEBUG DEBUG ${ARGN}) + if (VARIANT_IS_DEBUG) + # Only add the actual "-debug" if we're also building release libraries + if (BUILD_RELEASE) + set(VARIANT_TARGET_NAME "${VARIANT_TARGET_NAME}-debug") + endif (BUILD_RELEASE) + set(VARIANT_ABI_TAG "${VARIANT_ABI_TAG}d") + + set(VARIANT_DISPLAY_NAME "${VARIANT_DISPLAY_NAME}, debug") + else() + set(VARIANT_DISPLAY_NAME "${VARIANT_DISPLAY_NAME}, release") + endif() + + # If there is an ABI tag, append it to the versioned name + if (VARIANT_ABI_TAG) + set(VARIANT_VERSIONED_NAME "${VARIANT_VERSIONED_NAME}-${VARIANT_ABI_TAG}") + endif (VARIANT_ABI_TAG) + + if(BUILD_VERSIONED) + # Append the Boost version number to the versioned name + if(BOOST_VERSION_SUBMINOR GREATER 0) + set(VARIANT_VERSIONED_NAME + "${VARIANT_VERSIONED_NAME}-${BOOST_VERSION_MAJOR}_${BOOST_VERSION_MINOR}_${BOOST_VERSION_SUBMINOR}") + else(BOOST_VERSION_SUBMINOR GREATER 0) + set(VARIANT_VERSIONED_NAME + "${VARIANT_VERSIONED_NAME}-${BOOST_VERSION_MAJOR}_${BOOST_VERSION_MINOR}") + endif(BOOST_VERSION_SUBMINOR GREATER 0) + endif(BUILD_VERSIONED) +endmacro(boost_library_variant_target_name) + +# This macro is an internal utility macro that updates compilation and +# linking flags based on interactions among the features in a variant. +# +# boost_feature_interactions(prefix +# feature1 feature2 ...) +# +# where "prefix" is the prefix of the compilation and linking flags +# that will be updated (e.g., ${prefix}_COMPILE_FLAGS). feature1, +# feature2, etc. are the names of the features used in this particular +# variant. If the features in this variant conflict, set +# ${prefix}_OKAY to FALSE. +macro(boost_feature_interactions PREFIX) + # Don't build or link against a shared library and a static run-time + list_contains(IS_SHARED SHARED ${ARGN}) + list_contains(IS_STATIC_RUNTIME STATIC_RUNTIME ${ARGN}) + if (IS_SHARED AND IS_STATIC_RUNTIME) + set(${PREFIX}_OKAY FALSE) + endif (IS_SHARED AND IS_STATIC_RUNTIME) + + # With Visual C++, the dynamic runtime is multi-threaded only + if (MSVC) + list_contains(IS_DYNAMIC_RUNTIME DYNAMIC_RUNTIME ${ARGN}) + list_contains(IS_SINGLE_THREADED SINGLE_THREADED ${ARGN}) + if (IS_DYNAMIC_RUNTIME AND IS_SINGLE_THREADED) + set(${PREFIX}_OKAY FALSE) + endif (IS_DYNAMIC_RUNTIME AND IS_SINGLE_THREADED) + endif (MSVC) + + # Visual C++-specific runtime library flags + if(MSVC) + list_contains(IS_STATIC_RUNTIME STATIC_RUNTIME ${ARGN}) + list_contains(IS_DEBUG DEBUG ${ARGN}) + if(IS_DEBUG) + if(IS_STATIC_RUNTIME) + set(${PREFIX}_COMPILE_FLAGS "/MTd ${${PREFIX}_COMPILE_FLAGS}") + else(IS_STATIC_RUNTIME) + set(${PREFIX}_COMPILE_FLAGS "/MDd ${${PREFIX}_COMPILE_FLAGS}") + endif(IS_STATIC_RUNTIME) + else(IS_DEBUG) + if(IS_STATIC_RUNTIME) + set(${PREFIX}_COMPILE_FLAGS "/MT ${${PREFIX}_COMPILE_FLAGS}") + else(IS_STATIC_RUNTIME) + set(${PREFIX}_COMPILE_FLAGS "/MD ${${PREFIX}_COMPILE_FLAGS}") + endif(IS_STATIC_RUNTIME) + endif(IS_DEBUG) + endif(MSVC) +endmacro(boost_feature_interactions) + +# This macro is an internal utility macro that builds a particular +# variant of a boost library. +# +# boost_library_variant(libname +# feature1 feature2 ...) +# +# where libname is the name of the Boost library (e.g., +# "boost_filesystem") and feature1, feature2, ... are the features +# that will be used in this variant. +# +# This macro will define a new library target based on libname and the +# specific variant name (see boost_library_variant_target_name), which +# depends on the utility target libname. The compilation and linking +# flags for this library are defined by THIS_LIB_COMPILE_FLAGS, +# THIS_LIB_LINK_FLAGS, THIS_LIB_LINK_LIBS, and all of the compile and +# linking flags implied by the features provided. +# +# If any of the features listed conflict with this library, no new +# targets will be built. For example, if the library provides the +# option NOT_MULTI_THREADED, and one of the features provided is +# MULTI_THREADED, this macro will essentially be a no-op. +macro(boost_library_variant LIBNAME) + set(THIS_VARIANT_COMPILE_FLAGS "${THIS_LIB_COMPILE_FLAGS}") + set(THIS_VARIANT_LINK_FLAGS "${THIS_LIB_LINK_FLAGS}") + set(THIS_VARIANT_LINK_LIBS ${THIS_LIB_LINK_LIBS}) + + # Determine if it is okay to build this variant + set(THIS_VARIANT_OKAY TRUE) + foreach(ARG ${ARGN}) + # If the library itself stated that we cannot build this variant, + # don't. For example, we're trying to build a shared library + # variant, but the user specified NO_SHARED in the requirements of + # the library. + if (THIS_LIB_NO_${ARG}) + set(THIS_VARIANT_OKAY FALSE) + endif (THIS_LIB_NO_${ARG}) + + # If the user specified that we should not build any variants of + # this kind, don't. For example, if the BUILD_SHARED option is + # off, don't build shared libraries. + if(NOT BUILD_${ARG}) + set(THIS_VARIANT_OKAY FALSE) + endif(NOT BUILD_${ARG}) + + # Accumulate compile and link flags + set(THIS_VARIANT_COMPILE_FLAGS "${THIS_VARIANT_COMPILE_FLAGS} ${THIS_LIB_${ARG}_COMPILE_FLAGS} ${${ARG}_COMPILE_FLAGS}") + set(THIS_VARIANT_LINK_FLAGS "${THIS_VARIANT_LINK_FLAGS} ${THIS_LIB_${ARG}_LINK_FLAGS} ${${ARG}_LINK_FLAGS}") + set(THIS_VARIANT_LINK_LIBS ${THIS_VARIANT_LINK_LIBS} ${THIS_LIB_${ARG}_LINK_LIBS} ${${ARG}_LINK_LIBS}) + endforeach(ARG ${ARGN}) + + # Handle feature interactions + boost_feature_interactions("THIS_VARIANT" ${ARGN}) + + if (THIS_VARIANT_OKAY) + # Determine the suffix for this library target + boost_library_variant_target_name(${ARGN}) + set(VARIANT_LIBNAME "${LIBNAME}${VARIANT_TARGET_NAME}") + + # We handle static vs. dynamic libraries differently + list_contains(THIS_LIB_IS_STATIC "STATIC" ${ARGN}) + if (THIS_LIB_IS_STATIC) + # If the STATIC_TAG flag was set, we append "-s" to the name of + # the library. This is an unfortunate hack, needed only for the + # test library. + if (THIS_LIB_STATIC_TAG) + set(THIS_LIB_STATIC_TAG "-s") + else(THIS_LIB_STATIC_TAG) + set(THIS_LIB_STATIC_TAG "") + endif(THIS_LIB_STATIC_TAG) + + # On Windows, we need static and shared libraries to have + # different names, so we follow the Boost.Build version 2 style + # and prepend "lib" to the name. + if(WIN32 AND NOT CYGWIN) + set(LIBPREFIX "lib") + else(WIN32 AND NOT CYGWIN) + set(LIBPREFIX "") + endif(WIN32 AND NOT CYGWIN) + + # Add the library itself + add_library(${VARIANT_LIBNAME} STATIC ${THIS_LIB_SOURCES}) + + # Set properties on this library + set_target_properties(${VARIANT_LIBNAME} + PROPERTIES + OUTPUT_NAME "${LIBPREFIX}${LIBNAME}${VARIANT_VERSIONED_NAME}${THIS_LIB_STATIC_TAG}" + CLEAN_DIRECT_OUTPUT 1 + COMPILE_FLAGS "${THIS_VARIANT_COMPILE_FLAGS}" + LINK_FLAGS "${THIS_VARIANT_LINK_FLAGS}" + ) + elseif (THIS_LIB_MODULE) + # Add a module + add_library(${VARIANT_LIBNAME} MODULE ${THIS_LIB_SOURCES}) + + # Set properties on this library + set_target_properties(${VARIANT_LIBNAME} + PROPERTIES + OUTPUT_NAME "${LIBNAME}${VARIANT_VERSIONED_NAME}" + CLEAN_DIRECT_OUTPUT 1 + COMPILE_FLAGS "${THIS_VARIANT_COMPILE_FLAGS}" + LINK_FLAGS "${THIS_VARIANT_LINK_FLAGS}" + SOVERSION "${BOOST_VERSION}" + ) + else (THIS_LIB_IS_STATIC) + # Add a module + add_library(${VARIANT_LIBNAME} SHARED ${THIS_LIB_SOURCES}) + + # Set properties on this library + set_target_properties(${VARIANT_LIBNAME} + PROPERTIES + OUTPUT_NAME "${LIBNAME}${VARIANT_VERSIONED_NAME}" + CLEAN_DIRECT_OUTPUT 1 + COMPILE_FLAGS "${THIS_VARIANT_COMPILE_FLAGS}" + LINK_FLAGS "${THIS_VARIANT_LINK_FLAGS}" + SOVERSION "${BOOST_VERSION}" + ) + endif (THIS_LIB_IS_STATIC) + + # The basic LIBNAME target depends on each of the variants + add_dependencies(${LIBNAME} ${VARIANT_LIBNAME}) + + boost_post_results(${PROJECT_NAME} ${VARIANT_LIBNAME} build ${CMAKE_CURRENT_BINARY_DIR}) + + # Link against whatever libraries this library depends on + target_link_libraries(${VARIANT_LIBNAME} ${THIS_VARIANT_LINK_LIBS}) + foreach(dependency ${THIS_LIB_DEPENDS}) + target_link_libraries(${VARIANT_LIBNAME} "${dependency}${VARIANT_TARGET_NAME}") + endforeach(dependency) + + if(NOT THIS_LIB_NO_INSTALL) + # Setup installation properties + string(TOLOWER "${PROJECT_NAME}${VARIANT_TARGET_NAME}" LIB_COMPONENT) + string(REPLACE "-" "_" LIB_COMPONENT ${LIB_COMPONENT}) + + # Installation of this library variant + string(TOLOWER ${PROJECT_NAME} libname) + install(TARGETS ${VARIANT_LIBNAME} DESTINATION lib COMPONENT ${LIB_COMPONENT}) + set_property( + TARGET ${VARIANT_LIBNAME} + PROPERTY BOOST_CPACK_COMPONENT + ${LIB_COMPONENT}) + + # Make the library installation component dependent on the library + # installation components of dependent libraries. + set(THIS_LIB_COMPONENT_DEPENDS) + foreach(DEP ${THIS_LIB_DEPENDS}) + # We ask the library variant that this library depends on to tell us + # what it's associated installation component is. We depend on that + # installation component. + get_property(DEP_COMPONENT + TARGET "${DEP}${VARIANT_TARGET_NAME}" + PROPERTY BOOST_CPACK_COMPONENT) + + if (DEP_COMPONENT) + if (DEP_COMPONENT STREQUAL LIB_COMPONENT) + # Do nothing: we have library dependencies within one + # Boost library + else() + list(APPEND THIS_LIB_COMPONENT_DEPENDS ${DEP_COMPONENT}) + endif() + endif() + endforeach(DEP) + + if (COMMAND cpack_add_component) + cpack_add_component(${LIB_COMPONENT} + DISPLAY_NAME "${VARIANT_DISPLAY_NAME}" + GROUP ${libname} + DEPENDS ${THIS_LIB_COMPONENT_DEPENDS}) + endif () + endif(NOT THIS_LIB_NO_INSTALL) + endif (THIS_VARIANT_OKAY) +endmacro(boost_library_variant) + +# Updates the set of default build variants to account for variations +# in the given feature. +# +# boost_add_default_variant(feature-val1 feature-val2 ...) +# +# Each new feature creates a new set of build variants using that +# feature. For example, writing: +# +# boost_add_default_variant(SINGLE_THREADED MULTI_THREADED) +# +# will create single- and multi-threaded variants of every default +# library variant already defined, doubling the number of variants +# that will be built. See the top-level CMakeLists.txt for the set of +# default variants. +# +# Variables affected: +# +# BOOST_DEFAULT_VARIANTS: +# This variable describes all of the variants that will be built +# by default, and will be updated with each invocation of +# boost_add_default_variant. The variable itself is a list, where +# each element in the list contains a colon-separated string +# naming a specific set of features for that variant, e.g., +# STATIC:DEBUG:SINGLE_THREADED. +# +# BOOST_FEATURES: +# This variable describes all of the feature sets that we know about, +# and will be extended each time ither boost_add_default_variant or +# boost_add_extra_variant is invoked. This macro will contain a list +# of feature sets, each containing the values for a given feature +# separated by colons, e.g., "DEBUG:RELEASE". +# +# BOOST_ADD_ARG_NAMES: +# This variable describes all of the feature-specific arguments +# that can be used for the boost_add_library macro, separated by +# semicolons. For example, given the use of +# boost_add_default_variant above, this variable will contain (at +# least) +# +# SINGLE_THREADED_COMPILE_FLAGS;SINGLE_THREADED_LINK_FLAGS; +# MULTI_THREADED_COMPILE_FLAGS;MULTI_THREADED_LINK_FLAGS +# +# When this variable is used in boost_add_library, it turns these +# names into feature-specific options. For example, +# MULTI_THREADED_COMPILE_FLAGS provides extra compile flags to be +# used only for multi-threaded variants of the library. +# +# BOOST_ADDLIB_OPTION_NAMES: +# Like BOOST_ADD_ARG_NAMES, this variable describes +# feature-specific options to boost_library that can be used to +# turn off building of the library when the variant would require +# certain features. For example, the NO_SINGLE_THREADED option +# turns off building of single-threaded variants for a library. +# +# BOOST_ADDEXE_OPTION_NAMES: +# Like BOOST_ADDLIB_OPTION_NAMES, execept that that variable +# describes options to boost_add_executable that can be used to +# describe which features are needed to build the executable. +# For example, the MULTI_THREADED option requires that the +# executable be built against multi-threaded libraries and with +# multi-threaded options. +macro(boost_add_default_variant) + # Update BOOST_DEFAULT_VARIANTS + if (BOOST_DEFAULT_VARIANTS) + set(BOOST_DEFAULT_VARIANTS_ORIG ${BOOST_DEFAULT_VARIANTS}) + set(BOOST_DEFAULT_VARIANTS) + foreach(VARIANT ${BOOST_DEFAULT_VARIANTS_ORIG}) + foreach(FEATURE ${ARGN}) + list(APPEND BOOST_DEFAULT_VARIANTS "${VARIANT}:${FEATURE}") + endforeach(FEATURE ${ARGN}) + endforeach(VARIANT ${BOOST_DEFAULT_VARIANTS_ORIG}) + set(BOOST_DEFAULT_VARIANTS_ORIG) + else (BOOST_DEFAULT_VARIANTS) + set(BOOST_DEFAULT_VARIANTS ${ARGN}) + endif (BOOST_DEFAULT_VARIANTS) + + # Set Feature flag options used by the boost_library macro and the + # BOOST_FEATURES variable + set(BOOST_DEFVAR_FEATURES) + foreach(FEATURE ${ARGN}) + set(BOOST_ADD_ARG_NAMES + "${BOOST_ADD_ARG_NAMES};${FEATURE}_COMPILE_FLAGS;${FEATURE}_LINK_FLAGS;${FEATURE}_LINK_LIBS") + set(BOOST_ADDLIB_OPTION_NAMES "${BOOST_ADDLIB_OPTION_NAMES};NO_${FEATURE}") + set(BOOST_ADDEXE_OPTION_NAMES "${BOOST_ADDEXE_OPTION_NAMES};${FEATURE}") + if (BOOST_DEFVAR_FEATURES) + set(BOOST_DEFVAR_FEATURES "${BOOST_DEFVAR_FEATURES}:${FEATURE}") + else (BOOST_DEFVAR_FEATURES) + set(BOOST_DEFVAR_FEATURES "${FEATURE}") + endif (BOOST_DEFVAR_FEATURES) + endforeach(FEATURE ${ARGN}) + list(APPEND BOOST_FEATURES ${BOOST_DEFVAR_FEATURES}) +endmacro(boost_add_default_variant) + +# Updates the set of "extra" build variants, which may be used to +# generate extra, library-specific variants of libraries. +# +# boost_add_extra_variant(feature-val1 feature-val2 ...) +# +# Each extra viarant makes it possible for libraries to define extra +# variants. For example, writing: +# +# boost_add_extra_variant(PYTHON_NODEBUG PYTHON_DEBUG) +# +# creates a PYTHON_NODEBUG/PYTHON_DEBUG feature pair as an extra +# variant, used by the Boost.Python library, which generates separate +# variants of the Boost.Python library: one variant uses the Python +# debug libraries, the other does not. +# +# The difference between boost_add_default_variant and +# boost_add_extra_variant is that adding a new default variant +# introduces additional variants to *all* Boost libraries, unless +# those variants are explicitly excluded by the library. Adding a new +# extra variant, on the other hand, allows librarie to specifically +# request extra variants using that feature. +# +# Variables affected: +# +# BOOST_FEATURES: +# See boost_add_default_variant. +# +# BOOST_ADD_ARG_NAMES: +# See boost_add_default_variant. +# +# BOOST_ADDLIB_OPTION_NAMES: +# See boost_add_default_variant. +# +# BOOST_ADDEXE_OPTION_NAMES: +# See boost_add_default_variant. +macro(boost_add_extra_variant) + set(BOOST_EXTVAR_FEATURES) + foreach(FEATURE ${ARGN}) + set(BOOST_ADD_ARG_NAMES + "${BOOST_ADD_ARG_NAMES};${FEATURE}_COMPILE_FLAGS;${FEATURE}_LINK_FLAGS;${FEATURE}_LINK_LIBS") + set(BOOST_ADDLIB_OPTION_NAMES "${BOOST_ADDLIB_OPTION_NAMES};NO_${FEATURE}") + set(BOOST_ADDEXE_OPTION_NAMES "${BOOST_ADDEXE_OPTION_NAMES};${FEATURE}") + if (BOOST_EXTVAR_FEATURES) + set(BOOST_EXTVAR_FEATURES "${BOOST_EXTVAR_FEATURES}:${FEATURE}") + else (BOOST_EXTVAR_FEATURES) + set(BOOST_EXTVAR_FEATURES "${FEATURE}") + endif (BOOST_EXTVAR_FEATURES) + endforeach(FEATURE ${ARGN}) + list(APPEND BOOST_FEATURES ${BOOST_EXTVAR_FEATURES}) +endmacro(boost_add_extra_variant) + +# Creates a new Boost library target that generates a compiled library +# (.a, .lib, .dll, .so, etc) from source files. This routine will +# actually build several different variants of the same library, with +# different compilation options, as determined by the set of "default" +# library variants. +# +# boost_add_library(libname +# source1 source2 ... +# [COMPILE_FLAGS compileflags] +# [feature_COMPILE_FLAGS compileflags] +# [LINK_FLAGS linkflags] +# [feature_LINK_FLAGS linkflags] +# [LINK_LIBS linklibs] +# [feature_LINK_LIBS linklibs] +# [DEPENDS libdepend1 libdepend2 ...] +# [STATIC_TAG] +# [MODULE] +# [NOT_feature] +# [EXTRA_VARIANTS variant1 variant2 ...]) +# +# where libname is the name of Boost library binary (e.g., +# "boost_regex") and source1, source2, etc. are the source files used +# to build the library, e.g., cregex.cpp. +# +# This macro has a variety of options that affect its behavior. In +# several cases, we use the placeholder "feature" in the option name +# to indicate that there are actually several different kinds of +# options, each referring to a different build feature, e.g., shared +# libraries, multi-threaded, debug build, etc. For a complete listing +# of these features, please refer to the CMakeLists.txt file in the +# root of the Boost distribution, which defines the set of features +# that will be used to build Boost libraries by default. +# +# The options that affect this macro's behavior are: +# +# COMPILE_FLAGS: Provides additional compilation flags that will be +# used when building all variants of the library. For example, one +# might want to add "-DBOOST_SIGNALS_NO_LIB=1" through this option +# (which turns off auto-linking for the Signals library while +# building it). +# +# feature_COMPILE_FLAGS: Provides additional compilation flags that +# will be used only when building variants of the library that +# include the given feature. For example, +# MULTI_THREADED_COMPILE_FLAGS are additional flags that will be +# used when building a multi-threaded variant, while +# SHARED_COMPILE_FLAGS will be used when building a shared library +# (as opposed to a static library). +# +# LINK_FLAGS: Provides additional flags that will be passed to the +# linker when linking each variant of the library. This option +# should not be used to link in additional libraries; see LINK_LIBS +# and DEPENDS. +# +# feature_LINK_FLAGS: Provides additional flags that will be passed +# to the linker when building variants of the library that contain a +# specific feature, e.g., MULTI_THREADED_LINK_FLAGS. This option +# should not be used to link in additional libraries; see +# feature_LINK_LIBS. +# +# LINK_LIBS: Provides additional libraries against which each of the +# library variants will be linked. For example, one might provide +# "expat" as options to LINK_LIBS, to state that each of the library +# variants will link against the expat library binary. Use LINK_LIBS +# for libraries external to Boost; for Boost libraries, use DEPENDS. +# +# feature_LINK_LIBS: Provides additional libraries for specific +# variants of the library to link against. For example, +# MULTI_THREADED_LINK_LIBS provides extra libraries to link into +# multi-threaded variants of the library. +# +# DEPENDS: States that this Boost library depends on and links +# against another Boost library. The arguments to DEPENDS should be +# the unversioned name of the Boost library, such as +# "boost_filesystem". Like LINK_LIBS, this option states that all +# variants of the library being built will link against the stated +# libraries. Unlike LINK_LIBS, however, DEPENDS takes particular +# library variants into account, always linking the variant of one +# Boost library against the same variant of the other Boost +# library. For example, if the boost_mpi_python library DEPENDS on +# boost_python, multi-threaded variants of boost_mpi_python will +# link against multi-threaded variants of boost_python. +# +# STATIC_TAG: States that the name of static library variants on +# Unix need to be named differently from shared library +# variants. This particular option should only be used in rare cases +# where the static and shared library variants are incompatible, +# such that linking against the shared library rather than the +# static library will cause features. When this option is provided, +# static libraries on Unix variants will have "-s" appended to their +# names. Note: we hope that this is a temporary solution. At +# present, it is only used by the Test library. +# +# MODULE: This option states that, when building a shared library, +# the shared library should be built as a module rather than a +# normal shared library. Modules have special meaning an behavior on +# some platforms, such as Mac OS X. +# +# NOT_feature: States that library variants containing a particular +# feature should not be built. For example, passing +# NOT_SINGLE_THREADED suppresses generation of single-threaded +# variants of this library. +# +# EXTRA_VARIANTS: Specifies that extra variants of this library +# should be built, based on the features listed. Each "variant" is a +# colon-separated list of features. For example, passing +# EXTRA_VARIANTS "PYTHON_NODEBUG:PYTHON_DEBUG" +# will result in the creation of an extra set of library variants, +# some with the PYTHON_NODEBUG feature and some with the +# PYTHON_DEBUG feature. +# +# Example: +# boost_add_library( +# boost_thread +# barrier.cpp condition.cpp exceptions.cpp mutex.cpp once.cpp +# recursive_mutex.cpp thread.cpp tss_hooks.cpp tss_dll.cpp tss_pe.cpp +# tss.cpp xtime.cpp +# SHARED_COMPILE_FLAGS "-DBOOST_THREAD_BUILD_DLL=1" +# STATIC_COMPILE_FLAGS "-DBOOST_THREAD_BUILD_LIB=1" +# NO_SINGLE_THREADED +# ) +macro(boost_add_library LIBNAME) + parse_arguments(THIS_LIB + "DEPENDS;COMPILE_FLAGS;LINK_FLAGS;LINK_LIBS;EXTRA_VARIANTS;${BOOST_ADD_ARG_NAMES}" + "STATIC_TAG;MODULE;NO_INSTALL;${BOOST_ADDLIB_OPTION_NAMES}" + ${ARGN} + ) + set(THIS_LIB_SOURCES ${THIS_LIB_DEFAULT_ARGS}) + + if (NOT TEST_INSTALLED_TREE) + # A top-level target that refers to all of the variants of the + # library, collectively. + add_custom_target(${LIBNAME}) + + if (THIS_LIB_EXTRA_VARIANTS) + # Build the set of variants that we will generate for this library + set(THIS_LIB_VARIANTS) + foreach(VARIANT ${BOOST_DEFAULT_VARIANTS}) + foreach(EXTRA_VARIANT ${THIS_LIB_EXTRA_VARIANTS}) + string(REPLACE ":" ";" FEATURES "${EXTRA_VARIANT}") + separate_arguments(FEATURES) + foreach(FEATURE ${FEATURES}) + list(APPEND THIS_LIB_VARIANTS "${VARIANT}:${FEATURE}") + endforeach(FEATURE ${FEATURES}) + endforeach(EXTRA_VARIANT ${THIS_LIB_EXTRA_VARIANTS}) + endforeach(VARIANT ${BOOST_DEFAULT_VARIANTS}) + else (THIS_LIB_EXTRA_VARIANTS) + set(THIS_LIB_VARIANTS ${BOOST_DEFAULT_VARIANTS}) + endif (THIS_LIB_EXTRA_VARIANTS) + + # Build each of the library variants + foreach(VARIANT_STR ${THIS_LIB_VARIANTS}) + string(REPLACE ":" ";" VARIANT ${VARIANT_STR}) + separate_arguments(VARIANT) + boost_library_variant(${LIBNAME} ${VARIANT}) + endforeach(VARIANT_STR ${THIS_LIB_VARIANTS}) + endif (NOT TEST_INSTALLED_TREE) +endmacro(boost_add_library) + +# Creates a new executable from source files. +# +# boost_add_executable(exename +# source1 source2 ... +# [COMPILE_FLAGS compileflags] +# [feature_COMPILE_FLAGS compileflags] +# [LINK_FLAGS linkflags] +# [feature_LINK_FLAGS linkflags] +# [LINK_LIBS linklibs] +# [feature_LINK_LIBS linklibs] +# [DEPENDS libdepend1 libdepend2 ...] +# [feature] +# [NO_INSTALL]) +# +# where exename is the name of the executable (e.g., "wave"). source1, +# source2, etc. are the source files used to build the executable, e.g., +# cpp.cpp. If no source files are provided, "exename.cpp" will be +# used. +# +# This macro has a variety of options that affect its behavior. In +# several cases, we use the placeholder "feature" in the option name +# to indicate that there are actually several different kinds of +# options, each referring to a different build feature, e.g., shared +# libraries, multi-threaded, debug build, etc. For a complete listing +# of these features, please refer to the CMakeLists.txt file in the +# root of the Boost distribution, which defines the set of features +# that will be used to build Boost libraries by default. +# +# The options that affect this macro's behavior are: +# +# COMPILE_FLAGS: Provides additional compilation flags that will be +# used when building the executable. +# +# feature_COMPILE_FLAGS: Provides additional compilation flags that +# will be used only when building the executable with the given +# feature (e.g., SHARED_COMPILE_FLAGS when we're linking against +# shared libraries). Note that the set of features used to build the +# executable depends both on the arguments given to +# boost_add_executable (see the "feature" argument description, +# below) and on the user's choice of variants to build. +# +# LINK_FLAGS: Provides additional flags that will be passed to the +# linker when linking the executable. This option should not be used +# to link in additional libraries; see LINK_LIBS and DEPENDS. +# +# feature_LINK_FLAGS: Provides additional flags that will be passed +# to the linker when linking the executable with the given feature +# (e.g., MULTI_THREADED_LINK_FLAGS when we're linking a +# multi-threaded executable). +# +# LINK_LIBS: Provides additional libraries against which the +# executable will be linked. For example, one might provide "expat" +# as options to LINK_LIBS, to state that the executable will link +# against the expat library binary. Use LINK_LIBS for libraries +# external to Boost; for Boost libraries, use DEPENDS. +# +# feature_LINK_LIBS: Provides additional libraries to link against +# when linking an executable built with the given feature. +# +# DEPENDS: States that this executable depends on and links against +# a Boostlibrary. The arguments to DEPENDS should be the unversioned +# name of the Boost library, such as "boost_filesystem". Like +# LINK_LIBS, this option states that the executable will link +# against the stated libraries. Unlike LINK_LIBS, however, DEPENDS +# takes particular library variants into account, always linking to +# the appropriate variant of a Boost library. For example, if the +# MULTI_THREADED feature was requested in the call to +# boost_add_executable, DEPENDS will ensure that we only link +# against multi-threaded libraries. +# +# feature: States that the executable should always be built using a +# given feature, e.g., SHARED linking (against its libraries) or +# MULTI_THREADED (for multi-threaded builds). If that feature has +# been turned off by the user, the executable will not build. +# +# NO_INSTALL: Don't install this executable with the rest of Boost. +# +# OUTPUT_NAME: If you want the executable to be generated somewhere +# other than the binary directory, pass the path (including +# directory and file name) via the OUTPUT_NAME parameter. +# +# Example: +# boost_add_executable(wave cpp.cpp +# DEPENDS boost_wave boost_program_options boost_filesystem +# boost_serialization +# ) +macro(boost_add_executable EXENAME) + # Note: ARGS is here to support the use of boost_add_executable in + # the testing code. + parse_arguments(THIS_EXE + "DEPENDS;COMPILE_FLAGS;LINK_FLAGS;LINK_LIBS;OUTPUT_NAME;ARGS;${BOOST_ADD_ARG_NAMES}" + "NO_INSTALL;${BOOST_ADDEXE_OPTION_NAMES}" + ${ARGN} + ) + + # Determine the list of sources + if (THIS_EXE_DEFAULT_ARGS) + set(THIS_EXE_SOURCES ${THIS_EXE_DEFAULT_ARGS}) + else (THIS_EXE_DEFAULT_ARGS) + set(THIS_EXE_SOURCES ${EXENAME}.cpp) + endif (THIS_EXE_DEFAULT_ARGS) + + # Whether we can build both debug and release versions of this + # executable within an IDE (based on the selected configuration + # type). + set(THIS_EXE_DEBUG_AND_RELEASE FALSE) + + # Compute the variant that will be used to build this executable, + # taking into account both the requested features passed to + # boost_add_executable and what options the user has set. + set(THIS_EXE_OKAY TRUE) + set(THIS_EXE_VARIANT) + + foreach(FEATURESET_STR ${BOOST_FEATURES}) + string(REPLACE ":" ";" FEATURESET ${FEATURESET_STR}) + separate_arguments(FEATURESET) + set(THIS_EXE_REQUESTED_FROM_SET FALSE) + foreach (FEATURE ${FEATURESET}) + if (THIS_EXE_${FEATURE}) + # Make this feature part of the variant + list(APPEND THIS_EXE_VARIANT ${FEATURE}) + set(THIS_EXE_REQUESTED_FROM_SET TRUE) + + # The caller has requested this particular feature be used + # when building the executable. If we can't satisfy that + # request (because the user has turned off the build variants + # with that feature), then we won't build this executable. + if (NOT BUILD_${FEATURE}) + set(THIS_EXE_OKAY FALSE) + endif (NOT BUILD_${FEATURE}) + endif (THIS_EXE_${FEATURE}) + endforeach (FEATURE ${FEATURESET}) + + if (NOT THIS_EXE_REQUESTED_FROM_SET) + # The caller did not specify which feature value to use from + # this set, so find the first feature value that actually works. + set(THIS_EXE_FOUND_FEATURE FALSE) + + # If this feature set decides between Release and Debug, we + # either query CMAKE_BUILD_TYPE to determine which to use (for + # makefile targets) or handle both variants separately (for IDE + # targets). + if (FEATURESET_STR STREQUAL "RELEASE:DEBUG") + if (CMAKE_CONFIGURATION_TYPES) + # IDE target: can we build both debug and release? + if (BUILD_DEBUG AND BUILD_RELEASE) + # Remember that we're capable of building both configurations + set(THIS_EXE_DEBUG_AND_RELEASE TRUE) + + # Don't add RELEASE or DEBUG to the variant (yet) + set(THIS_EXE_FOUND_FEATURE TRUE) + endif (BUILD_DEBUG AND BUILD_RELEASE) + else (CMAKE_CONFIGURATION_TYPES) + # Makefile target: CMAKE_BUILD_TYPE tells us which variant to build + if (CMAKE_BUILD_TYPE STREQUAL "Release") + # Okay, build the release variant + list(APPEND THIS_EXE_VARIANT RELEASE) + set(THIS_EXE_FOUND_FEATURE TRUE) + elseif (CMAKE_BUILD_TYPE STREQUAL "Debug") + # Okay, build the debug variant + list(APPEND THIS_EXE_VARIANT DEBUG) + set(THIS_EXE_FOUND_FEATURE TRUE) + endif (CMAKE_BUILD_TYPE STREQUAL "Release") + endif (CMAKE_CONFIGURATION_TYPES) + endif (FEATURESET_STR STREQUAL "RELEASE:DEBUG") + + # Search through all of the features in the set to find one that works + foreach (FEATURE ${FEATURESET}) + # We only care about the first feature value we find... + if (NOT THIS_EXE_FOUND_FEATURE) + # Are we allowed to build this feature? + if (BUILD_${FEATURE}) + # Found it: we're done + list(APPEND THIS_EXE_VARIANT ${FEATURE}) + set(THIS_EXE_FOUND_FEATURE TRUE) + endif (BUILD_${FEATURE}) + endif (NOT THIS_EXE_FOUND_FEATURE) + endforeach (FEATURE ${FEATURESET}) + + if (NOT THIS_EXE_FOUND_FEATURE) + # All of the features in this set were turned off. + # Just don't build anything. + set(THIS_EXE_OKAY FALSE) + endif (NOT THIS_EXE_FOUND_FEATURE) + endif (NOT THIS_EXE_REQUESTED_FROM_SET) + endforeach(FEATURESET_STR ${BOOST_FEATURES}) + + # Propagate flags from each of the features + if (THIS_EXE_OKAY) + foreach (FEATURE ${THIS_EXE_VARIANT}) + # Add all of the flags for this feature + set(THIS_EXE_COMPILE_FLAGS + "${THIS_EXE_COMPILE_FLAGS} ${THIS_EXE_${FEATURE}_COMPILE_FLAGS} ${${FEATURE}_COMPILE_FLAGS}") + set(THIS_EXE_LINK_FLAGS + "${THIS_EXE_LINK_FLAGS} ${THIS_EXE_${FEATURE}_LINK_FLAGS} ${${FEATURE}_LINK_FLAGS} ${${FEATURE}_EXE_LINK_FLAGS}") + set(THIS_EXE_LINK_LIBS + ${THIS_EXE_LINK_LIBS} ${THIS_EXE_${FEATURE}_LINK_LIBS} ${${FEATURE}_LINK_LIBS}) + endforeach (FEATURE ${THIS_EXE_VARIANT}) + + # Handle feature interactions + boost_feature_interactions("THIS_EXE" ${THIS_EXE_VARIANT}) + endif (THIS_EXE_OKAY) + + if (THIS_EXE_OKAY) + # Compute the name of the variant targets that we'll be linking + # against. We'll use this to link against the appropriate + # dependencies. For IDE targets where we can build both debug and + # release configurations, create DEBUG_ and RELEASE_ versions of + # the macros. + if (THIS_EXE_DEBUG_AND_RELEASE) + boost_library_variant_target_name(RELEASE ${THIS_EXE_VARIANT}) + set(RELEASE_VARIANT_TARGET_NAME "${VARIANT_TARGET_NAME}") + boost_library_variant_target_name(DEBUG ${THIS_EXE_VARIANT}) + set(DEBUG_VARIANT_TARGET_NAME "${VARIANT_TARGET_NAME}") + else (THIS_EXE_DEBUG_AND_RELEASE) + boost_library_variant_target_name(${THIS_EXE_VARIANT}) + endif (THIS_EXE_DEBUG_AND_RELEASE) + + # Compute the actual set of library dependencies, based on the + # variant name we computed above. The RELEASE and DEBUG versions + # only apply when THIS_EXE_DEBUG_AND_RELEASE. + set(THIS_EXE_ACTUAL_DEPENDS) + set(THIS_EXE_RELEASE_ACTUAL_DEPENDS) + set(THIS_EXE_DEBUG_ACTUAL_DEPENDS) + foreach(LIB ${THIS_EXE_DEPENDS}) + if (LIB MATCHES ".*-.*") + # The user tried to state exactly which variant to use. Just + # propagate the dependency and hope that s/he was + # right. Eventually, this should at least warn, because it is + # not the "proper" way to do things + list(APPEND THIS_EXE_ACTUAL_DEPENDS ${LIB}) + list(APPEND THIS_EXE_RELEASE_ACTUAL_DEPENDS ${LIB}) + list(APPEND THIS_EXE_DEBUG_ACTUAL_DEPENDS ${LIB}) + else (LIB MATCHES ".*-.*") + # The user has given the name of just the library target, + # e.g., "boost_filesystem". We add on the appropriate variant + # name(s). + list(APPEND THIS_EXE_ACTUAL_DEPENDS "${LIB}${VARIANT_TARGET_NAME}") + list(APPEND THIS_EXE_RELEASE_ACTUAL_DEPENDS "${LIB}${RELEASE_VARIANT_TARGET_NAME}") + list(APPEND THIS_EXE_DEBUG_ACTUAL_DEPENDS "${LIB}${DEBUG_VARIANT_TARGET_NAME}") + endif (LIB MATCHES ".*-.*") + endforeach(LIB ${THIS_EXE_DEPENDS}) + + # Build the executable + # TODO: the use of ${PROJECT_NAME}/${EXENAME} is a bit strange. + # It's designed to keep the names of regression tests from one library + # separate from the regression tests of another library, but this can + # be handled better with OUTPUT_NAME. This would also allow us to eliminate + # the directory-creation logic in boost_library_project. + if (THIS_PROJECT_IS_TOOL) + set(THIS_EXE_NAME ${EXENAME}) + else() + set(THIS_EXE_NAME ${PROJECT_NAME}-${EXENAME}) + endif() + add_executable(${THIS_EXE_NAME} ${THIS_EXE_SOURCES}) + + # Set the various compilation and linking flags + set_target_properties(${THIS_EXE_NAME} + PROPERTIES + COMPILE_FLAGS "${THIS_EXE_COMPILE_FLAGS}" + LINK_FLAGS "${THIS_EXE_LINK_FLAGS}" + ) + + # For IDE generators where we can build both debug and release + # configurations, pass the configurations along separately. + if (THIS_EXE_DEBUG_AND_RELEASE) + set_target_properties(${THIS_EXE_NAME} + PROPERTIES + COMPILE_FLAGS_DEBUG "${DEBUG_COMPILE_FLAGS} ${THIS_EXE_COMPILE_FLAGS}" + COMPILE_FLAGS_RELEASE "${RELEASE_COMPILE_FLAGS} ${THIS_EXE_COMPILE_FLAGS}" + LINK_FLAGS_DEBUG "${DEBUG_LINK_FLAGS} ${DEBUG_EXE_LINK_FLAGS} ${THIS_EXE_LINK_FLAGS}" + LINK_FLAGS_RELEASE "${RELEASE_LINK_FLAGS} ${RELEASE_EXE_LINK_FLAGS} ${THIS_EXE_LINK_FLAGS}" + ) + endif (THIS_EXE_DEBUG_AND_RELEASE) + + # If the user gave an output name, use it. + if(THIS_EXE_OUTPUT_NAME) + set_target_properties(${THIS_EXE_NAME} + PROPERTIES + OUTPUT_NAME ${THIS_EXE_OUTPUT_NAME} + ) + endif() + + # Link against the various libraries + if (THIS_EXE_DEBUG_AND_RELEASE) + # Configuration-agnostic libraries + target_link_libraries(${THIS_EXE_NAME} ${THIS_EXE_LINK_LIBS}) + + # Link against libraries for "release" configuration + foreach(LIB ${THIS_EXE_RELEASE_ACTUAL_DEPENDS} ${THIS_EXE_RELEASE_LINK_LIBS}) + target_link_libraries(${THIS_EXE_NAME} optimized ${LIB}) + endforeach(LIB ${THIS_EXE_RELEASE_ACTUAL_DEPENDS} ${THIS_EXE_RELEASE_LINK_LIBS}) + + # Link against libraries for "debug" configuration + foreach(LIB ${THIS_EXE_DEBUG_ACTUAL_DEPENDS} ${THIS_EXE_DEBUG_LINK_LIBS}) + target_link_libraries(${THIS_EXE_NAME} debug ${LIB}) + endforeach(LIB ${THIS_EXE_DEBUG_ACTUAL_DEPENDS} ${THIS_EXE_DEBUG_LINK_LIBS}) + else (THIS_EXE_DEBUG_AND_RELEASE) + target_link_libraries(${THIS_EXE_NAME} + ${THIS_EXE_ACTUAL_DEPENDS} + ${THIS_EXE_LINK_LIBS}) + endif (THIS_EXE_DEBUG_AND_RELEASE) + + # Install the executable, if not suppressed + if (NOT THIS_EXE_NO_INSTALL) + install(TARGETS ${THIS_EXE_NAME} DESTINATION bin) + endif (NOT THIS_EXE_NO_INSTALL) + endif (THIS_EXE_OKAY) +endmacro(boost_add_executable) diff --git a/CMake/BoostDocs.cmake b/CMake/BoostDocs.cmake new file mode 100644 index 000000000..a82e0423e --- /dev/null +++ b/CMake/BoostDocs.cmake @@ -0,0 +1,520 @@ +########################################################################## +# Boost Documentation Generation # +########################################################################## +# Copyright (C) 2008 Douglas Gregor # +# # +# Distributed under the Boost Software License, Version 1.0. # +# See accompanying file LICENSE_1_0.txt or copy at # +# http://www.boost.org/LICENSE_1_0.txt # +########################################################################## +# Important developer macros in this file: # +# # +########################################################################## + +# Transforms the source XML file by applying the given XSL stylesheet. +# +# xsl_transform(output input [input2 input3 ...] +# STYLESHEET stylesheet +# [CATALOG catalog] +# [DIRECTORY mainfile] +# [PARAMETERS param1=value1 param2=value2 ...] +# [[MAKE_ALL_TARGET | MAKE_TARGET] target] +# [COMMENT comment]) +# +# This macro builds a custom command that transforms an XML file +# (input) via the given XSL stylesheet. The output will either be a +# single file (the default) or a directory (if the DIRECTION argument +# is specified). The STYLESBEET stylesheet must be a valid XSL +# stylesheet. Any extra input files will be used as additional +# dependencies for the target. For example, these extra input files +# might refer to other XML files that are included by the input file +# through XInclude. +# +# When the XSL transform output is going to a directory, the mainfile +# argument provides the name of a file that will be generated within +# the output directory. This file will be used for dependency tracking. +# +# XML catalogs can be used to remap parts of URIs within the +# stylesheet to other (typically local) entities. To provide an XML +# catalog file, specify the name of the XML catalog file via the +# CATALOG argument. It will be provided to the XSL transform. +# +# The PARAMETERS argument is followed by param=value pairs that set +# additional parameters to the XSL stylesheet. The parameter names +# that can be used correspond to the elements within the +# stylesheet. +# +# To associate a target name with the result of the XSL +# transformation, use the MAKE_TARGET or MAKE_ALL_TARGET option and +# provide the name of the target. The MAKE_ALL_TARGET option only +# differs from MAKE_TARGET in that MAKE_ALL_TARGET will make the +# resulting target a part of the default build. +# +# If a COMMENT argument is provided, it will be used as the comment +# CMake provides when running this XSL transformation. Otherwise, the +# comment will be "Generating "output" via XSL transformation...". +macro(xsl_transform OUTPUT INPUT) + parse_arguments(THIS_XSL + "STYLESHEET;CATALOG;MAKE_ALL_TARGET;MAKE_TARGET;PARAMETERS;DIRECTORY;COMMENT" + "" + ${ARGN} + ) + + # TODO: Is this the best way to handle catalogs? The alternative is + # that we could provide explicit remappings to the xsl_transform + # macro, and it could generate a temporary XML catalog file. + if (THIS_XSL_CATALOG) + set(THIS_XSL_CATALOG "XML_CATALOG_FILES=${THIS_XSL_CATALOG}") + endif () + + # Translate XSL parameters into a form that xsltproc can use. + set(THIS_XSL_EXTRA_FLAGS) + foreach(PARAM ${THIS_XSL_PARAMETERS}) + string(REGEX REPLACE "([^=]*)=([^;]*)" "\\1;\\2" + XSL_PARAM_LIST ${PARAM}) + list(GET XSL_PARAM_LIST 0 XSL_PARAM_NAME) + list(GET XSL_PARAM_LIST 1 XSL_PARAM_VALUE) + list(APPEND THIS_XSL_EXTRA_FLAGS + --stringparam ${XSL_PARAM_NAME} ${XSL_PARAM_VALUE}) + endforeach(PARAM) + + # If the user didn't provide a comment for this transformation, + # create a default one. + if(NOT THIS_XSL_COMMENT) + set(THIS_XSL_COMMENT "Generating ${OUTPUT} via XSL transformation...") + endif() + + # Figure out the actual output file that we tell CMake about + # (THIS_XSL_OUTPUT_FILE) and the output file or directory that we + # tell xsltproc about (THIS_XSL_OUTPUT). + if (THIS_XSL_DIRECTORY) + set(THIS_XSL_OUTPUT_FILE ${OUTPUT}/${THIS_XSL_DIRECTORY}) + set(THIS_XSL_OUTPUT ${OUTPUT}/) + else() + set(THIS_XSL_OUTPUT_FILE ${OUTPUT}) + set(THIS_XSL_OUTPUT ${OUTPUT}) + endif() + + if(NOT THIS_XSL_STYLESHEET) + message(SEND_ERROR + "xsl_transform macro invoked without a STYLESHEET argument") + else() + # Run the XSLT processor to do the XML transformation. + add_custom_command(OUTPUT ${THIS_XSL_OUTPUT_FILE} + COMMAND ${THIS_XSL_CATALOG} ${XSLTPROC} ${XSLTPROC_FLAGS} + ${THIS_XSL_EXTRA_FLAGS} -o ${THIS_XSL_OUTPUT} + --path ${CMAKE_CURRENT_BINARY_DIR} + ${THIS_XSL_STYLESHEET} ${INPUT} + COMMENT ${THIS_XSL_COMMENT} + DEPENDS ${INPUT} ${THIS_XSL_DEFAULT_ARGS}) + set_source_files_properties(${THIS_XSL_OUTPUT_FILE} + PROPERTIES GENERATED TRUE) + + # Create a custom target to refer to the result of this + # transformation. + if (THIS_XSL_MAKE_ALL_TARGET) + add_custom_target(${THIS_XSL_MAKE_ALL_TARGET} ALL + DEPENDS ${THIS_XSL_OUTPUT_FILE}) + elseif(THIS_XSL_MAKE_TARGET) + add_custom_target(${THIS_XSL_MAKE_TARGET} + DEPENDS ${THIS_XSL_OUTPUT_FILE}) + endif() + endif() +endmacro(xsl_transform) + +# Use Doxygen to parse header files and produce BoostBook output. +# +# doxygen_to_boostbook(output header1 header2 ... +# [PARAMETERS param1=value1 param2=value2 ... ]) +# +# This macro sets up rules to transform a set of C/C++ header files +# into BoostBook reference documentation. The resulting BoostBook XML +# file will be named by the "output" parameter, and the set of headers +# is provided following the output file. The actual parsing of header +# files is provided by Doxygen, and is transformed into XML through +# various XSLT transformations. +# +# Doxygen has a variety of configuration parameters. One can supply +# extra Doxygen configuration parameters by providing NAME=VALUE pairs +# following the PARAMETERS argument. These parameters will be added to +# the Doxygen configuration file. +# +# This macro is intended to be used internally by +# boost_add_documentation. +macro(doxygen_to_boostbook OUTPUT) + parse_arguments(THIS_DOXY + "PARAMETERS" + "" + ${ARGN}) + + # Create a Doxygen configuration file template + # TODO: We would like to create this file at build time rather + # than at configuration time + get_filename_component(DOXYFILE_PATH ${OUTPUT} PATH) + get_filename_component(DOXYFILE_NAME ${OUTPUT} NAME_WE) + set(DOXYFILE ${DOXYFILE_PATH}/${DOXYFILE_NAME}.doxyfile) + execute_process( + COMMAND ${DOXYGEN} -s -g ${DOXYFILE} + OUTPUT_QUIET ERROR_QUIET) + + # Update the Doxygen configuration file for XML generation + file(APPEND ${DOXYFILE} "OUTPUT_DIRECTORY = ${CMAKE_CURRENT_BINARY_DIR}\n") + file(APPEND ${DOXYFILE} "GENERATE_LATEX = NO\n") + file(APPEND ${DOXYFILE} "GENERATE_HTML = NO\n") + file(APPEND ${DOXYFILE} "GENERATE_XML = YES\n") + foreach(PARAM ${THIS_DOXY_PARAMETERS}) + file(APPEND ${DOXYFILE} "${PARAM}\n") + endforeach(PARAM) + + set(THIS_DOXY_HEADER_PATH ${CMAKE_SOURCE_DIR}/libs/${libname}/include) + + set(THIS_DOXY_HEADER_LIST "") + set(THIS_DOXY_HEADERS) + foreach(HDR ${THIS_DOXY_DEFAULT_ARGS}) + list(APPEND THIS_DOXY_HEADERS ${THIS_DOXY_HEADER_PATH}/${HDR}) + set(THIS_DOXY_HEADER_LIST + "${THIS_DOXY_HEADER_LIST} ${THIS_DOXY_HEADER_PATH}/${HDR}") + endforeach(HDR) + file(APPEND ${DOXYFILE} "INPUT = ${THIS_DOXY_HEADER_LIST}\n") + + # Generate Doxygen XML + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xml/index.xml + COMMAND ${DOXYGEN} ${DOXYFILE} + COMMENT "Generating Doxygen XML output for Boost.${PROJECT_NAME}..." + DEPENDS ${THIS_DOXY_HEADERS}) + + # Collect Doxygen XML into a single XML file + set_source_files_properties( + ${CMAKE_CURRENT_BINARY_DIR}/xml/combine.xslt + PROPERTIES GENERATED TRUE) + xsl_transform( + ${CMAKE_CURRENT_BINARY_DIR}/xml/all.xml + ${CMAKE_CURRENT_BINARY_DIR}/xml/index.xml + STYLESHEET ${CMAKE_CURRENT_BINARY_DIR}/xml/combine.xslt + COMMENT "Collecting Doxygen XML output for Boost.${PROJECT_NAME}...") + + # Transform single Doxygen XML file into BoostBook XML + xsl_transform(${OUTPUT} + ${CMAKE_CURRENT_BINARY_DIR}/xml/all.xml + STYLESHEET ${BOOSTBOOK_XSL_DIR}/doxygen/doxygen2boostbook.xsl + COMMENT "Transforming Doxygen XML into BoostBook XML for Boost.${PROJECT_NAME}...") +endmacro(doxygen_to_boostbook) + +# Adds documentation for the current library or tool project +# +# boost_add_documentation(source1 source2 source3 ... +# [HEADERS header1 header2 ...] +# [DOXYGEN_PARAMETERS param1=value1 param2=value2 ...]) +# + +# This macro describes the documentation for a library or tool, which +# will be built and installed as part of the normal build +# process. Documentation can be in a variety of formats, and the input +# format will determine how that documentation is transformed. The +# documentation's format is determined by its extension, and the +# following input formats are supported: +# +# QuickBook +# BoostBook (.XML extension): +macro(boost_add_documentation SOURCE) + parse_arguments(THIS_DOC + "HEADERS;DOXYGEN_PARAMETERS" + "" + ${ARGN}) + + # If SOURCE is not a full path, it's in the current source + # directory. + get_filename_component(THIS_DOC_SOURCE_PATH ${SOURCE} PATH) + if(THIS_DOC_SOURCE_PATH STREQUAL "") + set(THIS_DOC_SOURCE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE}") + else() + set(THIS_DOC_SOURCE_PATH ${SOURCE}) + endif() + + # If we are parsing C++ headers (with Doxygen) for reference + # documentation, do so now and produce the requested BoostBook XML + # file. + if (THIS_DOC_HEADERS) + set(DOC_HEADER_FILES) + set(DOC_BOOSTBOOK_FILE) + foreach(HEADER ${THIS_DOC_HEADERS}) + get_filename_component(HEADER_EXT ${HEADER} EXT) + string(TOUPPER ${HEADER_EXT} HEADER_EXT) + if (HEADER_EXT STREQUAL ".XML") + if (DOC_BOOSTBOOK_FILE) + # Generate this BoostBook file from the headers + doxygen_to_boostbook( + ${CMAKE_CURRENT_BINARY_DIR}/${DOC_BOOSTBOOK_FILE} + ${DOC_HEADER_FILES} + PARAMETERS ${THIS_DOC_DOXYGEN_PARAMETERS}) + list(APPEND THIS_DOC_DEFAULT_ARGS + ${CMAKE_CURRENT_BINARY_DIR}/${DOC_BOOSTBOOK_FILE}) + endif() + set(DOC_BOOSTBOOK_FILE ${HEADER}) + set(DOC_HEADER_FILES) + else() + if (NOT DOC_BOOSTBOOK_FILE) + message(SEND_ERROR + "HEADERS argument to boost_add_documentation must start with a BoostBook XML file name for output") + endif() + list(APPEND DOC_HEADER_FILES ${HEADER}) + endif() + endforeach() + + if (DOC_HEADER_FILES) + # Generate this BoostBook file from the headers + doxygen_to_boostbook( + ${CMAKE_CURRENT_BINARY_DIR}/${DOC_BOOSTBOOK_FILE} + ${DOC_HEADER_FILES} + PARAMETERS ${THIS_DOC_DOXYGEN_PARAMETERS}) + list(APPEND THIS_DOC_DEFAULT_ARGS + ${CMAKE_CURRENT_BINARY_DIR}/${DOC_BOOSTBOOK_FILE}) + + endif() + endif (THIS_DOC_HEADERS) + + # Figure out the source file extension, which will tell us how to + # build the documentation. + get_filename_component(THIS_DOC_EXT ${SOURCE} EXT) + string(TOUPPER ${THIS_DOC_EXT} THIS_DOC_EXT) + if (THIS_DOC_EXT STREQUAL ".QBK") + if (BUILD_QUICKBOOK) + # Transform Quickbook into BoostBook XML + get_filename_component(SOURCE_FILENAME ${SOURCE} NAME_WE) + set(BOOSTBOOK_FILE ${SOURCE_FILENAME}.xml) + add_custom_command(OUTPUT ${BOOSTBOOK_FILE} + COMMAND quickbook "--output-file=${BOOSTBOOK_FILE}" + ${THIS_DOC_SOURCE_PATH} + DEPENDS ${THIS_DOC_SOURCE_PATH} ${THIS_DOC_DEFAULT_ARGS} + COMMENT "Generating BoostBook documentation for Boost.${PROJECT_NAME}...") + + # Transform BoostBook into other formats + boost_add_documentation(${CMAKE_CURRENT_BINARY_DIR}/${BOOSTBOOK_FILE}) + else() + message(SEND_ERROR + "Quickbook is required to build Boost documentation.\nQuickbook can be built by enabling the BUILD_QUICKBOOK.") + endif() + elseif (THIS_DOC_EXT STREQUAL ".XML") + # Transform BoostBook XML into DocBook XML + get_filename_component(SOURCE_FILENAME ${SOURCE} NAME_WE) + set(DOCBOOK_FILE ${SOURCE_FILENAME}.docbook) + xsl_transform(${DOCBOOK_FILE} ${THIS_DOC_SOURCE_PATH} + ${THIS_DOC_DEFAULT_ARGS} + STYLESHEET ${BOOSTBOOK_XSL_DIR}/docbook.xsl + CATALOG ${CMAKE_BINARY_DIR}/catalog.xml + COMMENT "Generating DocBook documentation for Boost.${PROJECT_NAME}..." + MAKE_TARGET ${PROJECT_NAME}-docbook) + + # Transform DocBook into other formats + boost_add_documentation(${CMAKE_CURRENT_BINARY_DIR}/${DOCBOOK_FILE}) + elseif(THIS_DOC_EXT STREQUAL ".DOCBOOK") + # If requested, build HTML documentation + if (BUILD_DOCUMENTATION_HTML) + xsl_transform( + ${CMAKE_CURRENT_BINARY_DIR}/html + ${THIS_DOC_SOURCE_PATH} + STYLESHEET ${BOOSTBOOK_XSL_DIR}/html.xsl + CATALOG ${CMAKE_BINARY_DIR}/catalog.xml + DIRECTORY HTML.manifest + PARAMETERS admon.graphics.path=images + navig.graphics.path=images + boost.image.src=boost.png + COMMENT "Generating HTML documentation for Boost.${PROJECT_NAME}..." + MAKE_TARGET ${PROJECT_NAME}-html) + + # Install generated documentation + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html + DESTINATION share/boost-${BOOST_VERSION} + COMPONENT ${ULIBNAME}_DOCS + PATTERN "*.manifest" EXCLUDE) + endif () + + # If requested, build Unix man pages + if (BUILD_DOCUMENTATION_MAN_PAGES) + xsl_transform( + ${CMAKE_CURRENT_BINARY_DIR}/man + ${THIS_DOC_SOURCE_PATH} + STYLESHEET ${BOOSTBOOK_XSL_DIR}/manpages.xsl + CATALOG ${CMAKE_BINARY_DIR}/catalog.xml + DIRECTORY man.manifest + COMMENT "Generating man pages for Boost.${PROJECT_NAME}..." + MAKE_ALL_TARGET ${PROJECT_NAME}-man) + + # Install man pages + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man + DESTINATION . + COMPONENT ${ULIBNAME}_DOCS + PATTERN "*.manifest" EXCLUDE) + endif () + else() + message(SEND_ERROR "Unknown documentation source kind ${SOURCE}.") + endif() +endmacro(boost_add_documentation) + + +########################################################################## +# Documentation tools configuration # +########################################################################## + +# Downloads the DocBook DTD into a place where DOCBOOK_DTD_DIR can +# find it. +macro(download_docbook_dtd) + if (NOT DOCBOOK_DTD_DIR) + set(DOCBOOK_DTD_FILENAME "docbook-xml-${WANT_DOCBOOK_DTD_VERSION}.zip") + set(DOCBOOK_DTD_URL + "http://www.oasis-open.org/docbook/xml/${WANT_DOCBOOK_DTD_VERSION}/${DOCBOOK_DTD_FILENAME}") + message(STATUS "Downloading DocBook DTD from ${DOCBOOK_DTD_URL}...") + file(DOWNLOAD + "${DOCBOOK_DTD_URL}" + "${CMAKE_BINARY_DIR}/${DOCBOOK_DTD_FILENAME}" + TIMEOUT 60 STATUS DOCBOOK_DTD_STATUS) + list(GET DOCBOOK_DTD_STATUS 0 DOCBOOK_DTD_ERROR) + if (DOCBOOK_DTD_ERROR EQUAL 0) + # Download successful! Extract the DTD ZIP file. + message(STATUS "Extracting DocBook DTD...") + execute_process( + COMMAND ${UNZIP} -d docbook-dtd-${WANT_DOCBOOK_DTD_VERSION} -q "${CMAKE_BINARY_DIR}/${DOCBOOK_DTD_FILENAME}" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE UNZIP_DTD_RESULT) + if (UNZIP_DTD_RESULT EQUAL 0) + # Extraction successful. Cleanup the downloaded file. + file(REMOVE ${CMAKE_BINARY_DIR}/${DOCBOOK_DTD_FILENAME}) + set(DOCBOOK_DTD_DIR + ${CMAKE_BINARY_DIR}/docbook-dtd-${WANT_DOCBOOK_DTD_VERSION} + CACHE PATH "Path to the DocBook DTD" FORCE) + else() + # We failed: report the error to the user + message(SEND_ERROR "Extraction of DocBook DTD archive ${DOCBOOK_DTD_FILENAME} failed with error \"${UNZIP_DTD_RESULT}\". DocBook DTD and XSL autoconfiguration cannot continue.") + endif () + else() + list(GET DOCBOOK_DTD_STATUS 1 DOCBOOK_DTD_ERRORMSG) + message(SEND_ERROR "Unable to download DocBook DTD from ${DOCBOOK_DTD_URL}. Error was: \"${DOCBOOK_DTD_ERRORMSG}\"") + endif() + endif() +endmacro(download_docbook_dtd) + +# Downloads the DocBook XSL into a place where DOCBOOK_XSL_DIR can +# find it. +macro(download_docbook_xsl) + if (NOT DOCBOOK_XSL_DIR) + set(DOCBOOK_XSL_FILENAME "docbook-xsl-${WANT_DOCBOOK_XSL_VERSION}.zip") + set(DOCBOOK_XSL_URL + "${SOURCEFORGE_MIRROR}/sourceforge/docbook/${DOCBOOK_XSL_FILENAME}") + message(STATUS "Downloading DocBook XSL from ${DOCBOOK_XSL_URL}...") + file(DOWNLOAD + "${DOCBOOK_XSL_URL}" + "${CMAKE_BINARY_DIR}/${DOCBOOK_XSL_FILENAME}" + TIMEOUT 60 STATUS DOCBOOK_XSL_STATUS) + list(GET DOCBOOK_XSL_STATUS 0 DOCBOOK_XSL_ERROR) + if (DOCBOOK_XSL_ERROR EQUAL 0) + # Download successful! Extract the XSL ZIP file. + message(STATUS "Extracting DocBook XSL stylesheets...") + execute_process( + COMMAND ${UNZIP} -q "${CMAKE_BINARY_DIR}/${DOCBOOK_XSL_FILENAME}" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE UNZIP_XSL_RESULT) + if (UNZIP_XSL_RESULT EQUAL 0) + # Extraction successful. Clean up the downloaded file. + file(REMOVE ${CMAKE_BINARY_DIR}/${DOCBOOK_XSL_FILENAME}) + set(DOCBOOK_XSL_DIR + ${CMAKE_BINARY_DIR}/docbook-xsl-${WANT_DOCBOOK_XSL_VERSION} + CACHE PATH "Path to the DocBook XSL stylesheets" FORCE) + else() + # We failed: report the error to the user + message(SEND_ERROR "Extraction of DocBook XSL archive ${DOCBOOK_XSL_FILENAME} failed with error \"${UNZIP_XSL_RESULT}\". DocBook XSL and XSL autoconfiguration cannot continue.") + endif () + else() + list(GET DOCBOOK_XSL_STATUS 1 DOCBOOK_XSL_ERRORMSG) + message(SEND_ERROR "Unable to download DocBook XSL from ${DOCBOOK_XSL_URL}. Error was: \"${DOCBOOK_XSL_ERRORMSG}\". You might want to try another SourceForge mirror site by changing the advanced configuration variable SOURCEFORGE_MIRROR.") + endif() + endif() +endmacro(download_docbook_xsl) + +# Preferred versions of DocBook stylesheets and utilities. We don't +# require these, but we know that they work. +set(WANT_DOCBOOK_DTD_VERSION 4.2) +set(WANT_DOCBOOK_XSL_VERSION 1.73.2) + +# Find xsltproc to transform XML documents via XSLT +find_program(XSLTPROC xsltproc DOC "xsltproc transforms XML via XSLT") +set(XSLTPROC_FLAGS "--xinclude" CACHE STRING + "Flags to pass to xsltproc to transform XML documents") + +# Find the DocBook DTD (version 4.2) +find_path(DOCBOOK_DTD_DIR docbookx.dtd + PATHS "${CMAKE_BINARY_DIR}/docbook-dtd-${WANT_DOCBOOK_DTD_VERSION}" + DOC "Path to the DocBook DTD") + +# Find the DocBook XSL stylesheets +find_path(DOCBOOK_XSL_DIR html/html.xsl + PATHS "${CMAKE_BINARY_DIR}/docbook-xsl-${WANT_DOCBOOK_XSL_VERSION}" + DOC "Path to the DocBook XSL stylesheets") + +# Find the BoostBook DTD (it should be in the distribution!) +find_path(BOOSTBOOK_DTD_DIR boostbook.dtd + PATHS ${CMAKE_SOURCE_DIR}/tools/boostbook/dtd + DOC "Path to the BoostBook DTD") +mark_as_advanced(BOOSTBOOK_DTD_DIR) + +# Find the BoostBook XSL stylesheets (they should be in the distribution!) +find_path(BOOSTBOOK_XSL_DIR docbook.xsl + PATHS ${CMAKE_SOURCE_DIR}/tools/boostbook/xsl + DOC "Path to the BoostBook XSL stylesheets") +mark_as_advanced(BOOSTBOOK_XSL_DIR) + +# Try to find Doxygen +find_package(Doxygen) + +if (XSLTPROC AND DOXYGEN) + if (DOCBOOK_DTD_DIR AND DOCBOOK_XSL_DIR) + # Documentation build options + option(BUILD_DOCUMENTATION "Whether to build library documentation" ON) + option(BUILD_DOCUMENTATION_HTML "Whether to build HTML documentation" ON) + option(BUILD_DOCUMENTATION_MAN_PAGES "Whether to build Unix man pages" ON) + + # Generate an XML catalog file. + configure_file(${CMAKE_SOURCE_DIR}/tools/build/CMake/catalog.xml.in + ${CMAKE_BINARY_DIR}/catalog.xml + @ONLY) + else() + # Look for "unzip", because we'll need it to download the DocBook + # DTD and XSL stylesheets as part of autoconfiguration. + find_program(UNZIP unzip DOC "Used to extract ZIP archives") + + if (UNZIP) + option(DOCBOOK_AUTOCONFIG + "Automatically download and configure DocBook DTD and XSL" OFF) + set(SOURCEFORGE_MIRROR "http://dl.sourceforge.net" + CACHE STRING "SourceForge mirror used to download DocBook XSL during autoconfiguration") + mark_as_advanced(SOURCEFORGE_MIRROR) + if (DOCBOOK_AUTOCONFIG) + message(STATUS "Initiating DocBook DTD and XSL autoconfiguration...") + download_docbook_dtd() + download_docbook_xsl() + endif (DOCBOOK_AUTOCONFIG) + endif() + endif() +endif() + +# Turn off BUILD_DOCUMENTATION if it isn't going to succeed. +if (BUILD_DOCUMENTATION) + set(BUILD_DOCUMENTATION_OKAY TRUE) + if (NOT XSLTPROC) + set(BUILD_DOCUMENTATION_OKAY FALSE) + elseif (NOT DOXYGEN) + set(BUILD_DOCUMENTATION_OKAY FALSE) + elseif (NOT DOCBOOK_DTD_DIR) + set(BUILD_DOCUMENTATION_OKAY FALSE) + elseif (NOT DOCBOOK_XSL_DIR) + set(BUILD_DOCUMENTATION_OKAY FALSE) + else() + set(BUILD_DOCUMENTATION_OKAY TRUE) + endif() + + if (NOT BUILD_DOCUMENTATION_OKAY) + if (BUILD_DOCUMENTATION) + set(BUILD_DOCUMENTATION OFF CACHE BOOL + "Whether to build library documentation" FORCE) + endif() + endif() +endif() \ No newline at end of file diff --git a/CMake/BoostTesting.cmake b/CMake/BoostTesting.cmake new file mode 100644 index 000000000..e33fe40e4 --- /dev/null +++ b/CMake/BoostTesting.cmake @@ -0,0 +1,382 @@ +########################################################################## +# Regression Testing Support for Boost # +########################################################################## +# Copyright (C) 2007-8 Douglas Gregor # +# Copyright (C) 2007-8 Troy D. Straszheim # +# # +# Distributed under the Boost Software License, Version 1.0. # +# See accompanying file LICENSE_1_0.txt or copy at # +# http://www.boost.org/LICENSE_1_0.txt # +########################################################################## +# This file provides a set of CMake macros that support regression +# testing for Boost libraries. For each of the test macros below, the +# first argument, testname, states the name of the test that will be +# created. If no other arguments are provided, the source file +# testname.cpp will be used as the source file; otherwise, source +# files should be listed immediately after the name of the test. +# +# The macros for creating regression tests are: +# boost_test_run: Builds an executable and runs it as a test. The test +# succeeds if it builds and returns 0 when executed. +# +# boost_test_run_fail: Builds an executable and runs it as a test. The +# test succeeds if it builds but returns a non-zero +# exit code when executed. +# +# boost_test_compile: Tests that the given source file compiles without +# any errors. +# +# boost_test_compile_fail: Tests that the given source file produces +# errors when compiled. + +# User-controlled option that can be used to enable/disable regression +# testing. By default, we disable testing, because most users won't +# want or need to perform regression testing on Boost. The Boost build +# is significantly faster when we aren't also building regression +# tests. +option(BUILD_TESTING "Enable testing" OFF) + +if (BUILD_TESTING) + add_custom_target(test COMMENT "Running all tests") + + option(TEST_INSTALLED_TREE "Enable testing of an already-installed tree" OFF) + + if (TEST_INSTALLED_TREE) + include("${CMAKE_INSTALL_PREFIX}/lib/Boost${BOOST_VERSION}/boost-targets.cmake") + endif (TEST_INSTALLED_TREE) +endif (BUILD_TESTING) + +option(BOOST_BUILD_SANITY_TEST + "Don't build regular boost libraries, build libraries that test the boost cmake build system itself" OFF) + +if(BOOST_BUILD_SANITY_TEST) + set(BOOST_LIBS_DIR ${CMAKE_SOURCE_DIR}/tools/build/CMake/sanity) + configure_file(${CMAKE_SOURCE_DIR}/libs/CMakeLists.txt ${BOOST_LIBS_DIR}/CMakeLists.txt COPYONLY) +else(BOOST_BUILD_SANITY_TEST) + set(BOOST_LIBS_DIR ${CMAKE_SOURCE_DIR}/libs) +endif(BOOST_BUILD_SANITY_TEST) + + +# This macro is an internal utility macro that helps parse the +# arguments passed to the Boost testing commands. It will generally +# not be used by Boost developers. +macro(boost_test_add_dependent_includes includes) + foreach (include ${includes}) + #message(STATUS "include: ${include}") + include_directories("${Boost_SOURCE_DIR}/libs/${include}/include") + endforeach (include ${includes}) +endmacro(boost_test_add_dependent_includes includes) + + + +# This macro is an internal utility macro that helps parse the +# arguments passed to the Boost testing commands. It will generally +# not be used by Boost developers. +# +# boost_test_parse_args(testname +# [source1 source2 ...] +# [ARGS arg1 arg2... ] +# [COMPILE_FLAGS compileflags] +# [LINK_FLAGS linkflags] +# [LINK_LIBS linklibs] +# [DEPENDS libdepend1 libdepend2 ...] +# [COMPILE] [RUN] [FAIL]) +# +# testname is the name of the test. The remaining arguments passed to +# this macro will be parsed and categorized for the developer-level +# test macros to use. +# +# Variables affected: +# +# BOOST_TEST_OKAY: Will be set to TRUE if it is okay to build and +# run this test. +# +# BOOST_TEST_SOURCES: Will be populated with the set of source files +# that should be used to compile this test. If the user has provided +# source files, BOOST_TEST_SOURCES will contain those; otherwise, +# BOOST_TEST_SOURCES will only contain "testname.cpp". +# +# BOOST_TEST_TAG: compile, compile_fail, run, or run_fail. +# Used in test-reporting systems. +# +# BOOST_TEST_TESTNAME: A (hopefully) globally unique target name +# for the test, constructed from PROJECT-testname-TAG +# +# BOOST_TEST_arg: Will be populated with the arguments provided for +# the arguemnt "arg", where "arg" can be any of the extra arguments +# specified above. +# +# +macro(boost_test_parse_args testname) + #message("boost_test_parse_args ${testname} ${ARGN}") + set(BOOST_TEST_OKAY TRUE) + set(BOOST_TEST_COMPILE_FLAGS "") + parse_arguments(BOOST_TEST + "LINK_LIBS;LINK_FLAGS;DEPENDS;COMPILE_FLAGS;ARGS;EXTRA_OPTIONS" + "COMPILE;RUN;LINK;FAIL;RELEASE;DEBUG" + ${ARGN} + ) + + # Check each of the dependencies to see if we can still build this + # test. + foreach(ARG ${BOOST_TEST_DEPENDS}) + get_target_property(DEPEND_TYPE ${ARG} TYPE) + get_target_property(DEPEND_LOCATION ${ARG} LOCATION) + # If building static libraries is turned off, don't try to build + # the test + if (NOT BUILD_STATIC AND ${DEPEND_TYPE} STREQUAL "STATIC_LIBRARY") + set(BOOST_TEST_OKAY FALSE) + endif (NOT BUILD_STATIC AND ${DEPEND_TYPE} STREQUAL "STATIC_LIBRARY") + + # If building shared libraries is turned off, don't try to build + # the test + if (NOT BUILD_SHARED AND ${DEPEND_TYPE} STREQUAL "SHARED_LIBRARY") + set(BOOST_TEST_OKAY FALSE) + endif (NOT BUILD_SHARED AND ${DEPEND_TYPE} STREQUAL "SHARED_LIBRARY") + endforeach(ARG ${BOOST_TEST_DEPENDS}) + + # Setup the SOURCES variables. If no sources are specified, use the + # name of the test.cpp + if (BOOST_TEST_DEFAULT_ARGS) + set(BOOST_TEST_SOURCES ${BOOST_TEST_DEFAULT_ARGS}) + else (BOOST_TEST_DEFAULT_ARGS) + set(BOOST_TEST_SOURCES "${testname}.cpp") + endif (BOOST_TEST_DEFAULT_ARGS) + + #message("Sources: ${BOOST_TEST_SOURCES}") + if (BOOST_TEST_RUN) + set(BOOST_TEST_TAG "run") + elseif(BOOST_TEST_COMPILE) + set(BOOST_TEST_TAG "compile") + elseif(BOOST_TEST_LINK) + set(BOOST_TEST_TAG "link") + endif(BOOST_TEST_RUN) + + if (BOOST_TEST_FAIL) + set(BOOST_TEST_TAG ${BOOST_TEST_TAG}-fail) + endif(BOOST_TEST_FAIL) + + set(BOOST_TEST_TESTNAME "${PROJECT_NAME}-${testname}-${BOOST_TEST_TAG}") + #message("testname: ${BOOST_TEST_TESTNAME}") + # If testing is turned off, this test is not okay + if (NOT BUILD_TESTING) + set(BOOST_TEST_OKAY FALSE) + endif(NOT BUILD_TESTING) + +endmacro(boost_test_parse_args) + +# This macro creates a Boost regression test that will be executed. If +# the test can be built, executed, and exits with a return code of +# zero, it will be considered to have passed. +# +# boost_test_run(testname +# [source1 source2 ...] +# [ARGS arg1 arg2... ] +# [COMPILE_FLAGS compileflags] +# [LINK_FLAGS linkflags] +# [LINK_LIBS linklibs] +# [DEPENDS libdepend1 libdepend2 ...] +# [EXTRA_OPTIONS option1 option2 ...]) +# +# testname is the name of the test. source1, source2, etc. are the +# source files that will be built and linked into the test +# executable. If no source files are provided, the file "testname.cpp" +# will be used instead. +# +# There are several optional arguments to control how the regression +# test is built and executed: +# +# ARGS: Provides additional arguments that will be passed to the +# test executable when it is run. +# +# COMPILE_FLAGS: Provides additional compilation flags that will be +# used when building this test. For example, one might want to add +# "-DBOOST_SIGNALS_ASSERT=1" to turn on assertions within the library. +# +# LINK_FLAGS: Provides additional flags that will be passed to the +# linker when linking the test excecutable. This option should not +# be used to link in additional libraries; see LINK_LIBS and +# DEPENDS. +# +# LINK_LIBS: Provides additional libraries against which the test +# executable will be linked. For example, one might provide "expat" +# as options to LINK_LIBS, to state that this executable should be +# linked against the external "expat" library. Use LINK_LIBS for +# libraries external to Boost; for Boost libraries, use DEPENDS. +# +# DEPENDS: States that this test executable depends on and links +# against another Boost library. The argument to DEPENDS should be +# the name of a particular variant of a Boost library, e.g., +# boost_signals-static. +# +# EXTRA_OPTIONS: Provide extra options that will be passed on to +# boost_add_executable. +# +# Example: +# boost_test_run(signal_test DEPENDS boost_signals) +macro(boost_test_run testname) + boost_test_parse_args(${testname} ${ARGN} RUN) + if (BOOST_TEST_OKAY) + boost_add_executable(${testname} ${BOOST_TEST_SOURCES} + OUTPUT_NAME tests/${PROJECT_NAME}/${testname} + DEPENDS "${BOOST_TEST_DEPENDS}" + LINK_LIBS ${BOOST_TEST_LINK_LIBS} + LINK_FLAGS ${BOOST_TEST_LINK_FLAGS} + COMPILE_FLAGS ${BOOST_TEST_COMPILE_FLAGS} + NO_INSTALL + ${BOOST_TEST_EXTRA_OPTIONS}) + + if (THIS_EXE_OKAY) + # This target builds and runs the test + add_custom_target(${BOOST_TEST_TESTNAME}) + + file( TO_NATIVE_PATH "${BOOST_TEST_DRIVER}" NATIVE_BOOST_TEST_DRIVER ) + + set(THIS_TEST_PREFIX_ARGS + ${PYTHON_EXECUTABLE} ${NATIVE_BOOST_TEST_DRIVER} + ${CMAKE_CURRENT_BINARY_DIR} ${BOOST_TEST_TAG} ${testname} + ) + + add_custom_command(TARGET ${BOOST_TEST_TESTNAME} + POST_BUILD + COMMAND + ${THIS_TEST_PREFIX_ARGS} + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/tests/${PROJECT_NAME}/${testname} + ${BOOST_TEST_ARGS} + COMMENT "Running ${testname} in project ${PROJECT_NAME}" + ) + + add_dependencies(${BOOST_TEST_TESTNAME} + ${PROJECT_NAME}-${testname} + ) + + add_dependencies(${PROJECT_NAME}-test + ${BOOST_TEST_TESTNAME} + ) + + endif(THIS_EXE_OKAY) + endif (BOOST_TEST_OKAY) +endmacro(boost_test_run) + +# +# This macro creates a boost regression test that will be run but is +# expected to fail (exit with nonzero return code). +# See boost_test_run() +# +macro(boost_test_run_fail testname) + boost_test_run(${testname} ${ARGN} FAIL) +endmacro(boost_test_run_fail) + + +# This macro creates a Boost regression test that will be compiled, +# but not linked or executed. If the test can be compiled with no +# failures, the test passes. +# +# boost_test_compile(testname +# [source1] +# [COMPILE_FLAGS compileflags]) +# +# testname is the name of the test. source1 is the name of the source +# file that will be built. If no source file is provided, the file +# "testname.cpp" will be used instead. +# +# The COMPILE_FLAGS argument provides additional arguments that will +# be passed to the compiler when building this test. + +# Example: +# boost_test_compile(advance) +macro(boost_test_compile testname) + boost_test_parse_args(${testname} ${ARGN} COMPILE) + + + if (BOOST_TEST_OKAY) + # Determine the include directories to pass along to the underlying + # project. + # works but not great + get_directory_property(BOOST_TEST_INCLUDE_DIRS INCLUDE_DIRECTORIES) + set(BOOST_TEST_INCLUDES "") + foreach(DIR ${BOOST_TEST_INCLUDE_DIRS}) + set(BOOST_TEST_INCLUDES "${BOOST_TEST_INCLUDES};-I${DIR}") + endforeach(DIR ${BOOST_TEST_INCLUDE_DIRS}) + + set(THIS_TEST_PREFIX_ARGS + ${PYTHON_EXECUTABLE} ${BOOST_TEST_DRIVER} ${CMAKE_CURRENT_BINARY_DIR} ${BOOST_TEST_TAG} ${testname} + ) + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BOOST_TEST_TESTNAME}.${CMAKE_CXX_OUTPUT_EXTENSION} + COMMAND + ${THIS_TEST_PREFIX_ARGS} + ${CMAKE_CXX_COMPILER} + ${BOOST_TEST_COMPILE_FLAGS} + ${BOOST_TEST_INCLUDES} + -c ${BOOST_TEST_SOURCES} + -o ${CMAKE_CURRENT_BINARY_DIR}/${BOOST_TEST_TESTNAME}${CMAKE_CXX_OUTPUT_EXTENSION} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${BOOST_TEST_SOURCES} + COMMENT "Running ${testname} in project ${PROJECT_NAME}" + ) + + add_custom_target(${BOOST_TEST_TESTNAME} + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${BOOST_TEST_TESTNAME}.${CMAKE_CXX_OUTPUT_EXTENSION} + ) + + add_dependencies(${PROJECT_NAME}-test + ${BOOST_TEST_TESTNAME} + ) + + endif(BOOST_TEST_OKAY) +endmacro(boost_test_compile) + +# +# This macro creates a Boost regression test that is expected to +# *fail* to compile. See boost_test_compile() +# +macro(boost_test_compile_fail testname) + boost_test_compile(${testname} ${ARGN} FAIL) +endmacro(boost_test_compile_fail) + + + + +# +# boost_test_link: +# +# Under construction. +# +macro(boost_test_link testname) + boost_test_parse_args(${testname} ${ARGN} LINK) + if(BOOST_TEST_OKAY) + + set(THIS_TEST_PREFIX_ARGS + ${PYTHON_EXECUTABLE} ${BOOST_TEST_DRIVER} ${CMAKE_CURRENT_BINARY_DIR} test_link ${testname} + ) + + # + # FIXME: no ctest. + # + add_custom_target(TARGET ${BOOST_TEST_TESTNAME} + COMMAND /link/tests/are/failing/at/the/moment + COMMENT "Link test ${testname} in ${PROJECT_NAME} is failing." + ) + + # POST_BUILD + # COMMAND + # ${THIS_TEST_PREFIX_ARGS} + # ${CMAKE_CTEST_COMMAND} + # --build-and-test + # ${Boost_SOURCE_DIR}/tools/build/CMake/LinkTest + # ${Boost_BINARY_DIR}/tools/build/CMake/LinkTest + # --build-generator \\"${CMAKE_GENERATOR}\\" + # --build-makeprogram \\"${MAKEPROGRAM}\\" + # --build-project LinkTest + # --build-options -DSOURCE=${CMAKE_CURRENT_SOURCE_DIR}/${BOOST_TEST_SOURCES} -DINCLUDES=${Boost_SOURCE_DIR} -DCOMPILE_FLAGS=\\"${BOOST_TEST_COMPILE_FLAGS}\\" + # COMMENT "Running ${testname} (link) in project ${PROJECT_NAME}" + # ) + + add_dependencies(${PROJECT_NAME}-test + ${BOOST_TEST_TESTNAME} + ) + + endif(BOOST_TEST_OKAY) +endmacro(boost_test_link) + diff --git a/CMake/BoostUtils.cmake b/CMake/BoostUtils.cmake new file mode 100644 index 000000000..77b17f783 --- /dev/null +++ b/CMake/BoostUtils.cmake @@ -0,0 +1,213 @@ +########################################################################## +# Boost Utilities # +########################################################################## +# Copyright (C) 2007 Douglas Gregor # +# Copyright (C) 2007 Troy Straszheim # +# # +# Distributed under the Boost Software License, Version 1.0. # +# See accompanying file LICENSE_1_0.txt or copy at # +# http://www.boost.org/LICENSE_1_0.txt # +########################################################################## +# Macros in this module: # +# # +# list_contains: Determine whether a string value is in a list. # +# # +# car: Return the first element in a list # +# # +# cdr: Return all but the first element in a list # +# # +# parse_arguments: Parse keyword arguments for use in other macros. # +########################################################################## + +# This utility macro determines whether a particular string value +# occurs within a list of strings: +# +# list_contains(result string_to_find arg1 arg2 arg3 ... argn) +# +# This macro sets the variable named by result equal to TRUE if +# string_to_find is found anywhere in the following arguments. +macro(list_contains var value) + set(${var}) + foreach (value2 ${ARGN}) + if (${value} STREQUAL ${value2}) + set(${var} TRUE) + endif (${value} STREQUAL ${value2}) + endforeach (value2) +endmacro(list_contains) + +# This utility macro extracts the first argument from the list of +# arguments given, and places it into the variable named var. +# +# car(var arg1 arg2 ...) +macro(car var) + set(${var} ${ARGV1}) +endmacro(car) + +# This utility macro extracts all of the arguments given except the +# first, and places them into the variable named var. +# +# car(var arg1 arg2 ...) +macro(cdr var junk) + set(${var} ${ARGN}) +endmacro(cdr) + +# The PARSE_ARGUMENTS macro will take the arguments of another macro and +# define several variables. The first argument to PARSE_ARGUMENTS is a +# prefix to put on all variables it creates. The second argument is a +# list of names, and the third argument is a list of options. Both of +# these lists should be quoted. The rest of PARSE_ARGUMENTS are +# arguments from another macro to be parsed. +# +# PARSE_ARGUMENTS(prefix arg_names options arg1 arg2...) +# +# For each item in options, PARSE_ARGUMENTS will create a variable with +# that name, prefixed with prefix_. So, for example, if prefix is +# MY_MACRO and options is OPTION1;OPTION2, then PARSE_ARGUMENTS will +# create the variables MY_MACRO_OPTION1 and MY_MACRO_OPTION2. These +# variables will be set to true if the option exists in the command line +# or false otherwise. +# +# For each item in arg_names, PARSE_ARGUMENTS will create a variable +# with that name, prefixed with prefix_. Each variable will be filled +# with the arguments that occur after the given arg_name is encountered +# up to the next arg_name or the end of the arguments. All options are +# removed from these lists. PARSE_ARGUMENTS also creates a +# prefix_DEFAULT_ARGS variable containing the list of all arguments up +# to the first arg_name encountered. +MACRO(PARSE_ARGUMENTS prefix arg_names option_names) + SET(DEFAULT_ARGS) + FOREACH(arg_name ${arg_names}) + SET(${prefix}_${arg_name}) + ENDFOREACH(arg_name) + FOREACH(option ${option_names}) + SET(${prefix}_${option} FALSE) + ENDFOREACH(option) + + SET(current_arg_name DEFAULT_ARGS) + SET(current_arg_list) + FOREACH(arg ${ARGN}) + LIST_CONTAINS(is_arg_name ${arg} ${arg_names}) + IF (is_arg_name) + SET(${prefix}_${current_arg_name} ${current_arg_list}) + SET(current_arg_name ${arg}) + SET(current_arg_list) + ELSE (is_arg_name) + LIST_CONTAINS(is_option ${arg} ${option_names}) + IF (is_option) + SET(${prefix}_${arg} TRUE) + ELSE (is_option) + SET(current_arg_list ${current_arg_list} ${arg}) + ENDIF (is_option) + ENDIF (is_arg_name) + ENDFOREACH(arg) + SET(${prefix}_${current_arg_name} ${current_arg_list}) +ENDMACRO(PARSE_ARGUMENTS) + +# Perform a reverse topological sort on the given LIST. +# +# topological_sort(my_list "MY_" "_EDGES") +# +# LIST is the name of a variable containing a list of elements to be +# sorted in reverse topological order. Each element in the list has a +# set of outgoing edges (for example, those other list elements that +# it depends on). In the resulting reverse topological ordering +# (written back into the variable named LIST), an element will come +# later in the list than any of the elements that can be reached by +# following its outgoing edges and the outgoing edges of any vertices +# they target, recursively. Thus, if the edges represent dependencies +# on build targets, for example, the reverse topological ordering is +# the order in which one would build those targets. +# +# For each element E in this list, the edges for E are contained in +# the variable named ${PREFIX}${E}${SUFFIX}, where E is the +# upper-cased version of the element in the list. If no such variable +# exists, then it is assumed that there are no edges. For example, if +# my_list contains a, b, and c, one could provide a dependency graph +# using the following variables: +# +# MY_A_EDGES b +# MY_B_EDGES +# MY_C_EDGES a b +# +# With the involcation of topological_sort shown above and these +# variables, the resulting reverse topological ordering will be b, a, +# c. +function(topological_sort LIST PREFIX SUFFIX) + # Clear the stack and output variable + set(VERTICES "${${LIST}}") + set(STACK) + set(${LIST}) + + # Loop over all of the vertices, starting the topological sort from + # each one. + foreach(VERTEX ${VERTICES}) + string(TOUPPER ${VERTEX} UPPER_VERTEX) + + # If we haven't already processed this vertex, start a depth-first + # search from where. + if (NOT FOUND_${UPPER_VERTEX}) + # Push this vertex onto the stack with all of its outgoing edges + string(REPLACE ";" " " NEW_ELEMENT + "${VERTEX};${${PREFIX}${UPPER_VERTEX}${SUFFIX}}") + list(APPEND STACK ${NEW_ELEMENT}) + + # We've now seen this vertex + set(FOUND_${UPPER_VERTEX} TRUE) + + # While the depth-first search stack is not empty + list(LENGTH STACK STACK_LENGTH) + while(STACK_LENGTH GREATER 0) + # Remove the vertex and its remaining out-edges from the top + # of the stack + list(GET STACK -1 OUT_EDGES) + list(REMOVE_AT STACK -1) + + # Get the source vertex and the list of out-edges + separate_arguments(OUT_EDGES) + list(GET OUT_EDGES 0 SOURCE) + list(REMOVE_AT OUT_EDGES 0) + + # While there are still out-edges remaining + list(LENGTH OUT_EDGES OUT_DEGREE) + while (OUT_DEGREE GREATER 0) + # Pull off the first outgoing edge + list(GET OUT_EDGES 0 TARGET) + list(REMOVE_AT OUT_EDGES 0) + + string(TOUPPER ${TARGET} UPPER_TARGET) + if (NOT FOUND_${UPPER_TARGET}) + # We have not seen the target before, so we will traverse + # its outgoing edges before coming back to our + # source. This is the key to the depth-first traversal. + + # We've now seen this vertex + set(FOUND_${UPPER_TARGET} TRUE) + + # Push the remaining edges for the current vertex onto the + # stack + string(REPLACE ";" " " NEW_ELEMENT + "${SOURCE};${OUT_EDGES}") + list(APPEND STACK ${NEW_ELEMENT}) + + # Setup the new source and outgoing edges + set(SOURCE ${TARGET}) + string(TOUPPER ${SOURCE} UPPER_SOURCE) + set(OUT_EDGES + ${${PREFIX}${UPPER_SOURCE}${SUFFIX}}) + endif(NOT FOUND_${UPPER_TARGET}) + + list(LENGTH OUT_EDGES OUT_DEGREE) + endwhile (OUT_DEGREE GREATER 0) + + # We have finished all of the outgoing edges for + # SOURCE; add it to the resulting list. + list(APPEND ${LIST} ${SOURCE}) + + # Check the length of the stack + list(LENGTH STACK STACK_LENGTH) + endwhile(STACK_LENGTH GREATER 0) + endif (NOT FOUND_${UPPER_VERTEX}) + endforeach(VERTEX) + + set(${LIST} ${${LIST}} PARENT_SCOPE) +endfunction(topological_sort) diff --git a/CMake/FindICU.cmake b/CMake/FindICU.cmake new file mode 100644 index 000000000..9dff9f398 --- /dev/null +++ b/CMake/FindICU.cmake @@ -0,0 +1,51 @@ +# Finds the International Components for Unicode (ICU) Library +# +# ICU_FOUND - True if ICU found. +# ICU_I18N_FOUND - True if ICU's internationalization library found. +# ICU_INCLUDE_DIRS - Directory to include to get ICU headers +# Note: always include ICU headers as, e.g., +# unicode/utypes.h +# ICU_LIBRARIES - Libraries to link against for the common ICU +# ICU_I18N_LIBRARIES - Libraries to link against for ICU internationaliation +# (note: in addition to ICU_LIBRARIES) + +# Look for the header file. +find_path( + ICU_INCLUDE_DIR + NAMES unicode/utypes.h + DOC "Include directory for the ICU library") +mark_as_advanced(ICU_INCLUDE_DIR) + +# Look for the library. +find_library( + ICU_LIBRARY + NAMES icuuc cygicuuc cygicuuc32 + DOC "Libraries to link against for the common parts of ICU") +mark_as_advanced(ICU_LIBRARY) + +# Copy the results to the output variables. +if(ICU_INCLUDE_DIR AND ICU_LIBRARY) + set(ICU_FOUND 1) + set(ICU_LIBRARIES ${ICU_LIBRARY}) + set(ICU_INCLUDE_DIRS ${ICU_INCLUDE_DIR}) + + # Look for the ICU internationalization libraries + find_library( + ICU_I18N_LIBRARY + NAMES icuin icui18n cygicuin cygicuin32 + DOC "Libraries to link against for ICU internationalization") + mark_as_advanced(ICU_I18N_LIBRARY) + if (ICU_I18N_LIBRARY) + set(ICU_I18N_FOUND 1) + set(ICU_I18N_LIBRARIES ${ICU_I18N_LIBRARY}) + else (ICU_I18N_LIBRARY) + set(ICU_I18N_FOUND 0) + set(ICU_I18N_LIBRARIES) + endif (ICU_I18N_LIBRARY) +else(ICU_INCLUDE_DIR AND ICU_LIBRARY) + set(ICU_FOUND 0) + set(ICU_I18N_FOUND 0) + set(ICU_LIBRARIES) + set(ICU_I18N_LIBRARIES) + set(ICU_INCLUDE_DIRS) +endif(ICU_INCLUDE_DIR AND ICU_LIBRARY) diff --git a/CMake/boost_build_slave.py.in b/CMake/boost_build_slave.py.in new file mode 100755 index 000000000..9d80ed872 --- /dev/null +++ b/CMake/boost_build_slave.py.in @@ -0,0 +1,57 @@ +#!/usr/bin/python +# +# copyright (C) 2008 troy d. straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +# + +# +# Utilities, variables, imports for build slave python +# + +import os, os.path, marshal, xmlrpclib, pysvn, socket, platform +from pprint import pprint + +repo_path = "@CMAKE_SOURCE_DIR@" +client = pysvn.Client() +svn_entry = client.info(repo_path) +_configured_hostname = "@BOOST_BUILD_SLAVE_HOSTNAME@" +fqdn = _configured_hostname if len(_configured_hostname) > 0 else socket.getfqdn() +uname = platform.uname() +toolset = "@BOOST_TOOLSET@" + +timeout_seconds = @BOOST_BUILD_SLAVE_TIMEOUT@ +slave_details_file = "@BOOST_BUILD_SLAVE_DETAILS_FILE@" +contact_info = "@BOOST_BUILD_SLAVE_CONTACT_INFO@" + +xmlrpc_url = "@BOOST_BUILD_SLAVE_SUBMIT_URL@" + +build_id_file = os.path.join(r'@BOOST_BUILD_SLAVE_PYTHONPATH@', "build_id.txt") + +try: + f = open(build_id_file) + build_id = int(f.read()) +except: + build_id = None + +def set_build_id(build_id): + print "Setting new build id %d locally" % build_id + f = open(build_id_file, "w") + f.write(str(build_id)) + f.close() + +def details(): + if os.path.isabs(slave_details_file): + thefile = slave_details_file + else: + thefile = os.path.join("@CMAKE_BINARY_DIR@", slave_details_file) + + if os.path.exists(thefile): + f = open(thefile) + txt = f.read() + else: + txt = "Build slave details file @BOOST_BUILD_SLAVE_DETAILS_FILE@ not found." + + return txt diff --git a/CMake/catalog.xml.in b/CMake/catalog.xml.in new file mode 100644 index 000000000..75bc4f1d0 --- /dev/null +++ b/CMake/catalog.xml.in @@ -0,0 +1,9 @@ + + + + + + + diff --git a/CMake/classify.py.in b/CMake/classify.py.in new file mode 100755 index 000000000..212cc8ba6 --- /dev/null +++ b/CMake/classify.py.in @@ -0,0 +1,51 @@ +# +# Classifies pass/fail/warn for the sake of traash +# + +toolset = '@BOOST_TOOLSET@' +import os + +# 'cxx_compile_object' +# 'run' +# 'link_executable' +# 'create_shared_library' +# 'create_static_library' +# 'compile-fail' + +def classify(step): + print "step=", step + if 'errno' in step: + if step['errno'] == 666: + step['status'] = 'timeout' + else: + step['status'] = 'not_executed' + return + + if step['returncode'] != 0 and not step['expect_fail']: + step['status'] = 'fail' + return + + if step['returncode'] == 0 and step['expect_fail']: + step['status'] = 'unexpected_pass' + return + + # + # if it is an expected failure, don't warn just cause of warnings. + # + if step['returncode'] != 0 and step['expect_fail']: + step['status'] = 'pass' + return + + + if step['op'] != 'run' and len(step['stderr']) != 0 and not step['stderr'].isspace(): + step['status'] = 'warn' + return + + # on windoze, warnings are to be found in stdout... but the compiler always + # prints the name of the file first. So warn if there is more than one line + # in stdout. For now. + if os.name == 'nt' and step['op'] == 'cxx_compile_object' and step['stdout'].count('\n') > 1: + step['status'] = 'warn' + return + + step['status'] = 'pass' diff --git a/CMake/finish.py.in b/CMake/finish.py.in new file mode 100755 index 000000000..9952949b9 --- /dev/null +++ b/CMake/finish.py.in @@ -0,0 +1,23 @@ +#!/usr/bin/python +# +# copyright (C) 2008 troy d. straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +# + +# +# Start a new build, notify server via xmlrpc +# + +import sys +sys.path.append("@BOOST_BUILD_SLAVE_PYTHONPATH@") +from boost_build_slave import * + +print '\nFinishing build %d with %s via XML-RPC' % (build_id, xmlrpc_url) +s = xmlrpclib.Server(xmlrpc_url) + +s.traash.finish_build(build_id) + + diff --git a/CMake/info.py.in b/CMake/info.py.in new file mode 100755 index 000000000..0694cf6c0 --- /dev/null +++ b/CMake/info.py.in @@ -0,0 +1,26 @@ +#!/usr/bin/python +# +# copyright (C) 2008 troy d. straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +# + +# +# Start a new build, notify server via xmlrpc +# + +import sys +sys.path.append("@BOOST_BUILD_SLAVE_PYTHONPATH@") +from boost_build_slave import * + +print ' Url:', svn_entry.url, "at rev", svn_entry.revision.number +print ' FQDN:', fqdn +print ' Uname:', uname +print ' Toolset:', toolset +print ' Build ID:', build_id +print ' Contact:', contact_info +pref = '\n ' +print ' Details: ' + pref.join(details().splitlines()), '\n\n' + diff --git a/CMake/marshal.py.in b/CMake/marshal.py.in new file mode 100755 index 000000000..b59a77c3b --- /dev/null +++ b/CMake/marshal.py.in @@ -0,0 +1,110 @@ +#!/usr/bin/python +# +# copyright (C) 2008 troy d. straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +# +# +# Compiler driver. Takes a few arguments describing what is to be done +# (used to mark up the output) and executes compiler in a subshell, checking +# for errors and marshalling output to disk. +# +import sys, signal, threading, subprocess +sys.path.append("@BOOST_BUILD_SLAVE_PYTHONPATH@") +from boost_build_slave import * + +import datetime, time, signal +from subprocess import Popen, PIPE +from kill_subprocess import kill_subprocess +from classify import classify + +log = os.path.join(sys.argv[1], "Log.marshal") +op = sys.argv[2] +target = sys.argv[3] +argv = sys.argv[4:] +expect_fail = op.endswith("fail") + +if os.name == 'nt': + os.environ['PATH'] = r'@CMAKE_LIBRARY_OUTPUT_DIRECTORY@;' + os.environ['PATH'] + +print "***\n*** Executing op:" + op + "\n*** " + str(argv) + "\n*** log=" + log + "\n***" +# +# execute subprocess, watch for timeout +# +class SubprocThread(threading.Thread): + def __init__(self): + threading.Thread.__init__(self) + self.ex = None + + def run(self): + try: + self.proc = Popen(argv, stdout=PIPE, stderr=PIPE) + (self.stdout, self.stderr) = self.proc.communicate() + except EnvironmentError, e: + self.ex = e + +t = SubprocThread() +starttime = datetime.datetime.now() +t.start() +t.join(timeout_seconds) + +if t.isAlive(): + print "*** Killing subprocess after timeout" + kill_subprocess(t.proc.pid) + e = OSError() + e.errno = 666 + e.message = e.strerror = "TIMEOUT AFTER %d SECONDS" % timeout_seconds + e.filename = argv[0] + t.ex = e + +duration = datetime.datetime.now() - starttime + +# +# Collect and store subprocess info +# +result = { 'expect_fail' : expect_fail, + 'wallclock_duration' : duration.seconds + duration.microseconds * 10**-6 } + +if not t.ex: + result['returncode'] = t.proc.returncode + result['stdout'] = t.stdout + result['stderr'] = t.stderr + + if t.proc.returncode != 0 and not expect_fail: + print "*** returncode: %d" % t.proc.returncode + print "*** stdout:" + result['stdout'] + print "*** stderr:" + result['stderr'] +else: + result['errno'] = t.ex.errno + result['filename'] = t.ex.filename + result['message'] = t.ex.message + result['strerror'] = t.ex.strerror + print "Errno:" + str(t.ex.errno) + ": " + t.ex.strerror + +result.update({'op' : op, + 'target' : target, + 'cmdline' : argv }) + +classify(result) +print "post classification: result=", result + +f = open(log, "ab", 0) +marshal.dump(result, f) +f.close() + +if t.ex: + sys.exit(t.ex.errno) +else: + if expect_fail: + if t.proc.returncode != 0: + sys.exit(0) + else: + print "UNEXPECTED SUCCESS" + sys.exit(1) # we need an exit status for 'unexpected success' + else: + sys.exit(t.proc.returncode) + + + diff --git a/CMake/passthru.py.in b/CMake/passthru.py.in new file mode 100755 index 000000000..dd60ec353 --- /dev/null +++ b/CMake/passthru.py.in @@ -0,0 +1,73 @@ +#!/usr/bin/python +# +# copyright (C) 2008 troy d. straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +# + +# +# "Passthru" driver, only responsible for 'flipping' exit status of +# tests that are expected to fail. See driver.py for the version +# that is run when BOOST_BUILD_SLAVE is on, which does xmlizaton +# and the like +# +import sys, os, os.path +from subprocess import Popen, PIPE + +def verbose(what): + if @BOOST_DRIVER_VERBOSE@: + print what + +# ignored +# log = os.path.join(sys.argv[1], "Log.xml") +op = sys.argv[2] +# target = sys.argv[3] +argv = sys.argv[4:] +expect_fail = op.endswith("fail") + +# +# execute subprocess +# +subproc = None +returncode = None +ex = None +stdout = None +stderr = None +try: + subproc = Popen(argv, stdout=PIPE, stderr=PIPE) + (stdout, stderr) = subproc.communicate() +except EnvironmentError, e: + ex = e + +returncode = subproc.returncode + +if stdout: + print stdout +if stderr: + print stderr + +if not ex: + # possibly flip the return code + if not expect_fail: + if not returncode: + verbose("ok.") + else: + verbose("error.") + sys.exit(returncode) + else: + if returncode != 0: + verbose("ok.") + sys.exit(0) + else: + verbose("*** UNEXPECTED SUCCESS ***") + sys.exit(1) # we need an exit status for 'unexpected success' +else: + # if there is an os error 'above' the actual exit status of the subprocess, + # use the errno + print "Error in build system: " + str(ex.strerror) + sys.exit(ex.errno) + + + diff --git a/CMake/post.py.in b/CMake/post.py.in new file mode 100755 index 000000000..4f44294b0 --- /dev/null +++ b/CMake/post.py.in @@ -0,0 +1,56 @@ +#!/usr/bin/python +# +# copyright (C) 2008 troy d. straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +# + +# +# Send the build log via XML-RPC +# + +import sys +sys.path.append("@BOOST_BUILD_SLAVE_PYTHONPATH@") +from boost_build_slave import * + +s = xmlrpclib.Server(xmlrpc_url, allow_none=True) + +project_name = sys.argv[1] +parent_target = sys.argv[2] +build_or_test = sys.argv[3] +logdir = sys.argv[4] + +# print "\n>>>\n>>> Project " + project_name \ +# + "\n>>> POST build log for " + parent_target \ +# + "\n>>> from log dir" + logdir \ +# + "\n>>> to " + xmlrpc_url \ +# + "\n>>> Server build ID: %d" % build_id \ +# + "\n>>>" + +p = os.path.join(logdir, "Log.marshal") + +if not os.path.exists(p): + print "No results to submit" + sys.exit(0) + +f = open(p, "rb") + +i = 0 +while True: + try: + r = marshal.load(f) + r.update({ 'build_id' : build_id, + 'project' : project_name, + 'parent_target' : parent_target, + 'build_or_test' : build_or_test }) + s.traash.step(r) + i += 1 + except EOFError, e: + break + +print "Submitted ", i, " steps." +f.close() +os.remove(p) + diff --git a/CMake/run_continuous_slave.py.in b/CMake/run_continuous_slave.py.in new file mode 100755 index 000000000..8c8dd34d0 --- /dev/null +++ b/CMake/run_continuous_slave.py.in @@ -0,0 +1,82 @@ +#!/usr/bin/python +# +# Build slave script. +# + +import pysvn, os, time +from optparse import OptionParser + +parser = OptionParser() + +parser.add_option("-b", "--build-first", + action="store_true", dest="build_first", default=False, + help="Build on startup") + +parser.add_option("-c", "--clean-first", + action="store_true", dest="clean_first", default=False, + help="Clean on startup") + +parser.add_option("-C", "--clean-every-time", + action="store_true", dest="clean_every_time", default=False, + help="Clean before every build") + +parser.add_option("-k", "--keep-rebuilding", + action="store_true", dest="keep_rebuilding", default=False, + help="Rebuild even if there are no updates to svn") + +(options, args) = parser.parse_args() + + +client = pysvn.Client() + +wc_path = r'@CMAKE_SOURCE_DIR@' + +def do_build(clean_): + if clean_: + clean = 'clean' + else: + clean = '' + if os.name == 'nt': + cmd = 'nmake /I ' + clean + ' slave-start test slave-finish' + else: + cmd = 'make -i ' + clean + ' slave-start test slave-finish' + print "Starting build:\n>>> ", cmd + os.system(cmd) + + +if options.build_first: + do_build(options.clean_first) + +while True: + try: + svn_entry = client.info(wc_path) + + print "Wc has url %s rev %d.\nChecking for updates." \ + % (svn_entry.url, svn_entry.revision.number) + + ds = client.diff_summarize(url_or_path1=svn_entry.url, + revision1=pysvn.Revision(pysvn.opt_revision_kind.number, + svn_entry.revision.number), + url_or_path2=svn_entry.url, + revision2=pysvn.Revision(pysvn.opt_revision_kind.head) + ) + + if len(ds): + print "There are %d changesets:" % len(ds) + for j in ds: + print ">>>", j.path + print "Updating." + client.update(wc_path) + if len(ds) or options.keep_rebuilding: + do_build(options.clean_every_time) + else: + print "No updates." + except Exception, e: + print e + print "Error. Will retry." + + print "Sleeping %d seconds" % @BOOST_BUILD_SLAVE_SLEEP_DURATION@ + time.sleep(@BOOST_BUILD_SLAVE_SLEEP_DURATION@) + + + diff --git a/CMake/start.py.in b/CMake/start.py.in new file mode 100755 index 000000000..b068608fd --- /dev/null +++ b/CMake/start.py.in @@ -0,0 +1,38 @@ +#!/usr/bin/python +# +# copyright (C) 2008 troy d. straszheim +# +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt +# + +# +# Start a new build, notify server via xmlrpc +# + +import sys +sys.path.append("@BOOST_BUILD_SLAVE_PYTHONPATH@") +from boost_build_slave import * + +print 'Url:', svn_entry.url, "at rev", svn_entry.revision.number +print 'FQDN:', fqdn +print 'Uname:', uname +print 'Toolset:', toolset + +print '\nNotifying %s of new build via XML-RPC' % xmlrpc_url +s = xmlrpclib.Server(xmlrpc_url) + +build_id = s.traash.start_build({ 'svn_url' : svn_entry.url, + 'svn_rev' : svn_entry.revision.number, + 'sysname' : uname[0], + 'nodename' : uname[1], + 'sys_release' : uname[2], + 'sys_version' : uname[3], + 'sys_machine' : uname[4], + 'fqdn' : fqdn, + 'toolset' : toolset, + 'contact' : contact_info, + 'details' : details() }) + +set_build_id(build_id) diff --git a/CMake/unix_kill.py.in b/CMake/unix_kill.py.in new file mode 100755 index 000000000..166b32a7a --- /dev/null +++ b/CMake/unix_kill.py.in @@ -0,0 +1,6 @@ +import os, signal +def kill_subprocess(pid): + os.kill(pid, signal.SIGKILL) + os.waitpid(-1, os.WNOHANG) + + diff --git a/CMake/windows_kill.py.in b/CMake/windows_kill.py.in new file mode 100755 index 000000000..b96aad32e --- /dev/null +++ b/CMake/windows_kill.py.in @@ -0,0 +1,9 @@ +import os +def kill_subprocess(pid): + cmd = 'TASKKILL /PID ' + str(pid) + ' /T /F' + print "Timeout, killing subprocess:\n" + cmd + os.popen(cmd) + +import win32api, win32con +win32api.SetErrorMode( win32con.SEM_NOGPFAULTERRORBOX | win32con.SEM_FAILCRITICALERRORS ) +