From b698f4910bc8c037d54e68c7642afdafcb64b51c Mon Sep 17 00:00:00 2001
From: Stefan Bienert <stefan.bienert@unibas.ch>
Date: Fri, 13 Sep 2013 11:09:15 +0200
Subject: [PATCH] First setup of CMake, already has out-of-source build enabled

---
 .gitignore                     |   1 +
 CMakeLists.txt                 |  68 ++-
 cmake_support/FindPython.cmake |  38 +-
 cmake_support/PROMOD.cmake     | 868 +++++++++++++++++++++++++++++++++
 4 files changed, 961 insertions(+), 14 deletions(-)
 create mode 100644 cmake_support/PROMOD.cmake

diff --git a/.gitignore b/.gitignore
index 87a267d8..45022ce6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 junk.py
+stage/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e9f0c6b1..2b8da57f 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 4b4bce09..04861bc5 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 00000000..da085010
--- /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()
-- 
GitLab