Skip to content
Snippets Groups Projects
DD4hepBuild.cmake 73.4 KiB
Newer Older
#  OPTIONAL       -> Optional package dependency
#                    if required e.g. [LCIO REQUIRED SOURCES aaa.cpp] the plugin will NOT be built
#                    else        e.g. [LCIO          SOURCES aaa.cpp] the plugin will be built, but
#                                     the source files will be omitted.
#  DEFINITIONS    -> Optional compiler definitions to compile the sources
#
#  \author  M.Frank
#  \version 1.0
#
#---------------------------------------------------------------------------------------------------
function( dd4hep_add_library binary building )
  cmake_parse_arguments ( ARG "NODEFAULTS;NOINSTALL" "" "SOURCES;GENERATED;LINK_LIBRARIES;INCLUDE_DIRS;USES;OPTIONAL;DEFINITIONS;PRINT" ${ARGN} )
Markus Frank's avatar
Markus Frank committed
  dd4hep_package_properties( pkg PKG_NAME enabled )
  set ( tag "Library[${pkg}] -> ${binary}" )
  if ( NOT "${ARG_PRINT}" STREQUAL "" )
    set ( tag ${ARG_PRINT} )
  endif()

  if ( NOT "${enabled}" )
    dd4hep_skipmsg ( "${tag} DISBALED -- package is not built!" )
Markus Frank's avatar
Markus Frank committed
    dd4hep_debug( "+------------------------------------------- <<<< LIBRARY ${pkg}:${binary} >>>> Version: ${${pkg}_VERSION}" )
    set ( building_binary "OFF" )
Markus Frank's avatar
Markus Frank committed
    if ( NOT "${ARG_OPTIONAL}" STREQUAL "" )
      dd4hep_handle_optional_sources ( ${tag} "${ARG_OPTIONAL}" optional_missing optional_uses optional_sources )
Markus Frank's avatar
Markus Frank committed

    if ( NOT "${optional_missing}" STREQUAL "" )
      dd4hep_print ( "|++> ${tag} (optional) skipped. Missing dependency: ${optional_missing}" )
Markus Frank's avatar
Markus Frank committed
    else()
      if ( ${ARG_NODEFAULTS} )
        set ( LOCAL_LINK_LIBRARIES )
        set ( LOCAL_LINK_LIBRARIES )
        set ( LOCAL_DEFINITIONS )
      else()
        dd4hep_use_package( "${tag}" PACKAGE LOCAL 
          USES     ${ARG_USES} ${optional_uses}
          OPTIONAL ${ARG_OPTIONAL} )
      endif()
Markus Frank's avatar
Markus Frank committed
      if ( NOT "${LOCAL_MISSING}" STREQUAL "" )
        dd4hep_print ( "|++> ${tag} skipped. Missing dependency: ${missing}" )
Markus Frank's avatar
Markus Frank committed
      endif()
Markus Frank's avatar
Markus Frank committed
      dd4hep_make_unique_list( pkg_incs VALUES ${LOCAL_INCLUDE_DIRS}   ${ARG_INCLUDE_DIRS} )
      dd4hep_make_unique_list( pkg_libs VALUES ${LOCAL_LINK_LIBRARIES} ${ARG_LINK_LIBRARIES} )
      dd4hep_make_unique_list( pkg_defs VALUES ${LOCAL_DEFINITIONS}    ${ARG_DEFINITIONS} )
Markus Frank's avatar
Markus Frank committed
      file ( GLOB   sources ${ARG_SOURCES} )
      list ( APPEND sources ${optional_sources} )
      if ( NOT "${ARG_GENERATED}" STREQUAL "" )
        #
        # root-cint produces warnings of type 'unused-function' disable them on generated files
        foreach ( f in  ${ARG_GENERATED} )
          set_source_files_properties( ${f} PROPERTIES COMPILE_FLAGS "-Wno-unused-function -Wno-overlength-strings" GENERATED TRUE )
Markus Frank's avatar
Markus Frank committed
        endforeach()
        list ( APPEND sources ${ARG_GENERATED} )
Markus Frank's avatar
Markus Frank committed
      #
      if ( NOT "${sources}" STREQUAL "" )
        dd4hep_make_unique_list ( sources  VALUES ${sources} )
        dd4hep_debug( "${tag} ${sources}")
        #
        dd4hep_include_directories( "${pkg_incs}" )
Markus Frank's avatar
Markus Frank committed
        add_definitions ( ${pkg_defs} )
        #
        add_library ( ${binary} SHARED ${sources} )
        target_link_libraries ( ${binary} ${pkg_libs} )
        if ( "${${pkg}_VERSION}" STREQUAL "" OR "${${pkg}_SOVERSION}" STREQUAL "" )
          dd4hep_fatal ( "BAD Package versions: VERSION[${pkg}_VERSION] ${${pkg}_VERSION} SOVERSION[${pkg}_SOVERSION] ${${pkg}_SOVERSION} " )
Markus Frank's avatar
Markus Frank committed
        endif()
        ##dd4hep_print ( "set_target_properties ( ${binary} PROPERTIES VERSION ${${pkg}_VERSION} SOVERSION ${${pkg}_SOVERSION})")
Markus Frank's avatar
Markus Frank committed
        set_target_properties ( ${binary} PROPERTIES VERSION ${${pkg}_VERSION} SOVERSION ${${pkg}_SOVERSION})
        #
        if ( NOT ${ARG_NOINSTALL} )
          install ( TARGETS ${binary}  
            LIBRARY DESTINATION lib 
            RUNTIME DESTINATION bin)
        endif()
Markus Frank's avatar
Markus Frank committed
        set ( building_binary "ON" )
      else()
        dd4hep_print ( "|++> ${tag} Skipped. No sources to be compiled [Use constraint]" )
Markus Frank's avatar
Markus Frank committed
      endif()
    endif()
  endif()
  set ( ${building} ${building_binary} PARENT_SCOPE )
endfunction(dd4hep_add_library)

#---------------------------------------------------------------------------------------------------
#  dd4hep_add_regular_library
#
#  Arguments      -> See function dd4hep_add_library
#
#  \author  M.Frank
#  \version 1.0
#
#---------------------------------------------------------------------------------------------------
function( dd4hep_add_regular_library library )
  dd4hep_package_properties( pkg PKG enabled )
  set ( tag "Package library[${pkg}] -> ${library}" )
  if ( NOT "${enabled}" )
    dd4hep_skipmsg ( "${tag} DISBALED -- package is not built!" )
  else()
    dd4hep_add_library( ${library} building ${ARGN} PRINT ${tag} )
    if ( "${building}" )
      dd4hep_debug ( "add_package_library -> ${library} ${PKG}_LIBRARIES:${pkg_libs}" )
    else()
      dd4hep_fatal ( "Package library[${pkg}] -> ${binary} Cannot be built! This is an ERROR condition." )    
    endif()
  endif()
endfunction(dd4hep_add_regular_library)

#---------------------------------------------------------------------------------------------------
#  dd4hep_add_package_library
#
#  Package libraries are automatically added to the package's link libraries.
#  Package plugins and plugins depending on a package automically link against 
#  these libraries.
#
#  Arguments      -> See function dd4hep_add_library
#
#  \author  M.Frank
#  \version 1.0
#
#---------------------------------------------------------------------------------------------------
function( dd4hep_add_package_library library )
Markus Frank's avatar
Markus Frank committed
  dd4hep_package_properties( pkg PKG enabled )
  set ( tag "Package library[${pkg}] -> ${library}" )
  if ( NOT "${enabled}" )
    dd4hep_skipmsg ( "${tag} DISBALED -- package is not built!" )
Markus Frank's avatar
Markus Frank committed
    dd4hep_add_library( ${library} building ${ARGN} PRINT ${tag} )
    if ( "${building}" )
Markus Frank's avatar
Markus Frank committed
      get_property(pkg_libs GLOBAL PROPERTY PROPERTY ${PKG}_LIBRARIES )
      dd4hep_make_unique_list ( pkg_libs VALUES ${pkg_libs} ${library} )
      set_property(GLOBAL PROPERTY ${PKG}_LIBRARIES ${pkg_libs} )
      # Test and print if correct
      get_property(pkg_libs GLOBAL PROPERTY PROPERTY ${PKG}_LIBRARIES )
      dd4hep_debug ( "add_package_library -> ${library} ${PKG}_LIBRARIES:${pkg_libs}" )
    else()
      dd4hep_fatal ( "Package library[${pkg}] -> ${binary} Cannot be built! This is an ERROR condition." )    
Markus Frank's avatar
Markus Frank committed
    endif()
  endif()
endfunction(dd4hep_add_package_library)

#---------------------------------------------------------------------------------------------------
#
#  dd4hep_add_plugin 
#
#  Arguments
#  ---------
#  binary         -> plugin name
#  SOURCES        -> list of source files. Will be expanded to absolute names
#
#  The following variables EXTEND the package defaults
#  INCLUDE_DIRS   -> Additional include directories need to compile the binary
#  LINK_LIBRARIES -> Additional libraries needed to link the binary
#  USES           -> Required package dependencies
#  OPTIONAL       -> Optional package dependency
#                    if required e.g. [LCIO REQUIRED SOURCES aaa.cpp] the plugin will NOT be built
#                    else        e.g. [LCIO          SOURCES aaa.cpp] the plugin will be built, but
#                                     the source files will be omitted.
#  DEFINITIONS    -> Optional compiler definitions to compile the sources
#
#  \author  M.Frank
#  \version 1.0
#
#---------------------------------------------------------------------------------------------------
function( dd4hep_add_plugin binary )
Markus Frank's avatar
Markus Frank committed
  dd4hep_package_properties( pkg PKG enabled )
  set ( tag "Plugin[${pkg}] -> ${binary}" )
  if ( NOT "${enabled}" )
    dd4hep_skipmsg ( "${tag} DISBALED -- package is not built!" )
Markus Frank's avatar
Markus Frank committed
  else()
    cmake_parse_arguments(ARG "NOINSTALL" "" "SOURCES;GENERATED;LINK_LIBRARIES;INCLUDE_DIRS;USES;OPTIONAL;DEFINITIONS" ${ARGN})
    if ( ${ARG_NOINSTALL} )
      set(NOINSTALL NOINSTALL)
    endif()
Markus Frank's avatar
Markus Frank committed
    get_property(pkg_lib  GLOBAL PROPERTY ${PKG}_LIBRARIES )
    dd4hep_add_library( ${binary} building
      PRINT          ${tag}
      SOURCES        ${ARG_SOURCES}
      GENERATED      ${ARG_GENERATED}
      LINK_LIBRARIES ${ARG_LINK_LIBRARIES} ${pkg_lib}
      INCLUDE_DIRS   ${ARG_INCLUDE_DIRS} 
      USES           ${ARG_USES}
      OPTIONAL       "${ARG_OPTIONAL}"
Markus Frank's avatar
Markus Frank committed
    #
    # Generate ROOTMAP if the plugin will be built:
    if ( "${building}" )
Markus Frank's avatar
Markus Frank committed
      dd4hep_generate_rootmap( ${binary} )
    endif()
  endif()
endfunction(dd4hep_add_plugin)

#---------------------------------------------------------------------------------------------------
#  dd4hep_add_executable
#
#  Arguments
#  ---------
#  binary        -> plugin name
#  SOURCES        -> list of source files. Will be expanded to absolute names
#
#  The following variables EXTEND the package defaults
#  INCLUDE_DIRS   -> Additional include directories need to compile the binary
#  LINK_LIBRARIES -> Additional libraries needed to link the binary
#  USES           -> Required package dependencies
#  OPTIONAL       -> Optional package dependency
#                    if required e.g. [LCIO REQUIRED SOURCES aaa.cpp] the plugin will NOT be built
#                    else        e.g. [LCIO          SOURCES aaa.cpp] the plugin will be built, but
#                                     the source files will be omitted.
#  DEFINITIONS    -> Optional compiler definitions to compile the sources
#
#  \author  M.Frank
#  \version 1.0
#
#---------------------------------------------------------------------------------------------------
function ( dd4hep_add_executable binary )
Markus Frank's avatar
Markus Frank committed
  dd4hep_package_properties( pkg PKG enabled )
  set ( tag "Executable[${pkg}] -> ${binary}" )
  if ( NOT "${enabled}" )
    dd4hep_skipmsg ( "${tag} DISBALED -- package is not built!" )
Markus Frank's avatar
Markus Frank committed
    cmake_parse_arguments ( ARG "" "" "SOURCES;GENERATED;LINK_LIBRARIES;INCLUDE_DIRS;USES;OPTIONAL" ${ARGN})
    dd4hep_debug( "+------------------------------------------- <<<< EXECUTABLE ${pkg}:${binary} >>>> Version: ${${pkg}_VERSION}" )
    if ( NOT "${ARG_OPTIONAL}" STREQUAL "" )
      dd4hep_handle_optional_sources ( ${tag} "${ARG_OPTIONAL}" optional_missing optional_uses optional_sources )
    endif()
    #
    if ( NOT "${optional_missing}" STREQUAL "" )
      dd4hep_print ( "|++> ${tag} SKIPPED. Missing optional dependencies: ${optional_missing}" )
Markus Frank's avatar
Markus Frank committed
    else()
      set ( uses ${ARG_USES} ${optional_uses} )
      dd4hep_use_package ( ${tag} PACKAGE LOCAL 
        USES     "${uses}"
        OPTIONAL "${ARG_OPTIONAL}" )
      if ( "${LOCAL_MISSING}" STREQUAL "" )
        dd4hep_debug ( "${tag} Executable uses:     ${ARG_USES} -- ${uses}" )
        dd4hep_debug ( "${tag} Executable optional: ${ARG_OPTIONAL}" )
        #
        get_property ( pkg_library GLOBAL PROPERTY ${PKG}_LIBRARIES )
        #
        #  Sources may also be supplied without argument tag:
        if( "${ARG_SOURCES}" STREQUAL "")
	  set ( ARG_SOURCES ${ARG_UNPARSED_ARGUMENTS} )
        endif()
Markus Frank's avatar
Markus Frank committed
        #  Prepare flags for cint generated sources:
        foreach ( f in  ${ARG_GENERATED} )
          set_source_files_properties( ${f} PROPERTIES COMPILE_FLAGS "-Wno-unused-function -Wno-overlength-strings" GENERATED TRUE )
Markus Frank's avatar
Markus Frank committed
        endforeach()
        #
Markus Frank's avatar
Markus Frank committed
        set ( sources ${ARG_GENERATED} ${ARG_SOURCES} ${optional_sources} )
Markus Frank's avatar
Markus Frank committed
        #
Markus Frank's avatar
Markus Frank committed
        if( NOT "${sources}" STREQUAL "")
	  set (incs ${LOCAL_INCLUDE_DIRS} ${ARG_INCLUDE_DIRS} )
Markus Frank's avatar
Markus Frank committed
	  set (libs ${pkg_library} ${LOCAL_LINK_LIBRARIES} ${ARG_LINK_LIBRARIES} )
Markus Frank's avatar
Markus Frank committed
	  dd4hep_make_unique_list ( incs    VALUES ${incs} )
Markus Frank's avatar
Markus Frank committed
	  dd4hep_make_unique_list ( libs    VALUES ${libs} )
	  dd4hep_make_unique_list ( sources VALUES ${sources} )
	  #
	  dd4hep_debug ( "${tag} Libs:${libs}" )
	  dd4hep_include_directories( "${incs}" )
Markus Frank's avatar
Markus Frank committed
	  add_executable( ${binary} ${sources} )
	  target_link_libraries( ${binary} ${libs} )
	  #
	  #  Install the binary to the destination directory
	  install(TARGETS ${binary} 
	    LIBRARY DESTINATION lib 
	    RUNTIME DESTINATION bin )
        else()
	  dd4hep_print ( "|++> ${tag} SKIPPED. No sources to build [Use constraint]" )
Markus Frank's avatar
Markus Frank committed
        endif()
        dd4hep_fatal ( "${tag} SKIPPED. Missing dependencies: ${LOCAL_MISSING}" )
      endif()
    endif()
  endif()
endfunction(dd4hep_add_executable)

#---------------------------------------------------------------------------------------------------
#  dd4hep_add_dictionary
#
#
#  \author  M.Frank
#  \version 1.0
#
#---------------------------------------------------------------------------------------------------
function( dd4hep_add_dictionary dictionary )
Markus Frank's avatar
Markus Frank committed
  dd4hep_package_properties( pkg PKG enabled )
  set ( tag "Dictionary[${pkg}] -> ${dictionary}" )
  if ( NOT "${enabled}" )
    dd4hep_skipmsg ( "${tag} DISBALED -- package is not built!" )
Markus Frank's avatar
Markus Frank committed
  else()
    cmake_parse_arguments(ARG "" "" "SOURCES;EXCLUDE;LINKDEF;OPTIONS;OPTIONAL;INCLUDES;OUTPUT" ${ARGN} )
    dd4hep_print ( "|++> ${tag} Building dictionary ..." ) 
Markus Frank's avatar
Markus Frank committed
    if("${ARG_LINKDEF}" STREQUAL "")
      set(ARG_LINKDEF "${CMAKE_SOURCE_DIR}/DDCore/include/ROOT/LinkDef.h")
    endif()
    #
    if ( NOT "${ARG_OPTIONAL}" STREQUAL "" )
      dd4hep_handle_optional_sources ( ${tag} "${ARG_OPTIONAL}" optional_missing optional_uses optional_sources )
    endif()
    #
    if ( NOT "${optional_missing}" STREQUAL "" )
      dd4hep_print ( "|++> ${tag} SKIPPED. Missing optional dependencies: ${optional_missing}" )
    else()
      set ( uses ${ARG_USES} ${optional_uses} )
      dd4hep_use_package ( ${tag} PACKAGE LOCAL 
        USES     "${uses}"
        OPTIONAL "${ARG_OPTIONAL}" )
    endif()
    if ( NOT "${LOCAL_MISSING}" STREQUAL "" )
      dd4hep_print ( "|++> ${tag} skipped. Missing dependency: ${missing}  --> FATAL ERROR. Build should fail!" )
    endif()
    #
    get_property(incs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY PACKAGE_INCLUDE_DIRS)
    get_property(defs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS)
    get_property(opts DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_OPTIONS)
    dd4hep_make_unique_list( incs VALUES ${LOCAL_INCLUDE_DIRS}   ${incs} )
    dd4hep_make_unique_list( defs VALUES ${LOCAL_DEFINITIONS}    ${defs} )
    #
Markus Frank's avatar
Markus Frank committed
    file( GLOB headers ${ARG_SOURCES} )
    file( GLOB excl_headers ${ARG_EXCLUDE} )
    foreach( f ${excl_headers} )
      list( REMOVE_ITEM headers ${f} )
      dd4hep_print ( "|++        exclude: ${f}" )
Markus Frank's avatar
Markus Frank committed
    endforeach()
    #
    set ( inc_dirs -I${CMAKE_CURRENT_SOURCE_DIR}/include )
Markus Frank's avatar
Markus Frank committed
    foreach ( inc ${ARG_INCLUDES} )
      set ( inc_dirs ${inc_dirs} -I${inc} )
    endforeach()
Markus Frank's avatar
Markus Frank committed
    foreach ( inc ${incs} )
      file ( GLOB inc ${inc} )
      set ( inc_dirs ${inc_dirs} -I${inc} )
    endforeach()
    #
    file ( GLOB linkdefs ${ARG_LINKDEF} )
    #
    set ( comp_defs )
    foreach ( def ${defs} )
      set ( comp_defs ${comp_defs} -D${def} )
    endforeach()
    #
    dd4hep_make_unique_list ( sources   VALUES ${headers} )
    dd4hep_make_unique_list ( linkdefs  VALUES ${linkdefs} )
    dd4hep_make_unique_list ( inc_dirs  VALUES ${inc_dirs} )
    dd4hep_make_unique_list ( comp_defs VALUES ${comp_defs} )
    #
    dd4hep_debug ( "${tag}  Linkdef: '${linkdefs}'" ) 
    dd4hep_debug ( "${tag}  Compile: '${comp_defs};${inc_dirs}'" ) 
    dd4hep_debug ( "${tag}  Files:   '${headers}'" ) 
    dd4hep_debug ( "${tag}  Unparsed:'${ARG_UNPARSED_ARGUMENTS}'" ) 
    dd4hep_debug ( "${tag}  Sources: '${CMAKE_CURRENT_SOURCE_DIR}'" ) 
    #
    set ( output_dir ${CMAKE_CURRENT_BINARY_DIR}/../lib )
    if ( NOT "${ARG_OUTPUT}" STREQUAL "" )
      set ( output_dir ${ARG_OUTPUT} )
    endif()
    add_custom_command(OUTPUT ${dictionary}.cxx
      COMMAND ${ROOT_rootcling_CMD} -cint -f ${dictionary}.cxx
      -s ${output_dir}/${dictionary} -inlineInputHeader -c -p ${ARG_OPTIONS} ${comp_defs} -std=c++${CMAKE_CXX_STANDARD} ${inc_dirs} ${headers} ${linkdefs}
      DEPENDS ${headers} ${linkdefs} )
    #  Install the binary to the destination directory
    install(FILES ${output_dir}/${dictionary}_rdict.pcm DESTINATION lib)
endfunction()

#---------------------------------------------------------------------------------------------------
#
#  \author  M.Frank
#  \version 1.0
#
#---------------------------------------------------------------------------------------------------
macro( dd4hep_enable_tests )
  cmake_parse_arguments(MACRO_ARG "" "" "" ${ARGV} )
  if (BUILD_TESTING)
    set ( BUILDNAME "${CMAKE_SYSTEM}-${CMAKE_CXX_COMPILER}-${CMAKE_BUILD_TYPE}" CACHE STRING "set build string for cdash")
    dd4hep_list_to_string( _dir_entries PREFIX "DIRS:" ENTRIES ${MACRO_ARG_UNPARSED_ARGUMENTS} )
    dd4hep_print ( "|++> Enable CTest environment....BUILD:${BUILD_TESTING} ${_dir_entries}" )
    include(CTest)
    enable_testing ()
    if ( NOT "${MACRO_ARG_UNPARSED_ARGUMENTS}" STREQUAL "" )
      foreach ( _dir ${MACRO_ARG_UNPARSED_ARGUMENTS} )
        add_subdirectory ( ${_dir} )
      endforeach()
    endif()
  endif()
endmacro( dd4hep_enable_tests )

#---------------------------------------------------------------------------------------------------
macro ( dd4hep_configure_scripts _pkg )
  cmake_parse_arguments(MACRO_ARG "DEFAULT_SETUP;WITH_TESTS" "RUN_SCRIPT" "" ${ARGV} )
  # PackageName is a variable required by existing LC build scripts. 
  # Set it here and unset it at the end of the scope...
  set( PackageName ${_pkg} )
  dd4hep_list_to_string( _dir_entries PREFIX "DIRS:" ENTRIES ${MACRO_ARG_UNPARSED_ARGUMENTS} )
  dd4hep_print ( "|++> Setting up test environment for ${PackageName}: Testing:${BUILD_TESTING} Setup:${MACRO_ARG_DEFAULT_SETUP} With Tests(${MACRO_ARG_WITH_TESTS}): ${_dir_entries}" )
  if ( (NOT "${MACRO_ARG_DEFAULT_SETUP}" STREQUAL "") OR (NOT "${_pkg}" STREQUAL "") )
    configure_file( ${DD4hep_DIR}/cmake/run_test_package.sh ${EXECUTABLE_OUTPUT_PATH}/run_test_${_pkg}.sh @ONLY)
    INSTALL(PROGRAMS ${EXECUTABLE_OUTPUT_PATH}/run_test_${_pkg}.sh DESTINATION bin )
    #---- configure run environment ---------------
    configure_file( ${DD4hep_DIR}/cmake/thisdd4hep_package.sh.in  ${EXECUTABLE_OUTPUT_PATH}/this${_pkg}.sh @ONLY)
    install(PROGRAMS ${EXECUTABLE_OUTPUT_PATH}/this${_pkg}.sh DESTINATION bin )
    #--- install target-------------------------------------
    if ( IS_DIRECTORY scripts )
      dd4hep_install_dir ( compact scripts DESTINATION examples/${_pkg} )
    endif()
    if ( IS_DIRECTORY compact )
      dd4hep_install_dir ( compact DESTINATION examples/${_pkg} )
    endif()
  endif()
Andre Sailer's avatar
Andre Sailer committed
  #dd4hep_enable_tests ( ${MACRO_ARG_UPARSED_ARGUMENTS} )
  unset( PackageName )
endmacro( dd4hep_configure_scripts )

#---------------------------------------------------------------------------------------------------
#  dd4hep_add_test_reg
#
#  Add test with regular expression output parsing.
#  BUILD_EXEC:  Add and build executable with the same name as the test (Default NONE)
#  OUTPUT       Output file of the test (Default: empty)
#  COMMAND      Command to execute
#  EXEC_ARGS    Arguments to the command
#  REGEX_PASS   Regular expression to indicate that the test succeeded
#  REGEX_FAIL   Regular expression to indicate that the test failed
#
#  \author  M.Frank
#  \version 1.0
#
#---------------------------------------------------------------------------------------------------
function ( dd4hep_add_test_reg test_name )
  cmake_parse_arguments(ARG "BUILD_EXEC" "OUTPUT" "COMMAND;DEPENDS;EXEC_ARGS;REGEX_PASS;REGEX_PASSED;REGEX_FAIL;REGEX_FAILED" ${ARGN} )
Markus Frank's avatar
Markus Frank committed
  set ( missing )
  set ( use_test 1 )
Markus Frank's avatar
Markus Frank committed
  if ( "${use_test}" STREQUAL "" )
    dd4hep_print ( "*** Will not build/execute test ${test_name}. Missing dependencies: ${missing} ")
Markus Frank's avatar
Markus Frank committed
  else()
    if ( ${ARG_BUILD_EXEC} )
      #dd4hep_print ( "Building executable:  ${test_name} SOURCES src/${test_name}.cc")
Markus Frank's avatar
Markus Frank committed
      dd4hep_add_executable ( ${test_name} SOURCES src/${test_name}.cc )
    endif()
Markus Frank's avatar
Markus Frank committed
    set ( cmd ${ARG_COMMAND} )
    if ( "${cmd}" STREQUAL "" )
      set ( cmd ${CMAKE_INSTALL_PREFIX}/bin/run_test.sh ${test_name} )
    endif()
Markus Frank's avatar
Markus Frank committed
    set ( passed ${ARG_REGEX_PASS} ${ARG_REGEX_PASSED} )
    if ( "${passed}" STREQUAL "NONE" )
      unset ( passed )
    elseif ( "${passed}" STREQUAL "" )
      set ( passed "TEST_PASSED" )
    endif()
Markus Frank's avatar
Markus Frank committed
    set ( failed ${ARG_REGEX_FAIL} ${ARG_REGEX_FAILED} )
    if ( "${failed}" STREQUAL "NONE" )
      unset ( failed )
    endif()
    set ( output ${ARG_OUTPUT} )
Markus Frank's avatar
Markus Frank committed
    set ( args ${ARG_EXEC_ARGS} )
    if ( "${args}" STREQUAL "" )
      set ( args ${test_name} )
    endif()
    add_test(NAME t_${test_name} COMMAND ${cmd} ${output} ${args} ${output} )
    if ( NOT "${passed}" STREQUAL "" )
      set_tests_properties( t_${test_name} PROPERTIES PASS_REGULAR_EXPRESSION "${passed}" )
    endif()
    if ( NOT "${failed}" STREQUAL "" )
      set_tests_properties( t_${test_name} PROPERTIES FAIL_REGULAR_EXPRESSION "${failed}" )
    endif()
Markus Frank's avatar
Markus Frank committed
    # Set test dependencies if present
    foreach ( _dep ${ARG_DEPENDS} )
      set_tests_properties( t_${test_name} PROPERTIES DEPENDS t_${_dep} )
    endforeach()

#---------------------------------------------------------------------------------------------------
#  fill_dd4hep_library_path
#
#
#  \author  M.Petric
#  \version 1.0
#
#---------------------------------------------------------------------------------------------------
function ( fill_dd4hep_library_path )
  string(REGEX REPLACE "/lib/libCore.*" "" ROOT_ROOT ${ROOT_Core_LIBRARY})
  SET( ENV{DD4HEP_LIBRARY_PATH} ${ROOT_ROOT}/lib )
  if ( NOT "${Boost_LIBRARY_DIRS}" STREQUAL "" )
    SET( ENV{DD4HEP_LIBRARY_PATH} $ENV{DD4HEP_LIBRARY_PATH}:${Boost_LIBRARY_DIRS} )
  else()
    dd4hep_print("|++> The boost library path cannot be determined. Problems maybe ahead.")
  endif()
  if ( ${DD4HEP_USE_GEANT4} )
    string(REGEX REPLACE "/lib/Geant4.*" "" Geant4_ROOT ${Geant4_DIR})
    SET( ENV{DD4HEP_LIBRARY_PATH} ${Geant4_ROOT}/lib:$ENV{DD4HEP_LIBRARY_PATH} )
  endif()

  if(${DD4HEP_USE_LCIO})
    SET( ENV{DD4HEP_LIBRARY_PATH} ${LCIO_DIR}/lib:$ENV{DD4HEP_LIBRARY_PATH} )
  endif()

  SET( ENV{DD4HEP_LIBRARY_PATH} ${CLHEP_ROOT_DIR}/lib:$ENV{DD4HEP_LIBRARY_PATH} )

  if(${DD4HEP_USE_XERCESC})
    SET( ENV{DD4HEP_LIBRARY_PATH} ${XERCESC_ROOT_DIR}/lib:$ENV{DD4HEP_LIBRARY_PATH} )
  endif()

  SET( ENV{DD4HEP_LIBRARY_PATH} ${CMAKE_BINARY_DIR}/lib:$ENV{DD4HEP_LIBRARY_PATH} )
endfunction()


#---------------------------------------------------------------------------------------------------
#  new_dd4hep_add_dictionary
#
#
#  \author  A.Sailer
#  \version 1.0
#
#---------------------------------------------------------------------------------------------------
function( new_dd4hep_add_dictionary dictionary )
  cmake_parse_arguments(ARG "" "" "SOURCES;EXCLUDE;LINKDEF;OPTIONS;OPTIONAL;DEPENDS;DEFINITIONS;INCLUDES;OUTPUT" ${ARGN} )
  dd4hep_print ( "|++> Building dictionary ... ${dictionary}" ) 
  # if ( NOT "${ARG_OPTIONAL}" STREQUAL "" )
  #   dd4hep_handle_optional_sources ( ${tag} "${ARG_OPTIONAL}" optional_missing optional_uses optional_sources )
  # endif()

  file(GLOB headers ${ARG_SOURCES})
  file(GLOB excl_headers ${ARG_EXCLUDE})

  foreach( f ${excl_headers} )
    list( REMOVE_ITEM headers ${f} )
    dd4hep_print ( "|++        exclude: ${f}" )
  endforeach()
  
  set(inc_dirs ${CMAKE_CURRENT_SOURCE_DIR}/include)
  foreach(inc ${ARG_INCLUDES})
    LIST(APPEND inc_dirs ${inc})
  endforeach()

  set(comp_defs)
  foreach(def ${ARG_DEFINITIONS})
    LIST(APPEND comp_defs ${def})
  endforeach()

  foreach(DEP ${ARG_DEPENDS})
    # Get INCLUDE DIRECTORIES from Dependencies
    LIST(APPEND inc_dirs $<TARGET_PROPERTY:${DEP},INTERFACE_INCLUDE_DIRECTORIES>)
    # Get COMPILE DEFINITIONS from Dependencies
    LIST(APPEND comp_defs $<TARGET_PROPERTY:${DEP},INTERFACE_COMPILE_DEFINITIONS>)
  endforeach()

  #
  file ( GLOB linkdefs ${ARG_LINKDEF} )
  #
  dd4hep_debug("|++        Linkdef:    '${linkdefs}'" ) 
  dd4hep_debug("|++        Definition: '${comp_defs}'" ) 
  dd4hep_debug("|++        Include:    '${inc_dirs}'" ) 
  dd4hep_debug("|++        Files:      '${headers}'" ) 
  dd4hep_debug("|++        Unparsed:   '${ARG_UNPARSED_ARGUMENTS}'" ) 
  dd4hep_debug("|++        Sources:    '${CMAKE_CURRENT_SOURCE_DIR}'" ) 
  #
  set ( output_dir ${CMAKE_CURRENT_BINARY_DIR}/../lib )
  if ( NOT "${ARG_OUTPUT}" STREQUAL "" )
    set ( output_dir ${ARG_OUTPUT} )
  endif()

  SET(COMP_DEFS )
  SET(SPACE_I " -I")
  file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${dictionary}_arguments
    CONTENT "${ROOT_rootcling_CMD} -cint -f ${dictionary}.cxx -s ${output_dir}/${dictionary} -inlineInputHeader -c -p ${ARG_OPTIONS} -std=c++${CMAKE_CXX_STANDARD}  \
   $<$<BOOL:${comp_defs}>:-D$<JOIN:${comp_defs}, -D>> \
   $<$<BOOL:${inc_dirs}>:-I$<JOIN:${inc_dirs}, -I>> \
   $<JOIN:${headers}, >  $<JOIN:${linkdefs}, >"
    )
  add_custom_command(OUTPUT ${dictionary}.cxx ${output_dir}/${dictionary}_rdict.pcm
    COMMAND bash ${dictionary}_arguments
    DEPENDS ${headers} ${linkdefs}
    )
  add_custom_target(${dictionary}
    DEPENDS ${dictionary}.cxx ${output_dir}/${dictionary}_rdict.pcm
    )

  set_source_files_properties(${dictionary}.cxx ${output_dir}/${dictionary}_rdict.pcm
    PROPERTIES
    GENERATED TRUE)

  #  Install the binary to the destination directory
  install(FILES ${output_dir}/${dictionary}_rdict.pcm DESTINATION lib)

endfunction()


#---------------------------------------------------------------------------------------------------
#
#  new_dd4hep_add_plugin 
#
#  Arguments
#  ---------
#  binary         -> plugin name
#  SOURCES        -> Globbing expression to find source files
#  GENERATED      -> List of source files
#
#  INCLUDE_DIRS   -> Additional include directories need to compile the binary
#  LINK_LIBRARIES -> Additional libraries needed to link the binary
#  DEFINITIONS    -> Optional compiler definitions to compile the sources
#  \author  A.Sailer
#  \version 1.0
#
#---------------------------------------------------------------------------------------------------
function(new_dd4hep_add_plugin binary)
  cmake_parse_arguments(ARG "NOINSTALL" "" "SOURCES;GENERATED;LINK_LIBRARIES;INCLUDE_DIRS;DEFINITIONS" ${ARGN})
  if ( ${ARG_NOINSTALL} )
    set(NOINSTALL NOINSTALL)
  endif()
  file(GLOB SOURCES ${ARG_SOURCES})
Andre Sailer's avatar
Andre Sailer committed
  foreach( f in  ${ARG_GENERATED})
    set_source_files_properties(${f} PROPERTIES
      COMPILE_FLAGS "-Wno-unused-function -Wno-overlength-strings"
      GENERATED TRUE)
  endforeach()
Andre Sailer's avatar
Andre Sailer committed
  ADD_LIBRARY(${binary} SHARED ${SOURCES} ${ARG_GENERATED})
  TARGET_LINK_LIBRARIES(${binary} PUBLIC ${ARG_LINK_LIBRARIES})
  TARGET_INCLUDE_DIRECTORIES(${binary} PUBLIC ${ARG_INCLUDE_DIRS})
  TARGET_COMPILE_DEFINITIONS(${binary} PUBLIC ${ARG_DEFINITIONS})
  # what do these options mean?
  #NOINSTALL
  # Generate ROOTMAP if the plugin will be built:
  dd4hep_generate_rootmap( ${binary} )
endfunction(new_dd4hep_add_plugin)
Andre Sailer's avatar
Andre Sailer committed




macro(DD4HEP_SETUP_ROOT_TARGETS)

  #ROOT CXX Flags are a string with quotes, not a list, so we need to convert to a list...
  string(REPLACE " " ";" ROOT_CXX_FLAGS ${ROOT_CXX_FLAGS})

  IF(NOT TARGET ROOT::Core)
    #in ROOT before 6.10 there is no ROOT namespace, so we create ROOT::Core ourselves
    ADD_LIBRARY(ROOT::Core INTERFACE IMPORTED GLOBAL)
    SET_TARGET_PROPERTIES(ROOT::Core
      PROPERTIES
      INTERFACE_COMPILE_OPTIONS "${ROOT_CXX_FLAGS}"
      INTERFACE_INCLUDE_DIRECTORIES ${ROOT_INCLUDE_DIRS}
      )
    # there is also no dependency between the targets
    TARGET_LINK_LIBRARIES(ROOT::Core INTERFACE Core Rint Tree MathCore Hist Physics)
    #foreach(LIB Core RIO Net Hist Graf Graf3d Gpad Tree Rint Postscript Matrix Physics MathCore Thread MultiProc)
    # MESSAGE(STATUS "ROOT lib location ${LIB} ${ROOT_${LIB}_LIBRARY}")
    # SET_TARGET_PROPERTIES(ROOT::${LIB}
    #   PROPERTIES
    #   INTERFACE_COMPILE_OPTIONS "${ROOT_CXX_FLAGS}"
    #   INTERFACE_INCLUDE_DIRECTORIES ${ROOT_INCLUDE_DIRS}
    #   IMPORTED_LOCATION ${ROOT_${LIB}_LIBRARY}
    #   )
    #endforeach()
    # Non-standard ROOT components we need later on, we "import" them by hand for now
    foreach(LIB PyROOT Geom GenVector Eve Graf3d RGL Gui RIO MathCore MathMore)
      ADD_LIBRARY(ROOT::${LIB} INTERFACE IMPORTED GLOBAL)
      TARGET_LINK_LIBRARIES(ROOT::${LIB} INTERFACE ${LIB})
      # SET_TARGET_PROPERTIES(ROOT::${LIB}
      #   PROPERTIES
      #   INTERFACE_COMPILE_OPTIONS "${ROOT_CXX_FLAGS}"
      #   INTERFACE_INCLUDE_DIRECTORIES ${ROOT_INCLUDE_DIRS}
      #   IMPORTED_LOCATION ${ROOT_${LIB}_LIBRARY}
      #   )
    endforeach()
  ENDIF(NOT TARGET ROOT::Core)


  MESSAGE(STATUS "ROOT Libraries ${ROOT_LIBRARIES}")
  MESSAGE(STATUS "ROOT CXX_FLAGS ${ROOT_CXX_FLAGS}")
  MESSAGE(STATUS "ROOT INCL DIRS ${ROOT_INCLUDE_DIRS}")
  MESSAGE(STATUS "ROOT_VERSION: ${ROOT_VERSION}" )

ENDMACRO()


MACRO(DD4HEP_SETUP_GEANT4_TARGETS)

  IF(NOT TARGET Geant4::Interface)
    
    #include( ${Geant4_USE_FILE} ) # do not use the use file, this is not very considerate...
    IF((NOT ${Geant4_TLS_MODEL} STREQUAL "global-dynamic") AND NOT ${DD4HEP_IGNORE_GEANT4_TLS})
      MESSAGE(FATAL_ERROR "Geant4 was built with ${Geant4_TLS_MODEL}, DD4hep requires 'global-dynamic'! Ignore this ERROR with DD4HEP_IGNORE_GEANT4_TLS=True ")
    ENDIF()

    # if(Geant4_builtin_clhep_FOUND)
    #   set(CLHEP "")
    # else()
    #   FIND_PACKAGE(CLHEP REQUIRED)
    #   set(CLHEP CLHEP)
    # endif()

    MESSAGE(STATUS "Geant4 Libraries ${Geant4_LIBRARIES}")
    MESSAGE(STATUS "Geant4 CXX_FLAGS ${Geant4_CXX_FLAGS}")
    MESSAGE(STATUS "Geant4 INCL DIRS ${Geant4_INCLUDE_DIRS}")
    MESSAGE(STATUS "Geant4_VERSION: ${Geant4_VERSION}" )

    # Geant4::10.2.2 at least, not in 10.5 (check where it switches)
    # Geant4 CXX Flags are a string with quotes, not a list, so we need to convert to a list...
    string(REPLACE " " ";" Geant4_Flags ${Geant4_CXX_FLAGS} ${Geant4_CXX_FLAGS_${CMAKE_BUILD_TYPE}})
    SET(Geant4_CXX_FLAGS ${Geant4_Flags})

    #Geant4_DEFINITIONS already include -D, we jave to get rid of that so we can join things when creating dictionaries
    SET(G4_DEF_TEMP "")
    foreach(def ${Geant4_DEFINITIONS})
      string(REPLACE "-D" "" def ${def})
      LIST(APPEND G4_DEF_TEMP ${def})
    endforeach()
    SET(Geant4_DEFINITIONS ${G4_DEF_TEMP})
    UNSET(G4_DEF_TEMP)

    #get_filename_component(Geant4_LOCATION ${Geant4_INCLUDE_DIRS} DIRECTORY)
    #SET(Geant4_LOCATION "/cvmfs/ilc.desy.de/sw/x86_64_gcc49_sl6/geant4/10.03.p02/lib64")

    ADD_LIBRARY(Geant4::Interface INTERFACE IMPORTED GLOBAL)

    SET_TARGET_PROPERTIES(Geant4::Interface
      PROPERTIES
      INTERFACE_COMPILE_OPTIONS "${Geant4_CXX_FLAGS}"
      INTERFACE_COMPILE_DEFINITIONS "${Geant4_DEFINITIONS}"
      INTERFACE_INCLUDE_DIRECTORIES "${Geant4_INCLUDE_DIRS}"
      )

    IF(CLHEP)
      MESSAGE(STATUS "Adding CLHEP to Geant4::Interface Dependencies")
      TARGET_LINK_LIBRARIES(Geant4::Interface INTERFACE ${CLHEP})
    ENDIF()

    #Geant4_LIBRARIES are imported targets, we just add them all to our own interface library for convenience
    #Geant4 Libraries to not (yet) use a namespace
    foreach(LIB ${Geant4_LIBRARIES})
      #ADD_LIBRARY(Geant4::${LIB} SHARED IMPORTED GLOBAL)
      # MESSAGE(STATUS "Geant4 lib location ${LIB} ${G4_LIB_TEMP_${LIB}}")
      # SET_TARGET_PROPERTIES(Geant4::${LIB}
      #   PROPERTIES
      #   INTERFACE_COMPILE_OPTIONS "${Geant4_CXX_FLAGS}"
      #   INTERFACE_COMPILE_DEFINITIONS "${Geant4_DEFINITIONS}"
      #   INTERFACE_INCLUDE_DIRECTORIES "${Geant4_INCLUDE_DIRS}"
      #   IMPORTED_LOCATION ${G4_LIB_TEMP_${LIB}}
      #   )
      TARGET_LINK_LIBRARIES(Geant4::Interface INTERFACE ${LIB})
    endforeach()

    MESSAGE(STATUS "Geant4 Libraries ${Geant4_LIBRARIES};${Geant4_COMPONENT_LIBRARIES}")
    MESSAGE(STATUS "Geant4 Location ${Geant4_LOCATION}")
    MESSAGE(STATUS "Geant4 Defintitions ${Geant4_DEFINITIONS}")
    MESSAGE(STATUS "Geant4 CXX_FLAGS ${Geant4_CXX_FLAGS}")
    MESSAGE(STATUS "Geant4 INCL DIRS ${Geant4_INCLUDE_DIRS}")
    MESSAGE(STATUS "Geant4_VERSION: ${Geant4_VERSION}" )

  ENDIF()
Andre Sailer's avatar
Andre Sailer committed
ENDMACRO()

MACRO(DD4HEP_SETUP_LCIO_TARGETS)

  IF(NOT TARGET LCIO::LCIO)
    ADD_LIBRARY(LCIO::LCIO INTERFACE GLOBAL)
    TARGET_LINK_LIBRARIES(LCIO::LCIO ${LCIO_LIBRARIES})
    TARGET_INLCUDE_DIRECTORIES(LCIO::LCIO INTERFACE ${LCIO_INCLUDE_DIRS})
  ENDIF()
ENDMACRO()