plustab(GaudiProjectConfig)

# - GaudiProject
# Define the macros used by Gaudi-based projects, namely:
#  GAUDI_PROJECT(project version) : declare a project with it's version number
#  GAUDI_USE_PROJECT(project version) : declare the dependency on another project
#
# Authors: Pere Mato, Marco Clemencic

tabmessage("GaudiProjectConfig> ")

cmake_minimum_required(VERSION 2.4.6)
cmake_policy(SET CMP0003 NEW) # See "cmake --help-policy CMP0003" for more details
cmake_policy(SET CMP0011 NEW) # See "cmake --help-policy CMP0011" for more details
cmake_policy(SET CMP0009 NEW) # See "cmake --help-policy CMP0009" for more details

# Add the directory containing this file to the modules search path
#set(CMAKE_MODULE_PATH ${GaudiProject_DIR} ${CMAKE_MODULE_PATH})

if(WIN32)
  set(ld_library_path PATH)
elseif(APPLE)
  set(ld_library_path DYLD_LIBRARY_PATH)
else()
  set(ld_library_path LD_LIBRARY_PATH)
endif()

moinstab()

#---------------------------------------------------------------------------------------------------
#---GAUDI_PROJECT(project version)
#---------------------------------------------------------------------------------------------------
macro(GAUDI_PROJECT project_name version)
plustab(GAUDI_PROJECT)
  set(GaudiProject_DIR ${CMAKE_SOURCE_DIR})
  set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})

tabmessage("GAUDI_PROJECT> CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR} CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}")

  string(TOUPPER ${project_name} project)
  project(${project})

tabmessage("GAUDI_PROJECT> GaudiProject_DIR=${GaudiProject_DIR}")

  set(CMAKE_PROJECT_NAME ${project}) #----For some reason this is not set by calling 'project()'

  #--- Define the version of the project - can be used to generate sources,

tabmessage("GAUDI_PROJECT> Define the version of the project - version=${version}")

  set(${project}_VERSION ${version})
  if( ${version} MATCHES "[a-zA-Z]+([0-9]+)[a-zA-Z]+([0-9]+)[a-zA-Z]+([0-9]+)")
    string(REGEX REPLACE "[a-zA-Z]+([0-9]+)[a-zA-Z]+([0-9]+)[a-zA-Z]+([0-9]+)" "\\1"  major ${version})
    string(REGEX REPLACE "[a-zA-Z]+([0-9]+)[a-zA-Z]+([0-9]+)[a-zA-Z]+([0-9]+)" "\\2"  minor ${version})
    string(REGEX REPLACE "[a-zA-Z]+([0-9]+)[a-zA-Z]+([0-9]+)[a-zA-Z]+([0-9]+)" "\\3"  patch ${version})
  elseif(${version} MATCHES "[a-zA-Z]+([0-9]+)[a-zA-Z]+([0-9]+)")
    string(REGEX REPLACE "[a-zA-Z]+([0-9]+)[a-zA-Z]+([0-9]+)" "\\1"  major ${version})
    string(REGEX REPLACE "[a-zA-Z]+([0-9]+)[a-zA-Z]+([0-9]+)" "\\2"  minor ${version})
    set( patch 0)
  endif()
  set(${project}_VERSION_MAJOR ${major})
  set(${project}_VERSION_MINOR ${minor})
  set(${project}_VERSION_PATCH ${patch})

  #--- Project Options and Global settings----------------------------------------------------------

tabmessage("GAUDI_PROJECT> Project Options and Global settings")

  option(BUILD_SHARED_LIBS "Set to OFF to build static libraries" ON)
  option(BUILD_TESTS "Set to ON to build the tests (libraries and executables)" OFF)
  option(HIDE_WARNINGS "Turn on or off options that are used to hide warning messages" ON)
  #-------------------------------------------------------------------------------------------------


  #--- Build type and tag strings-------------------------------------------------------------------

tabmessage("GAUDI_PROJECT> Build type and tag strings")

  set(opt2buildtype Release)
  set(dbg2buildtype Debug)
  set(Debug2type dbg)
  set(Release2type opt)

  if(DEFINED ENV{CMAKECONFIG})
    set(tag $ENV{CMAKECONFIG})
  elseif(DEFINED ENV{CMTCONFIG})
    set(tag $ENV{CMTCONFIG})
  else()
    GAUDI_BINARY_TAG(tag)
  endif()
  string(REGEX MATCHALL "[^-]+" out "${tag}")

tabmessage("GAUDI_PROJECT> out=${out}")

  list(GET out 0 arch)
  list(GET out 1 os)
  list(GET out 2 comp)
  list(GET out 3 type)

  if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE ${${type}2buildtype} CACHE STRING
        "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
  endif()

  set(BINARY_TAG_PREFIX ${arch}-${os}-${comp} CACHE STRING "Installation binary tag prefix. The final tag will be made using the BUILD_TYPE" )
  set(BINARY_TAG ${BINARY_TAG_PREFIX}-${${CMAKE_BUILD_TYPE}2type})

tabmessage("GAUDI_PROJECT> BINARY_TAG=${BINARY_TAG}")

  if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
    set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/InstallArea/${BINARY_TAG} CACHE PATH
      "Install path prefix, prepended onto install directories." FORCE )
  endif()

  if(NOT BUILD_OUTPUT_PREFIX)
    set(BUILD_OUTPUT_PREFIX ${CMAKE_BINARY_DIR}/.build CACHE STRING
           "Base directory for generated files" FORCE)
  endif()
  if(NOT EXECUTABLE_OUTPUT_PATH)
    set(EXECUTABLE_OUTPUT_PATH ${BUILD_OUTPUT_PREFIX}/bin CACHE STRING
	   "Single build output directory for all executables" FORCE)
  endif()

tabmessage("GAUDI_PROJECT> EXECUTABLE_OUTPUT_PATH=${EXECUTABLE_OUTPUT_PATH}")

  if(NOT LIBRARY_OUTPUT_PATH)
    set(LIBRARY_OUTPUT_PATH ${BUILD_OUTPUT_PREFIX}/lib CACHE STRING
	   "Single build output directory for all libraries" FORCE)
  endif()
  if(NOT PYTHON_OUTPUT_PATH)
    set(PYTHON_OUTPUT_PATH ${BUILD_OUTPUT_PREFIX}/python CACHE STRING
	   "Single build output directory for all python files" FORCE)
  endif()


  if(BUILD_TESTS)
    enable_testing()
  endif()

  #--- Project Installations------------------------------------------------------------------------

tabmessage("GAUDI_PROJECT> (I) DIRECTORY cmake/ ")

  install(DIRECTORY cmake/ DESTINATION cmake
                           FILES_MATCHING PATTERN "*.cmake"
                           PATTERN ".svn" EXCLUDE )

tabmessage("GAUDI_PROJECT> (I) PROGRAMS cmake/testwrap.sh cmake/testwrap.csh cmake/testwrap.bat cmake/genCMake.py cmake/env.py")

  install(PROGRAMS cmake/testwrap.sh cmake/testwrap.csh cmake/testwrap.bat cmake/genCMake.py cmake/env.py DESTINATION scripts)

  #--- Global actions for the project

tabmessage("GAUDI_PROJECT> Global actions for the project ")

  INCLUDE(GaudiPolicy)

tabmessage("GAUDI_PROJECT> now call GAUDI_GET_PACKAGES")

  GAUDI_GET_PACKAGES(packages)
  #GAUDI_SORT_PACKAGES(packages ${packages})
  foreach(package ${packages})

tabmessage("GAUDI_PROJECT> -- Adding directory ${package}")

    add_subdirectory(${package})
  endforeach()

tabmessage("GAUDI_PROJECT> now call GAUDI_PROJECT_VERSION_HEADER")

  GAUDI_PROJECT_VERSION_HEADER()

tabmessage("GAUDI_PROJECT> now call GAUDI_BUILD_PROJECT_SETUP")

  GAUDI_BUILD_PROJECT_SETUP()

tabmessage("GAUDI_PROJECT> now call GAUDI_MERGE_TARGET for ConfDB Rootmap DictRootmap")

  GAUDI_MERGE_TARGET(ConfDB python ${CMAKE_PROJECT_NAME}_merged_confDb.py)
  GAUDI_MERGE_TARGET(Rootmap lib ${CMAKE_PROJECT_NAME}.rootmap)
  GAUDI_MERGE_TARGET(DictRootmap lib ${CMAKE_PROJECT_NAME}Dict.rootmap)


  #GAUDI_USE_PACKAGE(QMtest)
  #GAUDI_USE_PACKAGE(pytools)
  #GAUDI_USE_PACKAGE(RELAX)
  #SET( QMtest_environment ${QMtest_environment} QMTEST_CLASS_PATH=${CMAKE_SOURCE_DIR}/GaudiPolicy/qmtest_classes )

  #--- CPack configuration

tabmessage("GAUDI_PROJECT> CPack configuration")

  set(CPACK_PACKAGE_NAME ${project_name})
  foreach(t MAJOR MINOR PATCH)
    set(CPACK_PACKAGE_VERSION_${t} ${${project}_VERSION_${t}})
  endforeach()
  set(CPACK_SYSTEM_NAME ${BINARY_TAG})

  set(CPACK_GENERATOR TGZ)

  include(CPack)

moinstab()
endmacro()

#---------------------------------------------------------------------------------------------------
#---GAUDI_BINARY_TAG()
#---------------------------------------------------------------------------------------------------
function(GAUDI_BINARY_TAG)
plustab(GAUDI_BINARY_TAG)
  tabmessage("GAUDI_BINARY_TAG> CMAKE_SYSTEM --> ${CMAKE_SYSTEM}")
  execute_process(COMMAND uname -i OUTPUT_VARIABLE arch)
  tabmessage("GAUDI_BINARY_TAG> arch --> ${arch}")
moinstab()
endfunction()

#---------------------------------------------------------------------------------------------------
#---GAUDI_FIND_PROJECT(project version)
#---------------------------------------------------------------------------------------------------
macro( GAUDI_FIND_PROJECT project version)
plustab(GAUDI_FIND_PROJECT)
  file(TO_CMAKE_PATH "$ENV{CMAKEPROJECTPATH}" projectpath)
  foreach( path ${projectpath})
    if(EXISTS ${path}/${project})
      if(${version} STREQUAL "*")
        file(GLOB installations ${path}/${project}/${project}_* )
        foreach( installation ${installations})
          if(EXISTS ${installation}/InstallArea/${BINARY_TAG}/cmake )
            set(${project}_installation ${installation})
            break()
          endif()
        endforeach()
      else()
        if(EXISTS  ${path}/${project}/${project}_${version}/InstallArea/${BINARY_TAG}/cmake)
          set(${project}_installation ${path}/${project}/${project}_${version})
          break()
        endif()
      endif()
    endif()
    if(${project}_found)
      break()
    endif()
  endforeach()

  if( ${project}_installation )
    tabmessage("GAUDI_FIND_PROJECT> Found project ${project} with version ${version} at ${${project}_installation}")
    set(${project}_found 1)
    set(${project}_installarea ${${project}_installation}/InstallArea)
    set(${project}_binaryarea  ${${project}_installation}/InstallArea/${BINARY_TAG})
  else()
    tabmessage(ERROR "GAUDI_FIND_PROJECT> Project ${project} with version ${version} not found!!")
  endif()
moinstab()
endmacro()

#---------------------------------------------------------------------------------------------------
#---GAUDI_USE_PROJECT(project version)
#---------------------------------------------------------------------------------------------------
macro( GAUDI_USE_PROJECT project version )
  if( NOT ${project}_used )
    GAUDI_FIND_PROJECT(${project} ${version})
    if( ${project}_installation )
      #------Set the list of variables to make a effective 'use' of the project-----
      get_property(projects GLOBAL PROPERTY PROJECTS_FOUND)
      set_property(GLOBAL PROPERTY PROJECTS_FOUND ${projects} ${project})
      get_property(projects GLOBAL PROPERTY PROJECTS_FOUND)
      set(CMAKE_MODULE_PATH ${${project}_binaryarea}/cmake ${CMAKE_MODULE_PATH})
      include_directories( ${${project}_binaryarea}/include )
      link_directories( ${${project}_binaryarea}/lib )
      set(${project}_environment ${ld_library_path}+=${${project}_binaryarea}/lib
                                 PATH+=${${project}_binaryarea}/bin
                                 PATH+=${${project}_binaryarea}/scripts
                                 PYTHONPATH+=${${project}_binaryarea}/python )
      include(${project}Exports)
      set(${project}_used 1)
      #------------------------------------------------------------------------------
      if( EXISTS ${${project}_installation}/CMakeLists.txt)
        file(READ ${${project}_installation}/CMakeLists.txt file_contents)
        string( REGEX MATCHALL "GAUDI_USE_PROJECT[ ]*[(][ ]*([^)])+" vars ${file_contents})
        foreach( var ${vars})
          string(REGEX REPLACE "GAUDI_USE_PROJECT[ ]*[(][ ]*([^)])" "\\1" p ${var})
          separate_arguments(p)
          GAUDI_USE_PROJECT(${p})
        endforeach()
      endif()
    endif()
  endif()
endmacro()

#---------------------------------------------------------------------------------------------------
#---GAUDI_SORT_PACKAGES
#---------------------------------------------------------------------------------------------------
macro(__visit__ _p)
  if( NOT __${_p}_visited__)
    set(__${_p}_visited__ 1)
    #---list all dependent packages-----
    if( EXISTS ${CMAKE_SOURCE_DIR}/${_p}/CMakeLists.txt)
      file(READ ${CMAKE_SOURCE_DIR}/${_p}/CMakeLists.txt file_contents)
      string( REGEX MATCHALL "GAUDI_USE_PACKAGE[ ]*[(][ ]*([^ )])+" vars ${file_contents})
      foreach( var ${vars})
        string(REGEX REPLACE "GAUDI_USE_PACKAGE[ ]*[(][ ]*([^ )])" "\\1" __p ${var})
        __visit__(${__p})
      endforeach()
      set(out_packages ${out_packages} ${_p})
    endif()
  endif()
endmacro()

function(GAUDI_SORT_PACKAGES var)
  set(out_packages)
  set(in_packages ${ARGN})
  foreach(p ${in_packages})
    __visit__(${p})
  endforeach()
  set(${var} ${out_packages} PARENT_SCOPE)
endfunction()

#---------------------------------------------------------------------------------------------------
#---GAUDI_GET_PACKAGES
#---------------------------------------------------------------------------------------------------
function( GAUDI_GET_PACKAGES var)
plustab(GAUDI_GET_PACKAGES)
  set( packages )
  file(GLOB_RECURSE cmakelist_files  ${CMAKE_SOURCE_DIR} CMakeLists.txt)

tabmessage("GAUDI_GET_PACKAGES> CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR} cmakelist_files=${cmakelist_files}")

  foreach( file ${cmakelist_files} )
    get_filename_component(path ${file} PATH)
    if( NOT path STREQUAL ${CMAKE_SOURCE_DIR})
      string(REPLACE ${CMAKE_SOURCE_DIR}/ "" package ${path})
      SET(packages ${packages} ${package})
    endif()
  endforeach()
  set(${var} ${packages} PARENT_SCOPE)
moinstab()
endfunction()

#---------------------------------------------------------------------------------------------------
#---GAUDI_MERGE_TARGET
#---------------------------------------------------------------------------------------------------
# Create a MergedXXX target that takes input files and dependencies from
# properties of the packages
function(GAUDI_MERGE_TARGET tgt dest filename)
plustab(GAUDI_MERGE_TARGET)
  # Check if one of the packages produces files for this merge target
  get_property(needed GLOBAL PROPERTY Merged${tgt}_SOURCES SET)
  if(needed)
    # get the list of parts to merge
    get_property(parts GLOBAL PROPERTY Merged${tgt}_SOURCES)
    # create the targets
    set(output ${BUILD_OUTPUT_PREFIX}/${dest}/${filename})

tabmessage("GAUDI_MERGE_TARGET> (CC) ${merge_cmd} OUTPUT ${output}")

    add_custom_command(OUTPUT ${output}
                       COMMAND ${merge_cmd} ${parts} ${output}
                       DEPENDS ${parts})

tabmessage("GAUDI_MERGE_TARGET> (CT) Merged${tgt} ")

    add_custom_target(Merged${tgt} ALL DEPENDS ${output})
    # prepare the high level dependencies
    get_property(deps GLOBAL PROPERTY Merged${tgt}_DEPENDS)

tabmessage("GAUDI_MERGE_TARGET> (AD) Merged${tgt} ")

    add_dependencies(Merged${tgt} ${deps})
    # install rule for the merged DB

tabmessage("GAUDI_MERGE_TARGET> (I) FILES ${output} ")

    install(FILES ${output} DESTINATION ${dest})
  endif()
moinstab()
endfunction()