Back to home page

EIC code displayed by LXR

 
 

    


Warning, /geant4/cmake/Modules/G4CMakeUtilities.cmake is written in an unsupported language. File is not indexed.

0001 #.rst:
0002 # G4CMakeUtilities
0003 # ----------------
0004 #
0005 # Extra functions and macros for encapsulating common tasks.
0006 #
0007 
0008 #-----------------------------------------------------------------
0009 # License and Disclaimer
0010 #
0011 # The  Geant4 software  is  copyright of the Copyright Holders  of
0012 # the Geant4 Collaboration.  It is provided  under  the terms  and
0013 # conditions of the Geant4 Software License,  included in the file
0014 # LICENSE and available at  http://cern.ch/geant4/license .  These
0015 # include a list of copyright holders.
0016 #
0017 # Neither the authors of this software system, nor their employing
0018 # institutes,nor the agencies providing financial support for this
0019 # work  make  any representation or  warranty, express or implied,
0020 # regarding  this  software system or assume any liability for its
0021 # use.  Please see the license in the file  LICENSE  and URL above
0022 # for the full disclaimer and the limitation of liability.
0023 #
0024 # This  code  implementation is the result of  the  scientific and
0025 # technical work of the GEANT4 collaboration.
0026 # By using,  copying,  modifying or  distributing the software (or
0027 # any work based  on the software)  you  agree  to acknowledge its
0028 # use  in  resulting  scientific  publications,  and indicate your
0029 # acceptance of all terms of the Geant4 Software license.
0030 #
0031 #-----------------------------------------------------------------
0032 
0033 if(NOT __G4CMAKEUTILITIES_INCLUDED)
0034   set(__G4CMAKEUTILITIES_INCLUDED TRUE)
0035 else()
0036   return()
0037 endif()
0038 
0039 #.rst:
0040 # Included Modules
0041 # ^^^^^^^^^^^^^^^^
0042 #
0043 # This module includes the following modules:
0044 include(CMakeDependentOption)
0045 
0046 #-----------------------------------------------------------------------
0047 # CMAKE EXTENSIONS
0048 #-----------------------------------------------------------------------
0049 # macro set_ifnot(<var> <value>)
0050 #       If variable var is not set, set its value to that provided
0051 #
0052 macro(set_ifnot _var _value)
0053   if(NOT ${_var})
0054     set(${_var} ${_value})
0055   endif()
0056 endmacro()
0057 
0058 #-----------------------------------------------------------------------
0059 # function enum_option(<option>
0060 #                      VALUES <value1> ... <valueN>
0061 #                      TYPE   <valuetype>
0062 #                      DOC    <docstring>
0063 #                      [DEFAULT <elem>]
0064 #                      [CASE_INSENSITIVE])
0065 #          Declare a cache variable <option> that can only take values
0066 #          listed in VALUES. TYPE may be FILEPATH, PATH or STRING.
0067 #          <docstring> should describe that option, and will appear in
0068 #          the interactive CMake interfaces. If DEFAULT is provided,
0069 #          <elem> will be taken as the zero-indexed element in VALUES
0070 #          to which the value of <option> should default to if not
0071 #          provided. Otherwise, the default is taken as the first
0072 #          entry in VALUES. If CASE_INSENSITIVE is present, then
0073 #          checks of the value of <option> against the allowed values
0074 #          will ignore the case when performing string comparison.
0075 #
0076 function(enum_option _var)
0077   set(options CASE_INSENSITIVE)
0078   set(oneValueArgs DOC TYPE DEFAULT)
0079   set(multiValueArgs VALUES)
0080   cmake_parse_arguments(_ENUMOP "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
0081 
0082   # - Validation as needed arguments
0083   if(NOT _ENUMOP_VALUES)
0084     message(FATAL_ERROR "enum_option must be called with non-empty VALUES\n(Called for enum_option '${_var}')")
0085   endif()
0086 
0087   # - Set argument defaults as needed
0088   if(_ENUMOP_CASE_INSENSITIVE)
0089     set(_ci_values )
0090     foreach(_elem ${_ENUMOP_VALUES})
0091       string(TOLOWER "${_elem}" _ci_elem)
0092       list(APPEND _ci_values "${_ci_elem}")
0093     endforeach()
0094     set(_ENUMOP_VALUES ${_ci_values})
0095   endif()
0096 
0097   set_ifnot(_ENUMOP_TYPE STRING)
0098   set_ifnot(_ENUMOP_DEFAULT 0)
0099   list(GET _ENUMOP_VALUES ${_ENUMOP_DEFAULT} _default)
0100 
0101   if(NOT DEFINED ${_var})
0102     set(${_var} ${_default} CACHE ${_ENUMOP_TYPE} "${_ENUMOP_DOC} (${_ENUMOP_VALUES})")
0103   else()
0104     set(_var_tmp ${${_var}})
0105     if(_ENUMOP_CASE_INSENSITIVE)
0106       string(TOLOWER ${_var_tmp} _var_tmp)
0107     endif()
0108 
0109     list(FIND _ENUMOP_VALUES ${_var_tmp} _elem)
0110     if(_elem LESS 0)
0111       message(FATAL_ERROR "Value '${${_var}}' for variable ${_var} is not allowed\nIt must be selected from the set: ${_ENUMOP_VALUES} (DEFAULT: ${_default})\n")
0112     else()
0113       # - convert to lowercase
0114       if(_ENUMOP_CASE_INSENSITIVE)
0115         set(${_var} ${_var_tmp} CACHE ${_ENUMOP_TYPE} "${_ENUMOP_DOC} (${_ENUMOP_VALUES})" FORCE)
0116       endif()
0117     endif()
0118   endif()
0119   set_property(CACHE ${_var} PROPERTY STRINGS ${_ENUMOP_VALUES})
0120 endfunction()
0121 
0122 #-----------------------------------------------------------------------
0123 # GENERAL GEANT4
0124 #-----------------------------------------------------------------------
0125 # function geant4_add_feature(<NAME> <DOCSTRING>)
0126 #          Add a Geant4 feature, whose activation is specified by the
0127 #          existence of the variable <NAME>, to the list of enabled/disabled
0128 #          features, plus a docstring describing the feature
0129 #
0130 function(geant4_add_feature _var _description)
0131   if(${_var})
0132     set_property(GLOBAL APPEND PROPERTY GEANT4_ENABLED_FEATURES ${_var})
0133   else()
0134     set_property(GLOBAL APPEND PROPERTY GEANT4_DISABLED_FEATURES ${_var})
0135   endif()
0136 
0137   # Property name qualified by "G4" prefix so we can provide seperate
0138   # descriptions for CMake builtins we might expose (e.g. CXX_STANDARD)
0139   set_property(GLOBAL PROPERTY G4_${_var}_DESCRIPTION "${_description}")
0140 endfunction()
0141 
0142 #-----------------------------------------------------------------------
0143 # function geant4_print_enabled_features()
0144 #          Print enabled Geant4 features plus their docstrings.
0145 #
0146 function(geant4_print_enabled_features)
0147   set(_currentFeatureText "The following Geant4 features are enabled:")
0148   get_property(_enabledFeatures GLOBAL PROPERTY GEANT4_ENABLED_FEATURES)
0149 
0150   foreach(_feature ${_enabledFeatures})
0151     set(_currentFeatureText "${_currentFeatureText}\n${_feature}")
0152 
0153     get_property(_desc GLOBAL PROPERTY G4_${_feature}_DESCRIPTION)
0154 
0155     if(_desc)
0156       set(_currentFeatureText "${_currentFeatureText}: ${_desc}")
0157       set(_desc NOTFOUND)
0158     endif(_desc)
0159   endforeach(_feature)
0160 
0161   message(STATUS "${_currentFeatureText}\n")
0162 endfunction()
0163 
0164 #-----------------------------------------------------------------------
0165 # GEANT4 DATASETS
0166 #-----------------------------------------------------------------------
0167 # function geant4_latest_version(<dir> <name> <output variable>)
0168 #          Locate latest version of dataset <name> in <dir>, setting value
0169 #          of output variable to the full path to the dataset
0170 #
0171 function(geant4_latest_version dir name var)
0172   file(GLOB files RELATIVE ${dir} ${dir}/${name}*)
0173   set(newer)
0174   foreach(file ${files})
0175     string(REPLACE ${name} "" version ${file})
0176     if("${version}" VERSION_GREATER "${newer}")
0177       set(newer ${version})
0178     endif()
0179   endforeach()
0180   set(${var} ${dir}/${name}${newer} PARENT_SCOPE)
0181 endfunction()
0182 
0183 #-----------------------------------------------------------------------
0184 # GEANT4 EXTERNAL PACKAGE HELPERS
0185 #-----------------------------------------------------------------------
0186 # function geant4_save_package_variables(<title> <var1> ... <varN>)
0187 #          Save variables <var1> ... <varN> under <title> for export to
0188 #          build-time package settings file.
0189 #
0190 function(geant4_save_package_variables _title)
0191   get_property(__ep_titles GLOBAL PROPERTY GEANT4_EXPORT_PACKAGE_TITLES)
0192   if(NOT (${_title} IN_LIST __ep_titles))
0193     set_property(GLOBAL APPEND PROPERTY GEANT4_EXPORT_PACKAGE_TITLES ${_title})
0194   endif()
0195 
0196   get_property(__exported_vars GLOBAL PROPERTY GEANT4_EXPORT_PACKAGE_${_title}_VARIABLES)
0197   foreach(__varname ${ARGN})
0198     if(NOT (${__varname} IN_LIST __exported_vars))
0199       # Some variables might be empty on certain systems. Only save those with a value
0200       if(${__varname})
0201         # TODO: Also check that the save variable is in the cache...
0202         # if(CACHE ...) only available from 3.14
0203         set_property(GLOBAL APPEND PROPERTY GEANT4_EXPORT_PACKAGE_${_title}_VARIABLES ${__varname})
0204       endif()
0205     endif()
0206   endforeach()
0207 endfunction()
0208 
0209 # function geant4_export_package_variables(<file>)
0210 #          Write saved package variables to <file>
0211 #
0212 function(geant4_export_package_variables _file)
0213   set(GEANT4_PACKAGE_SETTINGS )
0214   get_property(__g4_exports GLOBAL PROPERTY GEANT4_EXPORT_PACKAGE_TITLES)
0215 
0216   foreach(__pkg_title ${__g4_exports})
0217     set(__local_build_setting "\n# ${__pkg_title} Build Time Settings")
0218     get_property(__pkg_vars GLOBAL PROPERTY GEANT4_EXPORT_PACKAGE_${__pkg_title}_VARIABLES)
0219 
0220     foreach(__var ${__pkg_vars})
0221       get_property(__var_value CACHE ${__var} PROPERTY VALUE)
0222       get_property(__var_type CACHE ${__var} PROPERTY TYPE)
0223       get_property(__var_help CACHE ${__var} PROPERTY HELPSTRING)
0224       # Variable may not be in cache, only local (canonical case being EXPAT_LIBRARY since CMake 3.27)
0225       # We still need to account for these because they may be required to be in the CACHE at least set in
0226       # earlier versions.
0227       # 1. Variable may not be in cache, only local (canonical case being EXPAT_LIBRARY since CMake 3.27)
0228       #    We still need to account for these because they may be required to be in the CACHE at least set in
0229       #    earlier versions.
0230       # 2. Depending on CMake version, variable may be in cache but unitialized, here we want the local value
0231       if(((NOT __var_value) AND (NOT __var_type) AND (NOT __var_help)) OR (__var_type STREQUAL "UNINITIALIZED"))
0232         set(__var_value ${${__var}})
0233         # TODO: set type based on whether it looks like a bool or path, but PATH almost invariably what we save
0234         # Only important in cmake GUI and if value needs to be changed, which we don't if package cache is used
0235         set(__var_type PATH)
0236         set(__var_help "no documentation, not a cache value")
0237       endif()
0238 
0239       list(APPEND __local_build_setting "geant4_set_and_check_package_variable(${__var} \"${__var_value}\" ${__var_type} \"${__var_help}\")")
0240     endforeach()
0241 
0242     list(APPEND GEANT4_PACKAGE_SETTINGS ${__local_build_setting})
0243   endforeach()
0244 
0245   string(REPLACE ";" "\n" GEANT4_PACKAGE_SETTINGS "${GEANT4_PACKAGE_SETTINGS}")
0246 
0247   configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/Geant4PackageCache.cmake.in
0248     ${_file}
0249     @ONLY
0250     )
0251 endfunction()
0252 
0253 #-----------------------------------------------------------------------
0254 # GEANT4 TESTING
0255 #-----------------------------------------------------------------------
0256 # function geant4_add_unit_tests(test1 test2 ... [dir1 ...]
0257 #                                INCLUDE_DIRS dir1 dir2 ...
0258 #                                LIBRARIES library1 library2 ...)
0259 #
0260 function(geant4_add_unit_tests)
0261   cmake_parse_arguments(ARG "" "" "INCLUDE_DIRS;LIBRARIES" ${ARGN})
0262 
0263   foreach(incdir ${ARG_INCLUDE_DIRS})
0264     if(IS_ABSOLUTE ${incdir})
0265       include_directories(${incdir})
0266     else()
0267       include_directories(${PROJECT_SOURCE_DIR}/source/${incdir})
0268     endif()
0269   endforeach()
0270 
0271   if(ARG_UNPARSED_ARGUMENTS)
0272     set(tnames ${ARG_UNPARSED_ARGUMENTS})
0273   else()
0274     set(tnames test*.cc)
0275   endif()
0276 
0277   set(alltests)
0278   foreach(tname ${tnames})
0279     if(tname STREQUAL ".")
0280       set(tests ".")
0281     else()
0282       file(GLOB tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${tname})
0283     endif()
0284     set(alltests ${alltests} ${tests})
0285   endforeach()
0286 
0287   if(NOT TARGET tests)
0288     add_custom_target(tests)
0289   endif()
0290 
0291   foreach(test ${alltests})
0292     if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${test})
0293       file(GLOB sources ${test}/src/*.cc)
0294       include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/${test}/include)
0295       file(GLOB test ${test}/*.cc)
0296     else()
0297       set(sources)
0298     endif()
0299     get_filename_component(name ${test} NAME_WE)
0300     add_executable(${name} EXCLUDE_FROM_ALL ${test} ${sources})
0301     target_link_libraries(${name} ${ARG_LIBRARIES})
0302     set_target_properties(${name} PROPERTIES OUTPUT_NAME ${name})
0303     add_dependencies(tests ${name})
0304     add_test(NAME ${name} COMMAND ${name})
0305     set_property(TEST ${name} PROPERTY LABELS UnitTests)
0306     set_property(TEST ${name} PROPERTY TIMEOUT 60)
0307   endforeach()
0308 endfunction()