diff --git a/.gitignore b/.gitignore index 87a267d895641f2b66b36a6426702984a094700a..45022ce6534d57f1350e9d7c5b0c1b6c9bd301d2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ junk.py +stage/ diff --git a/CMakeLists.txt b/CMakeLists.txt index e9f0c6b14eeec0ef4a60ae98603d3d5ae4064659..2b8da57ff355c6ca5edc5f6a28e2efc24365a23f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,9 +2,71 @@ # Author: Stefan Bienert #------------------------------------------------------------------------------- cmake_minimum_required(VERSION 2.6.4 FATAL_ERROR) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake_support) -project(PROMOD2) +project(PROMOD3 CXX C) -set (PROMOD2_VERSION_MAJOR 0) -set (PROMOD2_VERSION_MINOR 0) +include(PROMOD) +set(PROMOD3_VERSION_MAJOR 0) +set(PROMOD3_VERSION_MINOR 0) +set(PROMOD_VERSION_STRING ${PROMOD3_VERSION_MAJOR}.${PROMOD3_VERSION_MINOR}) + +if (CMAKE_COMPILER_IS_GNUCXX) + exec_program(gcc ARGS --version OUTPUT_VARIABLE CMAKE_C_COMPILER_VERSION) + if(CMAKE_C_COMPILER_VERSION MATCHES ".*4\\.[5-9].*") + set(PROMOD_GCC_45 true) + else() + set(PROMOD_GCC_45 false) + endif() +endif() + +if (OPTIMIZE) + set(CMAKE_BUILD_TYPE Release) + set(_OPT ON) +else() + set(CMAKE_BUILD_TYPE Debug) + set(_OPT OFF) +endif() + +setup_stage() +file(MAKE_DIRECTORY ${STAGE_DIR} + ${EXECUTABLE_OUTPUT_PATH} + ${HEADER_STAGE_PATH} + ${LIB_STAGE_PATH} + ${LIBEXEC_STAGE_PATH}) + +setup_compiler_flags() +setup_boost() + +find_package(Python 2.7 REQUIRED) +find_package(OPENSTRUCTURE 1.4 REQUIRED + COMPONENTS io mol seq seq_alg mol_alg conop) + +if (CMAKE_COMPILER_IS_GNUCXX) + # do not write back into cache, otherwise the compile command line gets + # expanded with multiple -fno-strict-aliasing flags, triggering a complete + # rebuild whenever cmake is run + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-strict-aliasing") + if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_GREATER "4.6") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes") + endif("${CMAKE_CXX_COMPILER_VERSION}" VERSION_GREATER "4.6") +endif() + +# basic environment +include_directories(${Boost_INCLUDE_DIRS} + ${OST_INCLUDE_DIR}) + +set(FILES_TO_BE_REMOVED ${CMAKE_SOURCE_DIR}/stage) +set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES + "${FILES_TO_BE_REMOVED}") + +## sub dirs to be recognised by CMake +## e.g. add_subdirectory(src), subdirs have thier own CMakeLists.txt +add_subdirectory(meld) + +## report setup +message(STATUS "PROMOD3 will be built with the following options:\n" + " OpenStructure (-DOST_ROOT) : ${OST_ROOT}\n" + " Optimized (-DOPTIMIZE) : ${_OPT}\n" + " Python : ${PYTHON_BINARY}\n") diff --git a/cmake_support/FindPython.cmake b/cmake_support/FindPython.cmake index 4b4bce09a84be3638ab954a665ae83b330c63b23..04861bc5f33999ea69bfeae1f32becff48780ad3 100644 --- a/cmake_support/FindPython.cmake +++ b/cmake_support/FindPython.cmake @@ -17,8 +17,8 @@ # Author: Marco Biasini #------------------------------------------------------------------------------- -set(PYTHON_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2) -set(PYTHON_MIN_VERSION 2.2.1) +set(PYTHON_VERSIONS 2.7) +set(PYTHON_MIN_VERSION 2.7) #------------------------------------------------------------------------------- # check for python framework @@ -42,12 +42,12 @@ endmacro() macro(_find_python PYTHON_ROOT VERSION) - string(REPLACE "." "" _VERSION_NO_DOTS ${VERSION}) + string(REPLACE "." "" _VERSION_NO_DOTS "${VERSION}") if(PYTHON_ROOT) find_library(PYTHON_LIBRARIES NAMES "python${_VERSION_NO_DOTS}" "python${VERSION}" HINTS "${PYTHON_ROOT}" - PATH_SUFFIXES lib + PATH_SUFFIXES lib libs NO_SYSTEM_ENVIRONMENT_PATH NO_DEFAULT_PATH ) find_path(PYTHON_INCLUDE_PATH @@ -69,17 +69,17 @@ macro(_find_python PYTHON_ROOT VERSION) endmacro() macro(_find_python_bin PYTHON_ROOT VERSION) - string(REPLACE "." "" _VERSION_NO_DOTS ${VERSION}) + string(REPLACE "." "" _VERSION_NO_DOTS "${VERSION}") if(PYTHON_ROOT) find_program(PYTHON_BINARY - NAMES "python" "python${_VERSION_NO_DOTS}" "python${VERSION}" + NAMES "python${_VERSION_NO_DOTS}" "python${VERSION}" python.exe HINTS "${PYTHON_ROOT}" PATH_SUFFIXES bin NO_SYSTEM_ENVIRONMENT_PATH NO_DEFAULT_PATH ) else() find_program(PYTHON_BINARY - NAMES "python" "python${_VERSION_NO_DOTS}" "python${VERSION}" + NAMES "python${_VERSION_NO_DOTS}" "python${VERSION}" HINTS "${CMAKE_PREFIX_PATH}" PATH_SUFFIXES bin ) @@ -96,7 +96,8 @@ macro(check_for_python_lib) _find_python("${PYTHON_ROOT}" "${PYTHON_VERSION}") else() foreach(_VERSION ${PYTHON_VERSIONS}) - if(${PYTHON_MIN_VERSION} VERSION_LESS ${_VERSION}) + if((${PYTHON_MIN_VERSION} VERSION_LESS ${_VERSION}) OR + (${PYTHON_MIN_VERSION} VERSION_EQUAL ${_VERSION})) _find_python("${PYTHON_ROOT}" "${_VERSION}") if(PYTHON_LIBRARIES) set(PYTHON_VERSION "${_VERSION}") @@ -105,6 +106,10 @@ macro(check_for_python_lib) endif() endforeach() endif() + # fallback to non-versioned naming scheme + if (NOT $PYTHON_LIBRARIES) + _find_python("${PYTHON_ROOT}" "") + endif() endmacro() macro(check_for_python_binary) @@ -112,15 +117,22 @@ macro(check_for_python_binary) _find_python_bin("${PYTHON_ROOT}" "${PYTHON_VERSION}") else() foreach(_VERSION ${PYTHON_VERSIONS}) - if(${PYTHON_MIN_VERSION} VERSION_LESS ${_VERSION}) + if((${PYTHON_MIN_VERSION} VERSION_LESS ${_VERSION}) OR + (${PYTHON_MIN_VERSION} VERSION_EQUAL ${_VERSION})) _find_python_bin("${PYTHON_ROOT}" "${_VERSION}") - if(PYTHON_LIBRARIES) + if(PYTHON_BINARY) set(PYTHON_VERSION "${_VERSION}") + # disallow all versions except for the one we just found. This makes + # sure we don't mismatch the python binary and the libraries. + set(PYTHON_VERSIONS "${_VERSION}") break() endif() endif() endforeach() endif() + if (NOT PYTHON_BINARY) + _find_python("${PYTHON_ROOT}" "") + endif() endmacro() if(NOT PYTHON_ROOT) @@ -134,11 +146,13 @@ if(APPLE AND NOT PYTHON_IGNORE_FRAMEWORKS) check_for_python_framework() endif() +# first check for python binary. +check_for_python_binary() + if(NOT PYTHON_FRAMEWORK_FOUND) check_for_python_lib() endif() -check_for_python_binary() mark_as_advanced( PYTHON_LIBRARIES PYTHON_INCLUDE_PATH @@ -159,6 +173,8 @@ if(PYTHON_LIBRARIES) endif() if (PYTHON_BINARY) + set(PYTHON_VERSION "${PYTHON_VERSION}" + CACHE STRING "Python Version" FORCE) set(PYTHON_BINARY "${PYTHON_BINARY}" CACHE FILEPATH "Python Binary" FORCE) endif() diff --git a/cmake_support/PROMOD.cmake b/cmake_support/PROMOD.cmake new file mode 100644 index 0000000000000000000000000000000000000000..da085010389640d841f4433055819f9ead1d7dcd --- /dev/null +++ b/cmake_support/PROMOD.cmake @@ -0,0 +1,868 @@ +#------------------------------------------------------------------------------- +# Authors: Marco Biasini, Juergen Haas, Andreas Schenk +# +# This file contains a bunch of useful macros to facilitate the build-system +# configuration for the modules. +#------------------------------------------------------------------------------- + +#------------------------------------------------------------------------------- +# map macro +# +# this function emulates a map/dict data type +#------------------------------------------------------------------------------- + +function(map COMMAND MAPNAME) + set (_KEYS ${MAPNAME}_MAP_KEYS ) + set (_VALUES ${MAPNAME}_MAP_VALUES) + if(${COMMAND} STREQUAL SET) + list(REMOVE_AT ARGN 0) + list(FIND ${_KEYS} ${ARGV2} _MAP_INDEX) + if(_MAP_INDEX EQUAL -1) + list(APPEND ${_KEYS} ${ARGV2}) + set(${_KEYS} ${${_KEYS}} PARENT_SCOPE) + set(${_VALUES}_${ARGV2} ${ARGN} PARENT_SCOPE) + else() + set(${_VALUES}_${ARGV2} ${ARGN} PARENT_SCOPE) + endif() + elseif(${COMMAND} STREQUAL GET) + list(FIND ${_KEYS} ${ARGV2} _MAP_INDEX) + if(_MAP_INDEX EQUAL -1) + MESSAGE(FATAL_ERROR "Unknown key: " ${ARGV2}) + endif() + set(${ARGV3} ${${_VALUES}_${ARGV2}} PARENT_SCOPE) + elseif(${COMMAND} STREQUAL KEYS) + set(${ARGV2} ${${_KEYS}} PARENT_SCOPE) + elseif(${COMMAND} STREQUAL CREATE) + set(${_KEYS} "" PARENT_SCOPE) + elseif(${COMMAND} STREQUAL LENGTH) + list(LENGTH ${_KEYS} _L) + set(${ARGV2} ${_L} PARENT_SCOPE) + else() + MESSAGE(FATAL_ERROR "Unknown map command:" ${COMMAND}) + endif() +endfunction() + + +#------------------------------------------------------------------------------- +# check_architecture +# +# detect architecture based on void pointer size. the output is stored in the +# 3 variables OS_32_BITS, OS_64_BITS and CMAKE_NATIVE_ARCH. The former two are +# set to 0 and 1 accordingly and CMAKE_NATIVE_ARCH is set to the 32 or 64 bit. +#------------------------------------------------------------------------------- +macro(check_architecture) + include(CheckTypeSize) + check_type_size(void* SIZEOF_VOID_PTR) + if(${SIZEOF_VOID_PTR} MATCHES "^8$") + set(OS_32_BITS 0) + set(OS_64_BITS 1) + set(CMAKE_NATIVE_ARCH 64) + else() + set(OS_32_BITS 1) + set(OS_64_BITS 0) + set(CMAKE_NATIVE_ARCH 32) + endif() +endmacro() + +#------------------------------------------------------------------------------- +# this macro has been adapted from +# http://www.cmake.org/Wiki/CMakeMacroParseArguments +#------------------------------------------------------------------------------- +macro(parse_argument_list PREFIX ARG_NAMES OPT_NAMES) + set(_DEFAULT_ARGS) + # reset variables + foreach(${_ARG_NAME} ${ARG_NAMES}) + set(PREFIX_${_ARG_NAME}) + endforeach() + foreach(_OPT_NAME ${OPT_NAMES}) + set(PREFIX_${_OPT_NAME} FALSE) + endforeach() + set(_CURR_ARG_NAME DEF_ARGS) + set(_CURR_ARG_LIST) + # loop over parameter list and split by ARG_NAMES + foreach(_ARG ${ARGN}) + set(_LARG_NAMES ${ARG_NAMES}) + list(FIND _LARG_NAMES ${_ARG} _IS_ARG_NAME) + if (_IS_ARG_NAME GREATER -1) + set(${PREFIX}_${_CURR_ARG_NAME} ${_CURR_ARG_LIST}) + set(_CURR_ARG_NAME "${_ARG}") + set(_CURR_ARG_LIST) + else() + set(_LOPT_NAMES ${OPT_NAMES}) + list(FIND _LOPT_NAMES ${_ARG} _IS_OPT_NAME) + if (_IS_OPT_NAME GREATER -1) + set(${PREFIX}_${_ARG} TRUE) + else() + list(APPEND _CURR_ARG_LIST "${_ARG}") + endif() + endif() + endforeach() + set(${PREFIX}_${_CURR_ARG_NAME} ${_CURR_ARG_LIST}) +endmacro() + +#------------------------------------------------------------------------------- +# copy_if_different +# +# copies file from source directory to destination directory, but only if its +# content changed. +#------------------------------------------------------------------------------- +macro(copy_if_different FROM_DIR TO_DIR FILES TARGETS TARGET) + foreach(SRC ${FILES}) + set(SRCFILE ${SRC}) + if("${FROM_DIR}" STREQUAL "" OR "${FROM_DIR}" STREQUAL "./") + set(FROM ${SRC}) + else() + set(FROM ${FROM_DIR}/${SRC}) + endif() + if("${TO_DIR}" STREQUAL "") + set(TO ${SRCFILE}) + else() + get_filename_component(TOFILE ${SRC} NAME) + set(TO ${TO_DIR}/${TOFILE}) + endif() + file(MAKE_DIRECTORY ${TO_DIR}) + add_custom_command(TARGET "${TARGET}" PRE_BUILD + DEPENDS ${FROM} + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FROM} ${TO}) + endforeach() +endmacro() + + +#------------------------------------------------------------------------------- +# parse_file_list +# +# this macro splits a list of files with IN_DIR statements and fills them into a map +# where the key is the directory name +#------------------------------------------------------------------------------- +macro(parse_file_list FILELIST FILEMAP) + set(_EXPECT_IN_DIR FALSE) + map(CREATE ${FILEMAP}) + set(_CURRENT_LIST) + foreach(_ITEM ${FILELIST}) + if (_ITEM STREQUAL "IN_DIR") + set(_EXPECT_IN_DIR TRUE) + else() + if (_EXPECT_IN_DIR) + set(_EXPECT_IN_DIR FALSE) + map(SET ${FILEMAP} ${_ITEM} ${_CURRENT_LIST}) + set(_CURRENT_LIST) + else() + list(APPEND _CURRENT_LIST "${_ITEM}") + endif() + endif() + endforeach() + if(_CURRENT_LIST) + map(SET ${FILEMAP} "." ${_CURRENT_LIST}) + endif() +endmacro() + + +#------------------------------------------------------------------------------- +# Synopsis: +# module(NAME name SOURCES source1 source2 HEADERS header1 header2 +# [IN_DIR dir] [header3 header4 [IN_DIR dir]] [DEPENDS_ON dep1 dep2] +# [HEADER_OUTPUT_DIR dir] +# [LINK link_cmds]) +# Description: +# Define an OpenStructure module. +#------------------------------------------------------------------------------- +macro(module) + #----------------------------------------------------------------------------- + # deal with arguments + #----------------------------------------------------------------------------- + set(_ARGS "NAME;SOURCES;HEADERS;DEPENDS_ON;LINK;HEADER_OUTPUT_DIR;PREFIX") + set(_ARG_PREFIX promod) + parse_argument_list(_ARG "${_ARGS}" "NO_STATIC" ${ARGN}) + if (NOT _ARG_NAME) + message(FATAL_ERROR + "invalid use of module(): a module name must be provided") + endif() + + if (ENABLE_STATIC AND _ARG_NO_STATIC) + return() + endif() + if (_ARG_HEADER_OUTPUT_DIR) + set(_HEADER_OUTPUT_DIR ${_ARG_HEADER_OUTPUT_DIR}) + else() + set(_HEADER_OUTPUT_DIR "${_ARG_PREFIX}/${_ARG_NAME}") + endif() + set(_LIB_NAME ${_ARG_PREFIX}_${_ARG_NAME}) + string(TOUPPER ${_LIB_NAME} _UPPER_LIB_NAME) + #----------------------------------------------------------------------------- + # create library + #----------------------------------------------------------------------------- + file(MAKE_DIRECTORY ${LIB_STAGE_PATH}) + file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + file(MAKE_DIRECTORY ${LIBEXEC_STAGE_PATH}) + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/tests") + if (NOT TARGET create_stage) + add_custom_target(create_stage COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_STAGE_PATH} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + COMMAND ${CMAKE_COMMAND} -E make_directory ${LIBEXEC_STAGE_PATH} + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/tests") + endif() + if (_ARG_SOURCES) + # when there is at least one source file, we build a library + set(_ABS_SOURCE_NAMES) + foreach(_SOURCE ${_ARG_SOURCES}) + if (IS_ABSOLUTE ${_SOURCE}) + list(APPEND _ABS_SOURCE_NAMES "${_SOURCE}") + else() + list(APPEND _ABS_SOURCE_NAMES "${CMAKE_CURRENT_SOURCE_DIR}/${_SOURCE}") + endif() + endforeach() + if (ENABLE_STATIC AND NOT _ARG_NO_STATIC) + add_library(${_LIB_NAME} STATIC ${_ABS_SOURCE_NAMES}) + else() + add_library(${_LIB_NAME} SHARED ${_ABS_SOURCE_NAMES}) + endif() + set_target_properties(${_LIB_NAME} + PROPERTIES OUTPUT_NAME ${_LIB_NAME} + PROJECT_LABEL ${_ARG_NAME} + EchoString ${_ARG_NAME} + MODULE_DEPS "${_ARG_DEPENDS_ON}") + get_target_property(_DEFS ${_LIB_NAME} COMPILE_DEFINITIONS) + add_dependencies(${_LIB_NAME} create_stage) + set_target_properties(${_LIB_NAME} PROPERTIES + COMPILE_DEFINITIONS PROMOD_MODULE_${_UPPER_LIB_NAME}) + set_target_properties(${_LIB_NAME} PROPERTIES + VERSION ${PROMOD_VERSION_STRING} + SOVERSION ${PROMOD_VERSION_MAJOR}.${PROMOD_VERSION_MINOR}) + set_target_properties(${_LIB_NAME} PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${LIB_STAGE_PATH} + ARCHIVE_OUTPUT_DIRECTORY ${LIB_STAGE_PATH} + RUNTIME_OUTPUT_DIRECTORY ${LIB_STAGE_PATH}) + if (APPLE) + set_target_properties(${_LIB_NAME} PROPERTIES + LINK_FLAGS "-Wl,-rpath,@loader_path" + INSTALL_NAME_DIR "@rpath") + endif() + if (ENABLE_STATIC) + install(TARGETS ${_LIB_NAME} ARCHIVE DESTINATION "${LIB_DIR}") + else() + install(TARGETS ${_LIB_NAME} LIBRARY DESTINATION "${LIB_DIR}") + endif() + if (_ARG_LINK) + target_link_libraries(${_LIB_NAME} ${_ARG_LINK}) + endif() + foreach(_DEPENDENCY ${_ARG_DEPENDS_ON}) + target_link_libraries(${_LIB_NAME} ${_DEPENDENCY}) + endforeach() + if (ENABLE_STATIC) + target_link_libraries(${_LIB_NAME} ${STATIC_LIBRARIES}) + endif() + else() + add_custom_target("${_LIB_NAME}" ALL) + set_target_properties("${_LIB_NAME}" PROPERTIES HEADER_ONLY 1 + MODULE_DEPS "${_ARG_DEPENDS_ON}") + endif() + #----------------------------------------------------------------------------- + # stage headers + #----------------------------------------------------------------------------- + if (_ARG_HEADERS) + stage_and_install_headers("${_ARG_HEADERS}" "${_HEADER_OUTPUT_DIR}" "${_LIB_NAME}") + endif() +endmacro() + +#------------------------------------------------------------------------------- +# macro stage_and_install_headers +#------------------------------------------------------------------------------- +macro(stage_and_install_headers HEADERLIST HEADER_OUTPUT_DIR TARGET) + add_custom_target("${TARGET}_headers" COMMENT "") + add_dependencies("${TARGET}" "${TARGET}_headers") + add_dependencies("${TARGET}_headers" create_stage) + parse_file_list("${HEADERLIST}" _HEADER_MAP) + map(KEYS _HEADER_MAP _HEADER_MAP_KEYS) + foreach(_DIR ${_HEADER_MAP_KEYS}) + map(GET _HEADER_MAP ${_DIR} _HEADERS) + set(_HDR_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_DIR}") + set(_ABS_HEADER_NAMES) + foreach(_HDR ${_HEADERS}) + list(APPEND _ABS_HEADER_NAMES ${_HDR_SOURCE_DIR}/${_HDR}) + endforeach() + set(_HDR_STAGE_DIR "${HEADER_OUTPUT_DIR}/${_DIR}") + set(_FULL_HEADER_DIR "${HEADER_STAGE_PATH}/${_HDR_STAGE_DIR}") + copy_if_different("" "${_FULL_HEADER_DIR}" "${_ABS_HEADER_NAMES}" "" "${TARGET}_headers") + install(FILES ${_ABS_HEADER_NAMES} DESTINATION "include/${_HDR_STAGE_DIR}") + endforeach() +endmacro() + + +#------------------------------------------------------------------------------- +# Synopsis +# executable(NAME exe_name SOURCES source1 source2 LINK link1 link2) +# +# Description: +# Compile, link and stage a C++ executable +#------------------------------------------------------------------------------- +macro(executable) + parse_argument_list(_ARG + "NAME;SOURCES;LINK;DEPENDS_ON" "NO_RPATH;STATIC" ${ARGN}) + if (NOT _ARG_NAME) + message(FATAL_ERROR "invalid use of executable(): a name must be provided") + endif() + add_executable(${_ARG_NAME} ${_ARG_SOURCES}) + if (APPLE AND NOT _ARG_NO_RPATH AND NOT ENABLE_STATIC) + set_target_properties(${_ARG_NAME} PROPERTIES + LINK_FLAGS "-Wl,-rpath,@loader_path/../lib/") + endif() + if (_ARG_LINK) + target_link_libraries(${_ARG_NAME} ${_ARG_LINK}) + endif() + foreach(_DEP ${_ARG_DEPENDS_ON}) + target_link_libraries(${_ARG_NAME} ${_DEP}) + endforeach() + if (ENABLE_STATIC AND _ARG_STATIC) + target_link_libraries(${_ARG_NAME} ${STATIC_LIBRARIES}) + if (UNIX AND NOT APPLE) + if (PROMOD_GCC_45) + set_target_properties(${_ARG_NAME} + PROPERTIES LINK_SEARCH_END_STATIC TRUE + LINK_FLAGS "-static-libgcc -static-libstdc++ -static -pthread") + else() + set_target_properties(${_ARG_NAME} + PROPERTIES LINK_SEARCH_END_STATIC TRUE + LINK_FLAGS "-static-libgcc -static -pthread") + endif() + endif() + endif() + install(TARGETS ${_ARG_NAME} DESTINATION bin) +endmacro() + + +#------------------------------------------------------------------------------- +# Synopsis +# executable_libexec(NAME exe_name SOURCES source1 source2 LINK link1 link2) +# +# Description: +# Compile, link and stage a C++ executable into the libexec directory +#------------------------------------------------------------------------------- +macro(executable_libexec) + parse_argument_list(_ARG + "NAME;SOURCES;LINK;DEPENDS_ON" "NO_RPATH;STATIC" ${ARGN}) + if (NOT _ARG_NAME) + message(FATAL_ERROR "invalid use of executable(): a name must be provided") + endif() + add_executable(${_ARG_NAME} ${_ARG_SOURCES}) + set_target_properties(${_ARG_NAME} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${LIBEXEC_STAGE_PATH}") + set_target_properties(${_ARG_NAME} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE + "${LIBEXEC_STAGE_PATH}") + set_target_properties(${_ARG_NAME} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG + "${LIBEXEC_STAGE_PATH}") + if (NOT _ARG_NO_RPATH AND NOT _ARG_STATIC) + if (APPLE) + set_target_properties(${_ARG_NAME} PROPERTIES + LINK_FLAGS "-Wl,-rpath,@loader_path/../../lib") + elseif (UNIX) + set_target_properties(${_ARG_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN/../../${LIB_DIR}") + endif (APPLE) + endif (NOT _ARG_NO_RPATH AND NOT _ARG_STATIC) + if (_ARG_LINK) + target_link_libraries(${_ARG_NAME} ${_ARG_LINK}) + endif() + if (ENABLE_STATIC AND _ARG_STATIC) + target_link_libraries(${_ARG_NAME} ${STATIC_LIBRARIES}) + set_target_properties(${_ARG_NAME} + PROPERTIES LINK_SEARCH_END_STATIC TRUE) + + endif() + foreach(_DEP ${_ARG_DEPENDS_ON}) + target_link_libraries(${_ARG_NAME} ${_DEP}) + endforeach() + install(TARGETS ${_ARG_NAME} DESTINATION ${LIBEXEC_PATH}) +endmacro() + +#------------------------------------------------------------------------------- +# Synopsis: +# substitute(IN_FILE in_file OUT_FILE out_file DICT a=b c=d) +# +#------------------------------------------------------------------------------- +macro(substitute) + parse_argument_list(_ARG + "IN_FILE;OUT_FILE;DICT" "" ${ARGN}) + if (NOT _ARG_IN_FILE) + message(FATAL_ERROR "invalid use of substitute(): no IN_FILE given") + endif() + if (NOT _ARG_OUT_FILE) + message(FATAL_ERROR "invalid use of substitute(): no OUT_FILE given") + endif() + set(_SUBST_DICT -DINPUT_FILE=${_ARG_IN_FILE} -DOUT_FILE=${_ARG_OUT_FILE}) + foreach(_SUBST ${_ARG_DICT}) + list(APPEND _SUBST_DICT -D${_SUBST}) + endforeach() + add_custom_target(subst_${_ARG_OUT_FILE} ALL COMMAND + ${CMAKE_COMMAND} ${_SUBST_DICT} + -P ${CMAKE_SOURCE_DIR}/cmake_support/substitute.cmake) +endmacro() + +#------------------------------------------------------------------------------- +# Synopsis: +# script(NAME script_name INPUT input_name SUBSTITUTE key=val key=val +# [OUTPUT_DIR dir] [TARGET target]) +#------------------------------------------------------------------------------- +macro(script) + set(_ARG_OUTPUT_DIR bin) + parse_argument_list(_ARG + "NAME;INPUT;SUBSTITUTE;TARGET;OUTPUT_DIR" "" ${ARGN}) + if (NOT _ARG_NAME) + message(FATAL_ERROR "invalid use of executable(): a name must be provided") + endif() + set(_INPUT ${_ARG_NAME}) + if (_ARG_INPUT) + set(_INPUT ${_ARG_INPUT}) + endif() + if (_ARG_SUBSTITUTE) + if (NOT _ARG_INPUT) + message(FATAL_ERROR "script() can only substitute when INPUT is present.") + endif() + + substitute(IN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${_INPUT}" OUT_FILE ${_ARG_NAME} + DICT ${_ARG_SUBSTITUTE}) + endif() + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${_ARG_NAME} DESTINATION ${_ARG_OUTPUT_DIR} + PERMISSIONS WORLD_EXECUTE GROUP_EXECUTE OWNER_EXECUTE + WORLD_READ GROUP_READ OWNER_READ) + copy_if_different("./" "${STAGE_DIR}/${_ARG_OUTPUT_DIR}" + "${_ARG_NAME}" "TARGETS" ${_ARG_TARGET}) + add_dependencies(${_ARG_TARGET} subst_${_ARG_NAME}) +endmacro() + +#------------------------------------------------------------------------------- +# Synopsis: +# ui_to_python(libname stagedir[input_file1 ...]) +# Description: +# Calls pyuic on every input file. The resulting python files are stored in +# the variable with name out_files. +#------------------------------------------------------------------------------- +macro(ui_to_python LIBNAME PYMODDIR STAGEDIR) + set(_input_files ${ARGN}) + add_custom_target("${LIBNAME}_ui" ALL) + add_dependencies("_${LIBNAME}" "${LIBNAME}_ui") + find_program(_PYUIC_EXECUTABLE + NAMES pyuic4-${PYTHON_VERSION} pyuic4 pyuic pyuic4.bat + PATHS ENV PATH + ) + if(NOT _PYUIC_EXECUTABLE) + message(FATAL_ERROR "Could not find pyuic command in " ${QT_BINARY_DIR} " for python version " ${PYTHON_VERSION}) + endif(NOT _PYUIC_EXECUTABLE) + set(out_files) + foreach(input_file ${_input_files}) + get_filename_component(_out_file ${input_file} NAME_WE) + get_filename_component(_in_file ${input_file} ABSOLUTE) + set(_out_file ${_out_file}_ui.py) + set(_abs_out_file ${STAGEDIR}/${_out_file}) + add_custom_command(TARGET ${LIBNAME}_ui + COMMAND ${_PYUIC_EXECUTABLE} -o ${_abs_out_file} ${_in_file} + VERBATIM DEPENDS ${input_file} + ) + list(APPEND out_files ${_abs_out_file}) + endforeach() + compile_py_files(_${LIBNAME} ${STAGEDIR} compiled_files ${out_files}) + install(FILES ${out_files} DESTINATION "${LIB_DIR}/${PYMODDIR}") + install(FILES ${compiled_files} DESTINATION "${LIB_DIR}/${PYMODDIR}") +endmacro() + +#------------------------------------------------------------------------------- +# Synopsis: +# compile_py_files(module out_dir compiled_files [input_file1 ...]) +# Description: +# Calls pyuic on every input file. The resulting python files are stored in +# the variable with name compiled_files. +#------------------------------------------------------------------------------- +macro(compile_py_files module out_dir compiled_files_name) + set(_input_files ${ARGN}) + set(${compiled_files_name}) + foreach(input_file ${_input_files}) + get_filename_component(_out_file ${input_file} NAME_WE) + get_filename_component(_in_file ${input_file} ABSOLUTE) + set(_out_file ${out_dir}/${_out_file}.pyc) + list(APPEND ${compiled_files_name} ${_out_file}) + get_filename_component(_in_name ${input_file} NAME) + file(MAKE_DIRECTORY ${out_dir}) + add_custom_command(TARGET ${module} + COMMAND ${PYTHON_BINARY} -c "import py_compile;py_compile.compile(\"${_in_file}\",\"${_out_file}\",\"${_in_name}\",doraise=True)" + VERBATIM DEPENDS ${input_file} + ) + endforeach() +endmacro() + +#------------------------------------------------------------------------------- +# Synopsis: +# pymod(NAME name CPP source1 source2 PY source source2 [IN_DIR dir] +# source3 source4 [IN_DIR dir] [LINK link] [OUTPUT_DIR dir] [UI user_interface_files]) +# +# Description: +# Define a python module consisting of C++ type wrappers and/or code written in +# Python. +# NAME is the name of +#------------------------------------------------------------------------------- +macro(pymod) + #----------------------------------------------------------------------------- + # deal with arguments + #----------------------------------------------------------------------------- + set(_ARG_PREFIX promod) + parse_argument_list(_ARG + "NAME;CPP;PY;LINK;OUTPUT_DIR;UI;PREFIX" "" ${ARGN}) + if (NOT _ARG_NAME) + message(FATAL_ERROR "invalid use of pymod(): a name must be provided") + endif() + if (ENABLE_STATIC) + return() + endif() + if (_ARG_OUTPUT_DIR) + set(PYMOD_DIR "python${PYTHON_VERSION}/site-packages/${_ARG_OUTPUT_DIR}") + else() + set(PYMOD_DIR "python${PYTHON_VERSION}/site-packages/${_ARG_PREFIX}/${_ARG_NAME}") + endif() + set(_LIB_NAME ${_ARG_PREFIX}_${_ARG_NAME}) + set(PYMOD_STAGE_DIR "${LIB_STAGE_PATH}/${PYMOD_DIR}") + file(MAKE_DIRECTORY ${PYMOD_STAGE_DIR}) + include_directories(${PYTHON_INCLUDE_PATH}) + #----------------------------------------------------------------------------- + # compile and link C++ wrappers + #----------------------------------------------------------------------------- + if (_ARG_CPP) + add_library("_${_LIB_NAME}" MODULE ${_ARG_CPP}) + set_target_properties("_${_LIB_NAME}" + PROPERTIES ECHO_STRING + "Building Python Module ${_ARG_NAME}") + if (_ARG_PREFIX) + set(_PARENT_NAME "${_ARG_PREFIX}_${_ARG_NAME}") + else() + set(_PARENT_NAME "${_ARG_NAME}") + endif() + get_target_property(_CUSTOM_CHECK "${_PARENT_NAME}" HEADER_ONLY) + if (NOT _CUSTOM_CHECK) + set(_PARENT_LIB_NAME "${_PARENT_NAME}") + endif() + target_link_libraries("_${_LIB_NAME}" ${_PARENT_LIB_NAME} + ${PYTHON_LIBRARIES} ${BOOST_PYTHON_LIBRARIES}) + + set_target_properties("_${_LIB_NAME}" + PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PYMOD_STAGE_DIR}) + set_target_properties("_${_LIB_NAME}" + PROPERTIES LIBRARY_OUTPUT_DIRECTORY_RELEASE ${PYMOD_STAGE_DIR}) + set_target_properties("_${_LIB_NAME}" + PROPERTIES LIBRARY_OUTPUT_DIRECTORY_DEBUG ${PYMOD_STAGE_DIR}) + + if (NOT ENABLE_STATIC) + if (_USE_RPATH) + string(REGEX REPLACE "/[^/]*" "/.." inv_pymod_path "/${PYMOD_DIR}") + set_target_properties("_${_LIB_NAME}" + PROPERTIES INSTALL_RPATH "$ORIGIN${inv_pymod_path}/") + else() + set_target_properties("_${_LIB_NAME}" + PROPERTIES INSTALL_RPATH "") + endif() + endif() + if (APPLE) + file(RELATIVE_PATH _REL_PATH "${PYMOD_STAGE_DIR}" "${LIB_STAGE_PATH}") + set_target_properties("_${_LIB_NAME}" PROPERTIES + LINK_FLAGS "-Wl,-rpath,@loader_path/${_REL_PATH}" + INSTALL_NAME_DIR "@rpath") + endif() + set_target_properties("_${_LIB_NAME}" + PROPERTIES PREFIX "") + install(TARGETS "_${_LIB_NAME}" LIBRARY DESTINATION + "${LIB_DIR}/${PYMOD_DIR}") + else() + add_custom_target("_${_LIB_NAME}" ALL) + endif() + #----------------------------------------------------------------------------- + # build ui files + #----------------------------------------------------------------------------- + if (_ARG_UI) + ui_to_python(${_LIB_NAME} ${PYMOD_DIR} ${PYMOD_STAGE_DIR} ${_ARG_UI}) + endif() + #----------------------------------------------------------------------------- + # compile python files + #----------------------------------------------------------------------------- + if (_ARG_PY) + parse_file_list("${_ARG_PY}" _PYFILE_MAP) + map(KEYS _PYFILE_MAP _PYFILE_MAP_KEYS) + foreach(_DIR ${_PYFILE_MAP_KEYS}) + map(GET _PYFILE_MAP ${_DIR} _PY_FILES) + set(_ABS_PY_FILES) + set(_PY_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_DIR}") + foreach(_PY ${_PY_FILES}) + list(APPEND _ABS_PY_FILES "${_PY_SOURCE_DIR}/${_PY}") + endforeach() + install(FILES ${_ABS_PY_FILES} DESTINATION "${LIB_DIR}/${PYMOD_DIR}/${_DIR}") + string(REPLACE "/" "_" _DIR_NO_SLASH "${_DIR}") + set(_PYMOD_TARGET "${_LIB_NAME}_${_DIR_NO_SLASH}_pymod") + string(REPLACE "_." "" _PYMOD_TARGET "${_PYMOD_TARGET}") + add_custom_target(${_PYMOD_TARGET} ALL) + copy_if_different("./" "${PYMOD_STAGE_DIR}/${_DIR}" + "${_ABS_PY_FILES}" "TARGETS" + "${_PYMOD_TARGET}") + compile_py_files(_${_LIB_NAME} ${PYMOD_STAGE_DIR}/${_DIR} compiled_files ${_ABS_PY_FILES}) + install(FILES ${compiled_files} DESTINATION "${LIB_DIR}/${PYMOD_DIR}/${_DIR}") + endforeach() + endif() + get_target_property(_MOD_DEPS "${_PARENT_NAME}" MODULE_DEPS) + if(_MOD_DEPS) + foreach(dep ${_MOD_DEPS}) + add_dependencies("_${_LIB_NAME}" "_${dep}") + endforeach() + endif() +endmacro() + +add_custom_target(check) +add_custom_target(check_xml) + +#------------------------------------------------------------------------------- +# promod_unittest +# +# define a unit test +#------------------------------------------------------------------------------- +macro(promod_unittest) + set(_ARG_PREFIX promod) + parse_argument_list(_ARG + "MODULE;PREFIX;SOURCES;LINK" "" ${ARGN}) + set(_SOURCES ${_ARG_SOURCES}) + set(CPP_TESTS) + set(PY_TESTS) + set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_BINARY_DIR}/tests") + foreach(src ${_SOURCES}) + if (${src} MATCHES "\\.py$") + list(APPEND PY_TESTS "${src}") + else() + list(APPEND CPP_TESTS "${CMAKE_CURRENT_SOURCE_DIR}/${src}") + endif() + endforeach() + set(_SOURCES ${CPP_TESTS}) + set(_test_name "${_ARG_PREFIX}_${_ARG_MODULE}_tests") + if(DEFINED CPP_TESTS) + if(COMPILE_TESTS) + add_executable(${_test_name} ${_SOURCES}) + else() + add_executable(${_test_name} EXCLUDE_FROM_ALL ${_SOURCES}) + endif() + set_target_properties(${_test_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests" ) + set_target_properties(${_test_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/tests" ) + set_target_properties(${_test_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/tests" ) + + target_link_libraries(${_test_name} ${BOOST_UNIT_TEST_LIBRARIES} + "${_ARG_PREFIX}_${_ARG_MODULE}") + add_custom_target("${_test_name}_run" + COMMAND PROMOD_ROOT=${STAGE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${_test_name} || echo + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "running checks for module ${_ARG_MODULE}" + DEPENDS ${_test_name}) + add_custom_target("${_test_name}_run_xml" + COMMAND PROMOD_ROOT=${STAGE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${_test_name} --log_format=xml --log_level=all > ${_test_name}_log.xml || echo + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "running checks for module ${_ARG_MODULE}" + DEPENDS ${_test_name}) + add_test("${_test_name}" ${CMAKE_CURRENT_BINARY_DIR}/${_test_name} ) + add_dependencies(check_xml "${_test_name}_run_xml") + add_dependencies(check "${_test_name}_run") + + if (_ARG_LINK) + target_link_libraries("${_test_name}" ${_ARG_LINK}) + endif() + + set_target_properties(${_test_name} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_CURRENT_BINARY_DIR}") + endif() + + foreach(py_test ${PY_TESTS}) + set(python_path $ENV{PYTHONPATH}) + if(python_path) + set(python_path "${python_path}:") + endif(python_path) + set(python_path "${python_path}${LIB_STAGE_PATH}/python${PYTHON_VERSION}/site-packages") + set (PY_TESTS_CMD "PYTHONPATH=${python_path} ${PYTHON_BINARY}") + add_custom_target("${py_test}_run" + sh -c "${PY_TESTS_CMD} ${CMAKE_CURRENT_SOURCE_DIR}/${py_test} || echo" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "running checks ${py_test}" VERBATIM) + add_custom_target("${py_test}_run_xml" + sh -c "${PY_TESTS_CMD} ${CMAKE_CURRENT_SOURCE_DIR}/${py_test} xml || echo" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "running checks ${py_test}" VERBATIM) + add_dependencies("${py_test}_run_xml" promod_scripts "_${_ARG_PREFIX}_${_ARG_MODULE}") + add_dependencies("${py_test}_run" promod_scripts "_${_ARG_PREFIX}_${_ARG_MODULE}") + add_dependencies(check "${py_test}_run") + add_dependencies(check_xml "${py_test}_run_xml") + + endforeach() + + # get_target_property(OUTT ${_test_name} GENERATOR_FILE_NAME) + # message("${OUTT}") + + # get_target_property(OUTT check GENERATOR_FILE_NAME) + # message("${OUTT}") +endmacro() + +#------------------------------------------------------------------------------- +# make sure the previously detected Python interpreter has the given module +#------------------------------------------------------------------------------- +macro(promod_find_python_module MODULE) + if (NOT PYTHON_MODULE_${MODULE}) + message(STATUS "Searching for python module ${MODULE} for ${PYTHON_BINARY}") + execute_process(COMMAND ${PYTHON_BINARY} -c "import ${MODULE}" + OUTPUT_QUIET ERROR_QUIET + RESULT_VARIABLE _IMPORT_ERROR) + if (_IMPORT_ERROR) + message(FATAL_ERROR "Could not find python module ${MODULE}. Please install it") + else() + message(STATUS "Found python module ${MODULE}") + set("PYTHON_MODULE_${MODULE}" FOUND CACHE STRING "" FORCE) + endif() + endif() +endmacro() + + +#------------------------------------------------------------------------------- +# this macro tries to detect a very common problem during configuration stage: +# it makes sure that boost python is linked against the same version of python +# that we are linking against. +#------------------------------------------------------------------------------- +macro(promod_match_boost_python_version) + include(CheckCXXSourceRuns) + # this variable may either be a simple library path or list that contains + # different libraries for different build-options. For example: + # optimized;<lib1>;debug;<lib2> + set(_BOOST_PYTHON_LIBRARY ${Boost_PYTHON_LIBRARY}) + list(LENGTH _BOOST_PYTHON_LIBRARY _BP_LENGTH) + if (_BP_LENGTH GREATER 1) + list(FIND _BOOST_PYTHON_LIBRARY optimized _OPTIMIZED_INDEX) + if (_OPTIMIZED_INDEX EQUAL -1) + message(FATAL_ERROR + "Error while trying to get path of boost python library") + endif() + math(EXPR _LIB_INDEX 1+${_OPTIMIZED_INDEX}) + list(GET _BOOST_PYTHON_LIBRARY ${_LIB_INDEX} _BP_LIB_PATH) + set(_BOOST_PYTHON_LIBRARY ${_BP_LIB_PATH}) + endif() + set(CMAKE_REQUIRED_FLAGS "-I${PYTHON_INCLUDE_PATH} -I${Boost_INCLUDE_DIR} ${PYTHON_LIBRARIES} ${_BOOST_PYTHON_LIBRARY}") + check_cxx_source_runs( +"#include <boost/python.hpp> + +using namespace boost::python; + +int main( int argc, char ** argv ) { + try { + Py_Initialize(); + + object main_module(( + handle<>(borrowed(PyImport_AddModule(\"__main__\"))))); + + object main_namespace = main_module.attr(\"__dict__\"); + + handle<> ignored(( PyRun_String( \"print 'Hello, World'\", + Py_file_input, + main_namespace.ptr(), + main_namespace.ptr() ) )); + } catch( error_already_set ) { + PyErr_Print(); + return 1; + } + return 0; +}" PYTHON_VERSION_FOUND_MATCHES_PYTHON_VERSION_BOOST_WAS_COMPILED_WITH) + + if(NOT PYTHON_VERSION_FOUND_MATCHES_PYTHON_VERSION_BOOST_WAS_COMPILED_WITH) + message(FATAL_ERROR "Python versions mismatch!\n" + "Make sure the python version for boost match the one you " + "specified during configuration\n") + endif() +endmacro() + + +#------------------------------------------------------------------------------- +# this macro sets up the stage directories +#------------------------------------------------------------------------------- +macro(setup_stage) + set(STAGE_DIR "${CMAKE_BINARY_DIR}/stage") + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${STAGE_DIR}/bin ) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${STAGE_DIR}/bin ) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${STAGE_DIR}/bin ) + set(HEADER_STAGE_PATH ${STAGE_DIR}/include ) + set(SHARED_DATA_PATH ${STAGE_DIR}/share/promod3 ) + + if (UNIX AND NOT APPLE) + check_architecture() + endif() + set (ARCH ${CMAKE_NATIVE_ARCH}) + if ("${ARCH}" MATCHES "64" AND NOT _UBUNTU_LAYOUT) + set(LIB_DIR lib64 ) + set(LIB_STAGE_PATH "${STAGE_DIR}/lib64" ) + else() + set(LIB_DIR lib ) + set(LIB_STAGE_PATH "${STAGE_DIR}/lib" ) + endif() + if (_UBUNTU_LAYOUT) + set(LIBEXEC_PATH ${LIB_DIR}/promod3/libexec ) + set(LIBEXEC_STAGE_PATH ${LIB_STAGE_PATH}/promod3/libexec ) + else() + set(LIBEXEC_PATH libexec/promod3 ) + set(LIBEXEC_STAGE_PATH ${STAGE_DIR}/libexec/promod3 ) + endif() + + include_directories("${HEADER_STAGE_PATH}") + link_directories(${LIB_STAGE_PATH}) + +endmacro() + +#------------------------------------------------------------------------------- +# get compiler version +#------------------------------------------------------------------------------- +function(get_compiler_version _OUTPUT_VERSION) + exec_program(${CMAKE_CXX_COMPILER} + ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion + OUTPUT_VARIABLE _COMPILER_VERSION + ) + string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2" + _COMPILER_VERSION ${_COMPILER_VERSION}) + + set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE) +endfunction() + + + +macro(setup_compiler_flags) + if (CMAKE_COMPILER_IS_GNUCXX) + get_compiler_version(_GCC_VERSION) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" ) + if (_GCC_VERSION MATCHES "44") + # gcc 4.4. is very strict about aliasing rules. the shared_count + # implementation that is used boost's shared_ptr violates these rules. To + # silence the warnings and prevent miscompiles, enable + # -fno-strict-aliasing + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing" ) + endif() + endif() +endmacro() +set(_BOOST_MIN_VERSION 1.31) + +macro(setup_boost) + find_package(Boost ${_BOOST_MIN_VERSION} COMPONENTS python REQUIRED) + set(BOOST_PYTHON_LIBRARIES ${Boost_LIBRARIES}) + set(Boost_LIBRARIES) + find_package(Boost ${_BOOST_MIN_VERSION} + COMPONENTS unit_test_framework REQUIRED) + set(BOOST_UNIT_TEST_LIBRARIES ${Boost_LIBRARIES}) + set(Boost_LIBRARIES) + if (ENABLE_STATIC) + set(Boost_USE_STATIC_LIBS ON) + endif() + find_package(Boost ${_BOOST_MIN_VERSION} + COMPONENTS filesystem system REQUIRED) + set(BOOST_LIBRARIES ${Boost_LIBRARIES}) + set(Boost_LIBRARIES) + find_package(Boost ${_BOOST_MIN_VERSION} COMPONENTS iostreams REQUIRED) + set(BOOST_IOSTREAM_LIBRARIES ${Boost_LIBRARIES}) + set(Boost_LIBRARIES) + find_package(Boost ${_BOOST_MIN_VERSION} COMPONENTS program_options REQUIRED) + set(BOOST_PROGRAM_OPTIONS ${Boost_LIBRARIES}) + set(Boost_LIBRARIES) + find_package(Boost ${_BOOST_MIN_VERSION} COMPONENTS regex REQUIRED) + set(BOOST_REGEX_LIBRARIES ${Boost_LIBRARIES}) + set(Boost_LIBRARIES) +endmacro()