1 # ============================================================================ 2 # Copyright (c) 2011-2012 University of Pennsylvania 3 # Copyright (c) 2013-2014 Carnegie Mellon University 4 # Copyright (c) 2013-2016 Andreas Schuh 7 # See COPYING file for license information or visit 8 # https://cmake-basis.github.io/download.html#license 9 # ============================================================================ 11 ############################################################################## 12 # @file CommonTools.cmake 13 # @brief Definition of common CMake functions. 16 ############################################################################## 25 include (CMakeParseArguments)
28 ## @addtogroup CMakeUtilities 32 # ============================================================================ 34 # ============================================================================ 36 # ---------------------------------------------------------------------------- 37 ## @brief Overloaded find_package() command. 39 # This macro calls CMake's 40 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:find_package"> 41 # find_package()</a> command and converts obsolete all uppercase "<PKG>_<VAR>" 42 # variables to case-sensitive "<Pkg>_<VAR>" variables. 43 # It further ensures that the global variables CMAKE_FIND_LIBRARY_SUFFIXES 44 # and CMAKE_FIND_EXECUTABLE_SUFFIX are reset to the values they had before 45 # the call to find_package(). This is required if the "Find<Pkg>.cmake" module 46 # has modified these variables, but not restored their initial value. 51 # attention: find_package() can be recursive. Hence, use "stack
" to keep 52 # track of library suffixes. Further note that we need to 53 # maintain a list of lists, which is not supported by CMake. 55 list (APPEND _BASIS_FIND_EXECUTABLE_SUFFIX "${CMAKE_FIND_EXECUTABLE_SUFFIX}
") 56 _find_package(${ARGV}) 57 # map common uppercase <PKG>_* variables to case-preserving <Pkg>_* 58 string (TOUPPER "${ARGV0}
" _FP_ARGV0_U) 59 foreach (_FP_VAR IN ITEMS FOUND DIR USE_FILE 60 VERSION VERSION_STRING 61 VERSION_MAJOR VERSION_MINOR VERSION_SUBMINOR VERSION_PATCH 62 MAJOR_VERSION MINOR_VERSION SUBMINOR_VERSION PATCH_VERSION 63 INCLUDE_DIR INCLUDE_DIRS INCLUDE_PATH 64 LIBRARY_DIR LIBRARY_DIRS LIBRARY_PATH 65 EXECUTABLE COMPILER CONVERTER) 66 if (NOT ${ARGV0}_${_FP_VAR} AND DEFINED ${_FP_ARGV0_U}_${_FP_VAR}) 67 set (${ARGV0}_${_FP_VAR} "${${_FP_ARGV0_U}_${_FP_VAR}}
") 72 # restore CMAKE_FIND_LIBRARY_SUFFIXES 73 string (REGEX REPLACE ";?{([^}]*)}$
" "" _BASIS_FIND_LIBRARY_SUFFIXES "${_BASIS_FIND_LIBRARY_SUFFIXES}
") 74 set (CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_MATCH_1}
") 75 # restore CMAKE_FIND_EXECUTABLE_SUFFIX 76 list (LENGTH _BASIS_FIND_EXECUTABLE_SUFFIX _FP_LAST) 77 if (_FP_LAST GREATER 0) 78 math (EXPR _FP_LAST "${_FP_LAST} - 1
") 79 list (REMOVE_AT _BASIS_FIND_EXECUTABLE_SUFFIX ${_FP_LAST}) 84 # ---------------------------------------------------------------------------- 85 ## @brief Tokenize dependency specification. 87 # This function parses a dependency specification such as 88 # "ITK-4.1{TestKernel,IO}
" into the package name, i.e., ITK, the requested 89 # (minimum) package version(s), i.e., 4.1, and a list of package components, i.e., 90 # TestKernel and IO. A valid dependency specification must specify the package 91 # name of the dependency (case-sensitive). The version and components 92 # specification are optional. Note that the components specification may 93 # be separated by an arbitrary number of whitespace characters including 94 # newlines. The same applies to the specification of the components themselves. 95 # This allows one to format the dependency specification as follows, for example: 105 # @param [in] DEP Dependency specification, i.e., "<Pkg>[-<version>[|...]][{<Component1>[,...]}]
". 106 # @param [out] PKG Package name. 107 # @param [out] VER Package version(s). 108 # @param [out] CMP List of package components. 109 function (basis_tokenize_dependency DEP PKG VER CMP) 111 if (DEP MATCHES "^([^ ]+)[ \\n\\t]*{([^}]*)}$
") 112 set (DEP "${CMAKE_MATCH_1}
") 113 string (REPLACE ",
" ";
" COMPONENTS "${CMAKE_MATCH_2}
") 114 foreach (C IN LISTS COMPONENTS) 115 string (STRIP "${C}
" C) 116 list (APPEND CMPS ${C}) 119 if (DEP MATCHES "^(.*)-([0-9]+(\\.[0-9]+)?(\\.[0-9]+)?(\\|[0-9]+(\\.[0-9]+)?(\\.[0-9]+)?)*)$
") 120 string (REPLACE "|
" ";
" CMAKE_MATCH_2 "${CMAKE_MATCH_2}
") 121 set (${PKG} "${CMAKE_MATCH_1}
" PARENT_SCOPE) 122 set (${VER} "${CMAKE_MATCH_2}
" PARENT_SCOPE) 124 set (${PKG} "${DEP}
" PARENT_SCOPE) 125 set (${VER} "" PARENT_SCOPE) 127 set (${CMP} "${CMPS}
" PARENT_SCOPE) 130 ## @brief Get installation prefix given path of <PKG>Config directory 131 function (_basis_config_to_prefix_dir PKG PKG_DIR PREFIX) 134 if (PKG_DIR MATCHES "^(.*)/([^/]+)\\.(framework|app)(/|$)
") 135 set (${PREFIX} "${CMAKE_MATCH_1}/${CMAKE_MATCH_2}.${CMAKE_MATCH_3}
" PARENT_SCOPE) 139 string (REGEX REPLACE "/+(cmake|CMake)
2813 usr/bin/env +([^ ]+)")
2814 set (INTERPRETER "${CMAKE_MATCH_1}")
2815 elseif (FIRST_LINE MATCHES "^#! *([^ ]+)")
2816 set (INTERPRETER "${CMAKE_MATCH_1}")
2817 get_filename_component (INTERPRETER "${INTERPRETER}" NAME)
2821 if (INTERPRETER MATCHES "^(python|jython|perl|bash)$")
2822 string (TOUPPER "${INTERPRETER}" LANG)
2828 # ------------------------------------------------------------------------
2829 # determine language from further known extensions
2832 if (SOURCE_FILE MATCHES "\\.py(\\.in)?$")
2835 elseif (SOURCE_FILE MATCHES "\\.(pl|pm|t)(\\.in)?$")
2838 elseif (SOURCE_FILE MATCHES "\\.sh(\\.in)?$")
2841 elseif (SOURCE_FILE MATCHES "\\.bat(\\.in)?$")
2845 set (LANGUAGE_OUT "UNKNOWN")
2850 # ------------------------------------------------------------------------
2852 if (LANGUAGE_OUT AND NOT "^${LANG}$" STREQUAL "^${LANGUAGE_OUT}$")
2853 if (LANGUAGE_OUT MATCHES "CXX" AND LANG MATCHES "MATLAB")
2854 # MATLAB Compiler can handle this...
2855 elseif (LANGUAGE_OUT MATCHES "MATLAB" AND LANG MATCHES "CXX")
2856 set (LANG "MATLAB") # language stays MATLAB
2857 elseif (LANGUAGE_OUT MATCHES "PYTHON" AND LANG MATCHES "JYTHON")
2858 # Jython can deal with Python scripts/modules
2859 elseif (LANGUAGE_OUT MATCHES "JYTHON" AND LANG MATCHES "PYTHON")
2860 set (LANG "JYTHON") # language stays JYTHON
2863 set (LANGUAGE_OUT "AMBIGUOUS")
2868 # update current language
2869 set (LANGUAGE_OUT "${LANG}")
2875 set (${LANGUAGE} "${LANGUAGE_OUT}" PARENT_SCOPE)
2877 message (FATAL_ERROR "basis_get_source_language called without arguments!")
2881 # ----------------------------------------------------------------------------
2882 ## @brief Configure .in source files.
2884 # This function configures each source file in the given argument list with
2885 # a .in file name suffix and stores the configured file in the build tree
2886 # with the same relative directory as the template source file itself.
2887 # The first argument names the CMake variable of the list of configured
2888 # source files where each list item is the absolute file path of the
2889 # corresponding (configured) source file.
2891 # @param [out] LIST_NAME Name of output list.
2892 # @param [in] ARGN These arguments are parsed and the following
2893 # options recognized. All remaining arguments are
2894 # considered to be source file paths.
2896 # <table border="0">
2898 # @tp @b BINARY_DIRECTORY @endtp
2899 # <td>Explicitly specify directory in build tree where configured
2900 # source files should be written to.</td>
2903 # @tp @b KEEP_DOT_IN_SUFFIX @endtp
2904 # <td>By default, after a source file with the .in extension has been
2905 # configured, the .in suffix is removed from the file name.
2906 # This can be omitted by giving this option.</td>
2911 function (basis_configure_sources LIST_NAME)
2913 CMAKE_PARSE_ARGUMENTS (ARGN "KEEP_DOT_IN_SUFFIX" "BINARY_DIRECTORY" "" ${ARGN})
2915 # ensure that specified BINARY_DIRECTORY is inside build tree of project
2916 if (ARGN_BINARY_DIRECTORY)
2917 get_filename_component (_binpath "${ARGN_BINARY_DIRECTORY}" ABSOLUTE)
2918 file (RELATIVE_PATH _relpath "${PROJECT_BINARY_DIR}" "${_binpath}")
2919 if (_relpath MATCHES "^\\.\\./")
2920 message (FATAL_ERROR "Specified BINARY_DIRECTORY must be inside the build tree!")
2926 # configure source files
2927 set (CONFIGURED_SOURCES)
2928 foreach (SOURCE ${ARGN_UNPARSED_ARGUMENTS})
2929 # The .in suffix is optional, add it here if a .in file exists for this
2930 # source file, but only if the source file itself does not name an actually
2931 # existing source file.
2933 # If the source file path is relative, prefer possibly already configured
2934 # sources in build tree such as the test driver source file created by
2935 # create_test_sourcelist() or a manual use of configure_file().
2937 # Note: Make path absolute, otherwise EXISTS check will not work!
2938 if (NOT IS_ABSOLUTE "${SOURCE}")
2939 if (EXISTS "${CMAKE_CURRENT_BINARY_DIR}/${SOURCE}")
2940 set (SOURCE "${CMAKE_CURRENT_BINARY_DIR}/${SOURCE}")
2941 elseif (EXISTS "${CMAKE_CURRENT_BINARY_DIR}/${SOURCE}.in")
2942 set (SOURCE "${CMAKE_CURRENT_BINARY_DIR}/${SOURCE}.in")
2943 elseif (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE}")
2944 set (SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE}")
2945 elseif (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE}.in")
2946 set (SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE}.in")
2949 if (NOT EXISTS "${SOURCE}" AND EXISTS "${SOURCE}.in")
2950 set (SOURCE "${SOURCE}.in")
2953 # configure source file if filename ends in .in suffix
2954 if (SOURCE MATCHES "\\.in$")
2955 # if binary directory was given explicitly, use it
2956 if (ARGN_BINARY_DIRECTORY)
2957 get_filename_component (SOURCE_NAME "${SOURCE}" NAME)
2958 if (NOT ARGN_KEEP_DOT_IN_SUFFIX)
2959 string (REGEX REPLACE "\\.in$" "" SOURCE_NAME "${SOURCE_NAME}")
2961 set (CONFIGURED_SOURCE "${ARGN_BINARY_DIRECTORY}/${SOURCE_NAME}")
2964 # if source is in project's source tree use relative binary directory
2965 if ("^${SOURCE}$" STREQUAL "^${PROJECT_SOURCE_DIR}$")
2966 basis_get_relative_path (CONFIGURED_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}" "${SOURCE}")
2967 get_filename_component (CONFIGURED_SOURCE "${CMAKE_CURRENT_BINARY_DIR}/${CONFIGURED_SOURCE}" ABSOLUTE)
2968 if (NOT ARGN_KEEP_DOT_IN_SUFFIX)
2969 string (REGEX REPLACE "\\.in$" "" CONFIGURED_SOURCE "${CONFIGURED_SOURCE}")
2971 # otherwise, use current binary directory
2973 get_filename_component (SOURCE_NAME "${SOURCE}" NAME)
2974 if (NOT ARGN_KEEP_DOT_IN_SUFFIX)
2975 string (REGEX REPLACE "\\.in$" "" SOURCE_NAME "${SOURCE_NAME}")
2977 set (CONFIGURED_SOURCE "${CMAKE_CURRENT_BINARY_DIR}/${SOURCE_NAME}")
2980 # configure source file
2981 configure_file ("${SOURCE}" "${CONFIGURED_SOURCE}" @ONLY)
2983 message ("** Configured source file with .in extension")
2985 # otherwise, skip configuration of this source file
2987 set (CONFIGURED_SOURCE "${SOURCE}")
2989 message ("** Skipped configuration of source file")
2993 message ("** Source: ${SOURCE}")
2994 message ("** Configured source: ${CONFIGURED_SOURCE}")
2996 list (APPEND CONFIGURED_SOURCES "${CONFIGURED_SOURCE}")
2999 set (${LIST_NAME} "${CONFIGURED_SOURCES}" PARENT_SCOPE)
3002 # ----------------------------------------------------------------------------
3003 ## @brief Remove one blank line from top of string
3004 macro (basis_remove_blank_line STRVAR)
3005 if (${STRVAR} MATCHES "(^|(.*)\n)[ \t]*\n(.*)")
3006 set (${STRVAR} "${CMAKE_MATCH_1}${CMAKE_MATCH_3}")
3010 # ----------------------------------------------------------------------------
3011 ## @brief Configure and optionally compile script file.
3013 # This function is used to configure script files during the build. It is
3014 # called by the build script generated by basis_add_script_target() for each script
3015 # target. It is also used to configure the modules of the packages
3016 # implemented in supported scripting languages which are located in the
3017 # @c PROJECT_LIBRARY_DIR of the source tree.
3019 # In case of executable scripts, this function automatically prepends the
3020 # module search paths such that the modules of this software package are found
3021 # (and preferred in case of potential name conflicts with other packages).
3022 # Moreover, it adds (or replaces) the shebang directive on Unix such that the
3023 # configured interpreter version is used. On Windows, it converts the executable
3024 # script into a Windows Command instead which executes the proper interpreter
3025 # with the code section of the input script.
3027 # @param [in] INPUT Input script file.
3028 # @param [in] OUTPUT Configured output script file.
3029 # @param [in] ARGN Optional arguments:
3033 # @tp @b COMPILE @endtp
3034 # <td>Whether to compile module scripts if suitable, i.e., an intermediate
3035 # format exists for the specific scripting language. For example,
3036 # Python modules can be compiled.</td>
3038 # @tp @b CONFIGURATION name @endtp
3039 # <td>Name of build configuration.</td>
3042 # @tp @b COPYONLY @endtp
3043 # <td>Whether to only copy the script file without replacing CMake variables
3044 # within the file. This option is passed on to CMake's configure_file()
3045 # command used to configure the script file. By default, the option
3046 # \@ONLY is used instead.</td>
3049 # @tp @b EXECUTABLE @endtp
3050 # <td>Specifies that the given script file is an executable script and not a
3051 # module script. Otherwise, if this option is not given and the output
3052 # file name contains a file name extension, the given script file is
3053 # configured as module script. A script file with an output file name
3054 # that has no extension, is always considered to be an executable.</td>
3057 # @tp @b DIRECTORY dir @endtp
3058 # <td>Build tree directory of configured script. By default, the directory
3059 # of the output script file is used to set the @c __DIR__ variable
3060 # used to make absolute file paths relative to the configured build
3061 # tree script file in the script configuration file
3062 # (see basis_set_script_path()).
3065 # @tp @b DESTINATION dir @endtp
3066 # <td>Installation directory for configured script. If this option is given,
3067 # the @c BUILD_INSTALL_SCRIPT variable is set to @c TRUE before including
3068 # any specified script configuration files (see @p CONFIG_FILE option).
3069 # Moreover, the @c __DIR__ variable is set to the specified directory.
3070 # Otherwise, if this option is omitted, the @c BUILD_INSTALL_SCRIPT variable
3071 # is set to @c FALSE instead and @c __DIR__ is set to the directory of
3072 # the configured @p OUTPUT file. Note that the @c BUILD_INSTALL_SCRIPT and
3073 # @c __DIR__ variables are in particular used by basis_set_script_path()
3074 # to convert the given paths to paths relative to the location of the
3075 # configured/installed script.</td>
3078 # @tp @b CACHE_FILE file1 [file2...] @endtp
3079 # <td>List of CMake files with dump of variables which should be included
3080 # before configuring the script. The cache files can be generated using
3081 # the basis_dump_variables() function.</td>
3084 # @tp @b CONFIG_FILE file1 [file2...] @endtp
3085 # <td>List of script configuration files to include before the configuration
3086 # of the script. See also the documentation of the @p DESTINATION option.</td>
3089 # @tp @b LINK_DEPENDS dep1 [dep2...] @endtp
3090 # <td>List of "link" dependencies, i.e., modules and script/module libraries
3091 # required by this script. For executable scripts, the paths to these
3092 # modules/packages is added to the module search path. If the prefix
3093 # "relative " is given before a file path, it is made relative to the
3094 # output/installation directory of the script file. All given input paths
3095 # must be absolute, however, as the relative location depends on
3096 # whether the script will be installed, i.e., the @c DESTINATION
3097 # is specified, or not.</td>
3100 function (basis_configure_script INPUT OUTPUT)
3101 # rename arguments to avoid conflict with script configuration
3102 set (_INPUT_FILE "${INPUT}")
3103 set (_OUTPUT_FILE "${OUTPUT}")
3104 # --------------------------------------------------------------------------
3106 CMAKE_PARSE_ARGUMENTS (
3108 "COMPILE;COPYONLY;EXECUTABLE"
3109 "DIRECTORY;DESTINATION;LANGUAGE;CONFIGURATION"
3110 "CACHE_FILE;CONFIG_FILE;LINK_DEPENDS"
3113 if (ARGN_UNPARSED_ARGUMENTS)
3114 message (FATAL_ERROR "Unrecognized arguments given: ${ARGN_UNPARSED_ARGUMENTS}")
3116 if (NOT ARGN_LANGUAGE)
3117 basis_get_source_language (ARGN_LANGUAGE "${_INPUT_FILE}")
3119 # --------------------------------------------------------------------------
3120 # include cache files
3121 foreach (_F IN LISTS ARGN_CACHE_FILE)
3122 get_filename_component (_F "${_F}" ABSOLUTE)
3123 if (NOT EXISTS "${_F}")
3124 message (FATAL_ERROR "Cache file ${_F} does not exist!")
3128 # --------------------------------------------------------------------------
3129 # general variables for use in scripts and those intended for use in script
3130 # configurations. The __DIR__ is in particular used by basis_set_script_path()
3131 # to make absolute paths relative to the script file location
3132 if (ARGN_DESTINATION)
3133 if (NOT IS_ABSOLUTE "${ARGN_DESTINATION}")
3134 set (ARGN_DESTINATION "${CMAKE_INSTALL_PREFIX}/${ARGN_DESTINATION}")
3136 set (BUILD_INSTALL_SCRIPT TRUE)
3137 set (__DIR__ "${ARGN_DESTINATION}")
3139 set (BUILD_INSTALL_SCRIPT FALSE)
3141 if (NOT IS_ABSOLUTE "${ARGN_DIRECTORY}")
3142 message (FATAL_ERROR "Build tree script DIRECTORY must be an absolute path")
3144 set (__DIR__ "${ARGN_DIRECTORY}")
3145 string (REPLACE "$<${BASIS_GE_CONFIG}>" "${ARGN_CONFIGURATION}" __DIR__ "${__DIR__}")
3147 get_filename_component (__DIR__ "${_OUTPUT_FILE}" PATH)
3150 get_filename_component (__NAME__ "${_OUTPUT_FILE}" NAME)
3151 set (__FILE__ "${__DIR__}/${__NAME__}")
3152 set (__CONFIG__ "${ARGN_CONFIGURATION}")
3153 # --------------------------------------------------------------------------
3154 # replace $<CONFIG> (deprecated $<CONFIGURATION>) in paths of link dependencies
3155 string (REPLACE "$<${BASIS_GE_CONFIG}>" "${ARGN_CONFIGURATION}" ARGN_LINK_DEPENDS "${ARGN_LINK_DEPENDS}")
3156 # --------------------------------------------------------------------------
3157 # include script configuration files
3158 foreach (_F IN LISTS ARGN_CONFIG_FILE)
3159 get_filename_component (_F "${_F}" ABSOLUTE)
3160 if (NOT EXISTS "${_F}")
3161 message (FATAL_ERROR "Script configuration file ${_F} does not exist!")
3165 # --------------------------------------------------------------------------
3166 # configure executable script
3167 if (ARGN_EXECUTABLE)
3168 # Attention: Every line of code added/removed will introduce a mismatch
3169 # between error messages of the interpreter and the original
3170 # source file. To not confuse/mislead developers too much,
3171 # keep number of lines added/removed at a minimum or at least
3172 # try to balance the number of lines added and removed.
3173 # Moreover, blank lines can be used to insert code without
3174 # changing the number of source code lines.
3175 file (READ "${_INPUT_FILE}" SCRIPT)
3176 # (temporarily) remove existing shebang directive
3177 file (STRINGS "${_INPUT_FILE}" FIRST_LINE LIMIT_COUNT 1)
3178 if (FIRST_LINE MATCHES "^#!")
3179 basis_sanitize_for_regex (FIRST_LINE_RE "${FIRST_LINE}")
3180 string (REGEX REPLACE "^${FIRST_LINE_RE}\n?" "" SCRIPT "${SCRIPT}")
3181 set (SHEBANG "${FIRST_LINE}")
3183 # replace CMake variables used in script
3184 if (NOT ARGN_COPYONLY)
3185 string (CONFIGURE "${SCRIPT}" SCRIPT @ONLY)
3187 # add code to set module search path
3188 if (ARGN_LANGUAGE MATCHES "[JP]YTHON")
3189 if (ARGN_LINK_DEPENDS)
3190 set (PYTHON_CODE "import sys; import os.path; __dir__ = os.path.dirname(os.path.realpath(__file__))")
3191 list (REVERSE ARGN_LINK_DEPENDS)
3192 foreach (DIR ${ARGN_LINK_DEPENDS})
3193 if (DIR MATCHES "^relative +(.*)$")
3194 basis_get_relative_path (DIR "${__DIR__}" "${CMAKE_MATCH_1}")
3196 if (DIR MATCHES "\\.(py|class)$")
3197 get_filename_component (DIR "${DIR}" PATH)
3199 if (IS_ABSOLUTE "${DIR}")
3200 set (PYTHON_CODE "${PYTHON_CODE}; sys.path.insert(0, os.path.realpath('${DIR}'))")
3202 set (PYTHON_CODE "${PYTHON_CODE}; sys.path.insert(0, os.path.realpath(os.path.join(__dir__, '${DIR}')))")
3205 # insert extra Python code near top, but after any future statement
3206 # (http://docs.python.org/2/reference/simple_stmts.html#future)
3207 set (FUTURE_STATEMENTS)
3208 if (SCRIPT MATCHES "^(.*from[ \t]+__future__[ \t]+import[ \t]+[a-z_]+[^\n]*\n)(.*)$")
3209 set (FUTURE_STATEMENTS "${CMAKE_MATCH_1}")
3210 set (SCRIPT "${CMAKE_MATCH_2}")
3212 basis_remove_blank_line (SCRIPT) # remove a blank line therefore
3213 set (SCRIPT "${FUTURE_STATEMENTS}${PYTHON_CODE} # <-- added by BASIS\n${SCRIPT}")
3215 elseif (ARGN_LANGUAGE MATCHES "PERL")
3216 if (ARGN_LINK_DEPENDS)
3217 set (PERL_CODE "use Cwd qw(realpath); use File::Basename;")
3218 foreach (DIR ${ARGN_LINK_DEPENDS})
3219 if (DIR MATCHES "^relative +(.*)$")
3220 basis_get_relative_path (DIR "${__DIR__}" "${CMAKE_MATCH_1}")
3222 if (DIR MATCHES "\\.pm$")
3223 get_filename_component (DIR "${DIR}" PATH)
3225 if (IS_ABSOLUTE "${DIR}")
3226 set (PERL_CODE "${PERL_CODE} use lib '${DIR}';")
3228 set (PERL_CODE "${PERL_CODE} use lib dirname(realpath(__FILE__)) . '/${DIR}';")
3231 basis_remove_blank_line (SCRIPT) # remove a blank line therefore
3232 set (SCRIPT "${PERL_CODE} # <-- added by BASIS\n${SCRIPT}")
3234 elseif (ARGN_LANGUAGE MATCHES "BASH")
3235 basis_library_prefix (PREFIX BASH)
3236 # In case of Bash, set BASIS_BASH_UTILITIES which is required to first source the
3237 # BASIS utilities modules (in particular core.sh). This variable should be set to
3238 # the utilities.sh module of BASIS by default as part of the BASIS installation
3239 # (environment variable) and is here set to the project-specific basis.sh module.
3241 # Note that folks at SBIA may submit a Bash script directly to a batch queuing
3242 # system such as the Oracle Grid Engine (SGE) instead of writing a separate submit
3243 # script. To avoid not finding the BASIS utilities in this case only because the
3244 # Bash file was copied by SGE to a temporary file, consider the <PROJECT>_DIR
3245 # environment variable as an alternative.
3247 # Note: Code formatted such that it can be on single line. Use no comments within!
3248 "__FILE__=\"$(cd -P -- \"$(dirname -- \"$BASH_SOURCE\")\" && pwd -P)/$(basename -- \"$BASH_SOURCE\")\"
3249 if [[ -n \"$SGE_ROOT\" ]] && [[ $__FILE__ =~ $SGE_ROOT/.* ]] && [[ -n \"\${${PROJECT_NAME}_DIR}\" ]] && [[ -f \"\${${PROJECT_NAME}_DIR}/bin/${__NAME__}\" ]]
3250 then __FILE__=\"\${${PROJECT_NAME}_DIR}/bin/${__NAME__}\"
3254 while [[ -h \"$lnk\" ]] && [[ $i -lt 100 ]]
3255 do dir=`dirname -- \"$lnk\"`
3256 lnk=`readlink -- \"$lnk\"`
3257 lnk=`cd \"$dir\" && cd $(dirname -- \"$lnk\") && pwd`/`basename -- \"$lnk\"`
3260 [[ $i -lt 100 ]] && __FILE__=\"$lnk\"
3262 __DIR__=\"$(dirname -- \"$__FILE__\")\"
3263 BASIS_BASH_UTILITIES=\"$__DIR__/${BASH_LIBRARY_DIR}/${PREFIX}basis.sh\""
3265 string (REPLACE "\n" "; " BASH_CODE "${BASH_CODE}")
3266 # set BASHPATH which is used by import() function provided by core.sh module of BASIS
3268 foreach (DIR ${ARGN_LINK_DEPENDS})
3269 if (DIR MATCHES "^relative +(.*)$")
3270 basis_get_relative_path (DIR "${__DIR__}" "${CMAKE_MATCH_1}")
3272 if (DIR MATCHES "\\.sh$")
3273 get_filename_component (DIR "${DIR}" PATH)
3275 if (IS_ABSOLUTE "${DIR}")
3276 list (APPEND BASHPATH "${DIR}")
3278 list (APPEND BASHPATH "$__DIR__/${DIR}")
3282 list (REMOVE_DUPLICATES BASHPATH)
3283 list (APPEND BASHPATH "$BASHPATH")
3284 basis_list_to_delimited_string (BASHPATH ":" NOAUTOQUOTE ${BASHPATH})
3285 set (BASH_CODE "${BASH_CODE}; BASHPATH=\"${BASHPATH}\"")
3287 basis_remove_blank_line (SCRIPT) # remove a blank line therefore
3288 set (SCRIPT "${BASH_CODE} # <-- added by BASIS\n${SCRIPT}")
3290 # replace shebang directive
3291 if (PYTHON_EXECUTABLE AND ARGN_LANGUAGE MATCHES "PYTHON")
3293 set (SHEBANG "@setlocal enableextensions & \"${PYTHON_EXECUTABLE}\" -x \"%~f0\" %* & goto :EOF")
3295 set (SHEBANG "#! ${PYTHON_EXECUTABLE}")
3297 elseif (JYTHON_EXECUTABLE AND ARGN_LANGUAGE MATCHES "JYTHON")
3299 set (SHEBANG "@setlocal enableextensions & \"${JYTHON_EXECUTABLE}\" -x \"%~f0\" %* & goto :EOF")
3301 # Attention: It is IMPORTANT to not use "#! <interpreter>" even if the <interpreter>
3302 # is given as full path in case of jython. Otherwise, the Jython executable
3303 # fails to execute from within a Python script using the os.system(),
3304 # subprocess.popen(), subprocess.call() or similar function!
3305 # Don't ask me for an explanation, but possibly the used shell otherwise does
3306 # not recognize the shebang as being valid. Using /usr/bin/env helps out here,
3308 set (SHEBANG "#! /usr/bin/env ${JYTHON_EXECUTABLE}")
3310 elseif (PERL_EXECUTABLE AND ARGN_LANGUAGE MATCHES "PERL")
3312 set (SHEBANG "@goto = \"START_OF_BATCH\" ;\n@goto = ();")
3313 set (SCRIPT "${SCRIPT}\n\n__END__\n\n:\"START_OF_BATCH\"\n@\"${PERL_EXECUTABLE}\" -w -S \"%~f0\" %*")
3315 set (SHEBANG "#! ${PERL_EXECUTABLE} -w")
3317 elseif (BASH_EXECUTABLE AND ARGN_LANGUAGE MATCHES "BASH")
3318 set (SHEBANG "#! ${BASH_EXECUTABLE}")
3320 # add (modified) shebang directive again
3322 set (SCRIPT "${SHEBANG}\n${SCRIPT}")
3324 # write configured script
3325 file (WRITE "${_OUTPUT_FILE}" "${SCRIPT}")
3326 # make script executable on Unix
3327 if (UNIX AND NOT ARGN_DESTINATION)
3328 execute_process (COMMAND /bin/chmod +x "${_OUTPUT_FILE}")
3330 # --------------------------------------------------------------------------
3331 # configure module script
3333 # configure module - do not use configure_file() as it will not update the
3334 # file if nothing has changed. the update of the modification
3335 # time is however in particular required for the
3336 # configure_script.cmake build command which uses this
3337 # function to build script targets. otherwise, the custom
3338 # build command is reexecuted only because the output files
3339 # never appear to be more recent than the dependencies
3340 file (READ "${_INPUT_FILE}" SCRIPT)
3341 if (NOT ARGN_COPYONLY)
3342 string (CONFIGURE "${SCRIPT}" SCRIPT @ONLY)
3344 file (WRITE "${_OUTPUT_FILE}" "${SCRIPT}")
3345 # compile module if requested
3347 if (ARGN_LANGUAGE MATCHES "PYTHON" AND PYTHON_EXECUTABLE)
3348 basis_get_compiled_file (CFILE "${_OUTPUT_FILE}" PYTHON)
3349 execute_process (COMMAND "${PYTHON_EXECUTABLE}" -E -c "import py_compile; py_compile.compile('${_OUTPUT_FILE}', '${CFILE}')")
3350 basis_compile_python_modules_for_jython (RV)
3352 basis_get_compiled_jython_file_of_python_module (CFILE "${_OUTPUT_FILE}")
3353 get_filename_component (CDIR "${CFILE}" PATH)
3354 file (MAKE_DIRECTORY "${CDIR}")
3355 execute_process (COMMAND "${JYTHON_EXECUTABLE}" -c "import py_compile; py_compile.compile('${_OUTPUT_FILE}', '${CFILE}')")
3357 elseif (ARGN_LANGUAGE MATCHES "JYTHON" AND JYTHON_EXECUTABLE)
3358 basis_get_compiled_file (CFILE "${_OUTPUT_FILE}" JYTHON)
3359 execute_process (COMMAND "${JYTHON_EXECUTABLE}" -c "import py_compile; py_compile.compile('${_OUTPUT_FILE}', '${CFILE}')")
3365 # ----------------------------------------------------------------------------
3366 ## @brief Get type name of target.
3368 # @param [out] TYPE The target's type name or NOTFOUND.
3369 # @param [in] TARGET_UID The UID of the target.
3370 function (_basis_get_target_type TYPE TARGET_UID)
3371 get_target_property (IMPORTED ${TARGET_UID} IMPORTED)
3373 get_target_property (TYPE_OUT ${TARGET_UID} TYPE)
3375 get_target_property (TYPE_OUT ${TARGET_UID} BASIS_TYPE)
3377 get_target_property (TYPE_OUT ${TARGET_UID} TYPE)
3380 set ("${TYPE}" "${TYPE_OUT}" PARENT_SCOPE)
3383 # ----------------------------------------------------------------------------
3384 ## @brief Get type name of target.
3386 # @param [out] TYPE The target's type name or NOTFOUND.
3387 # @param [in] TARGET_NAME The name of the target.
3388 function (basis_get_target_type TYPE TARGET_NAME)
3389 basis_get_target_uid (TARGET_UID "${TARGET_NAME}")
3390 if (TARGET ${TARGET_UID})
3391 _basis_get_target_type(TYPE_OUT ${TARGET_UID})
3393 set (TYPE_OUT "NOTFOUND")
3395 set ("${TYPE}" "${TYPE_OUT}" PARENT_SCOPE)
3398 # ----------------------------------------------------------------------------
3399 ## @brief Get location of build target output file(s).
3401 # This convenience function can be used to get the full path of the output
3402 # file(s) generated by a given build target. It is similar to the read-only
3403 # @c LOCATION property of CMake targets and should be used instead of
3404 # reading this porperty. In case of scripted libraries, this function returns
3405 # the path of the root directory of the library that has to be added to the
3406 # module search path.
3408 # @note If the target is a binary built from C++ source files and the CMake
3409 # generator is an IDE such as Visual Studio or Xcode, the absolute
3410 # directory of the target location ends with the generator expression
3411 # "/$<${BASIS_GE_CONFIG}>" which is to be substituted by the respective
3412 # build configuration.
3414 # @param [out] VAR Path of build target output file.
3415 # @param [in] TARGET_NAME Name of build target.
3416 # @param [in] PART Which file name component of the @c LOCATION
3417 # property to return. See get_filename_component().
3418 # If POST_INSTALL_RELATIVE is given as argument,
3419 # @p VAR is set to the path of the installed file
3420 # relative to the installation prefix. Similarly,
3421 # POST_INSTALL sets @p VAR to the absolute path
3422 # of the installed file post installation.
3424 # @returns Path of output file similar to @c LOCATION property of CMake targets.
3426 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#prop_tgt:LOCATION
3427 function (basis_get_target_location VAR TARGET_NAME PART)
3428 basis_get_target_uid (TARGET_UID "${TARGET_NAME}")
3429 if (TARGET "${TARGET_UID}")
3430 _basis_get_target_name (TARGET_NAME "${TARGET_UID}")
3431 _basis_get_target_type (TYPE "${TARGET_UID}")
3432 get_target_property (IMPORTED ${TARGET_UID} IMPORTED)
3433 # ------------------------------------------------------------------------
3436 # Note: This might not be required though as even custom executable
3437 # and library targets can be imported using CMake's
3438 # add_executable(<NAME> IMPORTED) and add_library(<NAME> <TYPE> IMPORTED)
3439 # commands. Such executable can, for example, also be a BASH
3440 # script built by basis_add_script().
3442 # 1. Try IMPORTED_LOCATION_<CMAKE_BUILD_TYPE>
3443 if (CMAKE_BUILD_TYPE)
3444 string (TOUPPER "${CMAKE_BUILD_TYPE}" U)
3448 get_target_property (LOCATION ${TARGET_UID} IMPORTED_LOCATION_${U})
3449 # 2. Try IMPORTED_LOCATION
3451 get_target_property (LOCATION ${TARGET_UID} IMPORTED_LOCATION)
3453 # 3. Prefer Release over all other configurations
3455 get_target_property (LOCATION ${TARGET_UID} IMPORTED_LOCATION_RELEASE)
3457 # 4. Just use any of the imported configurations
3459 get_property (CONFIGS TARGET ${TARGET_UID} PROPERTY IMPORTED_CONFIGURATIONS)
3460 foreach (C IN LISTS CONFIGS)
3461 string (TOUPPER "${C}" C)
3462 get_target_property (LOCATION ${TARGET_UID} IMPORTED_LOCATION_${C})
3468 # make path relative to CMAKE_INSTALL_PREFIX if POST_INSTALL_RELATIVE given
3469 if (LOCATION AND ARGV2 MATCHES "POST_INSTALL_RELATIVE")
3470 file (RELATIVE_PATH LOCATION "${CMAKE_INSTALL_PREFIX}" "${LOCATION}")
3472 # ------------------------------------------------------------------------
3473 # non-imported targets
3475 # Attention: The order of the matches/if cases matters here!
3476 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3478 if (TYPE MATCHES "^SCRIPT_(EXECUTABLE|MODULE)$")
3479 if (PART MATCHES "POST_INSTALL")
3480 get_target_property (DIRECTORY ${TARGET_UID} INSTALL_DIRECTORY)
3482 get_target_property (DIRECTORY ${TARGET_UID} OUTPUT_DIRECTORY)
3483 if (DIRECTORY AND CMAKE_GENERATOR MATCHES "Visual Studio|Xcode")
3484 set (DIRECTORY "${DIRECTORY}/$<${BASIS_GE_CONFIG}>")
3487 get_target_property (FNAME ${TARGET_UID} OUTPUT_NAME)
3488 elseif (TYPE STREQUAL "^SCRIPT_MODULE$")
3489 if (PART MATCHES "POST_INSTALL")
3490 get_target_property (DIRECTORY ${TARGET_UID} INSTALL_DIRECTORY)
3492 get_target_property (COMPILE ${TARGET_UID} COMPILE)
3493 get_target_property (DIRECTORY ${TARGET_UID} OUTPUT_DIRECTORY)
3494 if (DIRECTORY AND (COMPILE OR CMAKE_GENERATOR MATCHES "Visual Studio|Xcode"))
3495 set (DIRECTORY "${DIRECTORY}/$<${BASIS_GE_CONFIG}>")
3498 get_target_property (FNAME ${TARGET_UID} OUTPUT_NAME)
3499 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3501 elseif (TYPE MATCHES "LIBRARY|MODULE|MEX")
3502 if (TYPE MATCHES "STATIC")
3503 if (PART MATCHES "POST_INSTALL")
3504 get_target_property (DIRECTORY ${TARGET_UID} ARCHIVE_INSTALL_DIRECTORY)
3506 get_target_property (DIRECTORY ${TARGET_UID} ARCHIVE_OUTPUT_DIRECTORY)
3508 get_target_property (FNAME ${TARGET_UID} ARCHIVE_OUTPUT_NAME)
3510 if (PART MATCHES "POST_INSTALL")
3511 get_target_property (DIRECTORY ${TARGET_UID} LIBRARY_INSTALL_DIRECTORY)
3513 get_target_property (DIRECTORY ${TARGET_UID} LIBRARY_OUTPUT_DIRECTORY)
3515 get_target_property (FNAME ${TARGET_UID} LIBRARY_OUTPUT_NAME)
3517 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3520 if (PART MATCHES "POST_INSTALL")
3521 get_target_property (DIRECTORY ${TARGET_UID} RUNTIME_INSTALL_DIRECTORY)
3523 get_target_property (DIRECTORY ${TARGET_UID} RUNTIME_OUTPUT_DIRECTORY)
3525 get_target_property (FNAME ${TARGET_UID} RUNTIME_OUTPUT_NAME)
3527 if (DIRECTORY MATCHES "NOTFOUND")
3528 message (FATAL_ERROR "Failed to get directory of ${TYPE} ${TARGET_UID}!"
3529 " Check implementation of basis_get_target_location()"
3530 " and make sure that the required *INSTALL_DIRECTORY"
3531 " property is set on the target!")
3534 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3535 # get output name of built file (if applicable)
3537 get_target_property (FNAME ${TARGET_UID} OUTPUT_NAME)
3539 if (NOT "^${TYPE}$" STREQUAL "^SCRIPT_LIBRARY$")
3540 get_target_property (PREFIX ${TARGET_UID} PREFIX)
3541 get_target_property (SUFFIX ${TARGET_UID} SUFFIX)
3543 set (TARGET_FILE "${FNAME}")
3545 set (TARGET_FILE "${TARGET_NAME}")
3548 set (TARGET_FILE "${PREFIX}${TARGET_FILE}")
3551 set (TARGET_FILE "${TARGET_FILE}${SUFFIX}")
3552 elseif (WIN32 AND "^${TYPE}$" STREQUAL "^EXECUTABLE$")
3553 set (TARGET_FILE "${TARGET_FILE}.exe")
3556 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3557 # prepend $<CONFIG> "generator expression" for non-custom binaries
3558 # when built with an IDE such as Visual Studio or Xcode
3559 if ("^${TYPE}$" STREQUAL "^EXECUTABLE$" OR "^${TYPE}$" STREQUAL "^LIBRARY$")
3560 if (NOT PART MATCHES "INSTALL")
3561 if (CMAKE_GENERATOR MATCHES "Visual Studio|Xcode")
3562 set (DIRECTORY "${DIRECTORY}/$<${BASIS_GE_CONFIG}>")
3566 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3567 # assemble final path
3568 if (PART MATCHES "POST_INSTALL_RELATIVE")
3569 if (IS_ABSOLUTE "${DIRECTORY}")
3570 file (RELATIVE_PATH DIRECTORY "${CMAKE_INSTALL_PREFIX}" "${DIRECTORY}")
3575 elseif (PART MATCHES "POST_INSTALL")
3576 if (NOT IS_ABSOLUTE "${DIRECTORY}")
3577 set (DIRECTORY "${CMAKE_INSTALL_PREFIX}/${DIRECTORY}")
3581 set (LOCATION "${DIRECTORY}/${TARGET_FILE}")
3583 set (LOCATION "${DIRECTORY}")
3586 set (LOCATION "${DIRECTORY}")
3589 # get filename component
3590 if (LOCATION AND PART MATCHES "(^|_)(PATH|NAME|NAME_WE)$")
3591 get_filename_component (LOCATION "${LOCATION}" "${CMAKE_MATCH_2}")
3594 message (FATAL_ERROR "basis_get_target_location(): Unknown target ${TARGET_UID}")
3597 set ("${VAR}" "${LOCATION}" PARENT_SCOPE)
3600 # ----------------------------------------------------------------------------
3601 ## @brief Get link libraries/dependencies of (imported) target.
3603 # This function recursively adds the dependencies of the dependencies as well
3604 # and returns them together with the list of the direct link dependencies.
3605 # Moreover, for script targets, if any of the dependencies uses the BASIS
3606 # utilities for the given language (@c BASIS_UTILITIES property), the
3607 # corresponding utilities library is added to the list of dependencies.
3608 # Note that therefore the BASIS utilities targets have to be added already,
3609 # which is only the case during the finalization of script targets.
3611 # @param [out] LINK_DEPENDS List of all link dependencies. In case of scripts,
3612 # the dependencies are the required modules or
3613 # paths to required packages, respectively.
3614 # @param [in] TARGET_NAME Name of the target.
3615 function (basis_get_target_link_libraries LINK_DEPENDS TARGET_NAME)
3616 basis_get_target_uid (TARGET_UID "${TARGET_NAME}")
3617 if (NOT TARGET "${TARGET_UID}")
3618 message (FATAL_ERROR "basis_get_target_link_libraries(): Unknown target: ${TARGET_UID}")
3620 if (BASIS_DEBUG AND BASIS_VERBOSE)
3621 message ("** basis_get_target_link_libraries():")
3622 message ("** TARGET_NAME: ${TARGET_NAME}")
3623 message ("** CURRENT_DEPENDS: ${ARGN}")
3625 # get type of target
3626 get_target_property (BASIS_TYPE ${TARGET_UID} BASIS_TYPE)
3627 # get direct link dependencies of target
3628 get_target_property (IMPORTED ${TARGET_UID} IMPORTED)
3630 # 1. Try IMPORTED_LINK_INTERFACE_LIBRARIES_<CMAKE_BUILD_TYPE>
3631 if (CMAKE_BUILD_TYPE)
3632 string (TOUPPER "${CMAKE_BUILD_TYPE}" U)
3636 get_target_property (DEPENDS ${TARGET_UID} "IMPORTED_LINK_INTERFACE_LIBRARIES_${U}")
3637 # 2. Try IMPORTED_LINK_INTERFACE_LIBRARIES
3639 get_target_property (DEPENDS ${TARGET_UID} "IMPORTED_LINK_INTERFACE_LIBRARIES")
3641 # 3. Prefer Release over all other configurations
3643 get_target_property (DEPENDS ${TARGET_UID} "IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE")
3645 # 4. Just use any of the imported configurations
3647 get_property (CONFIGS TARGET "${TARGET_UID}" PROPERTY IMPORTED_CONFIGURATIONS)
3648 foreach (C IN LISTS CONFIGS)
3649 get_target_property (DEPENDS ${TARGET_UID} "IMPORTED_LINK_INTERFACE_LIBRARIES_${C}")
3655 # otherwise, get LINK_DEPENDS property value
3656 elseif (BASIS_TYPE MATCHES "^EXECUTABLE$|^(SHARED|STATIC|MODULE)_LIBRARY$")
3657 get_target_property (DEPENDS ${TARGET_UID} BASIS_LINK_DEPENDS)
3659 get_target_property (DEPENDS ${TARGET_UID} LINK_DEPENDS)
3664 # prepend BASIS utilities if used (and added)
3665 if (BASIS_TYPE MATCHES "SCRIPT")
3666 set (BASIS_UTILITIES_TARGETS)
3667 foreach (UID IN ITEMS ${TARGET_UID} ${DEPENDS})
3668 if (TARGET "${UID}")
3669 get_target_property (BASIS_UTILITIES ${UID} BASIS_UTILITIES)
3670 get_target_property (LANGUAGE ${UID} LANGUAGE)
3671 if (BASIS_UTILITIES)
3672 set (BASIS_UTILITIES_TARGET)
3673 if (LANGUAGE MATCHES "[JP]YTHON")
3674 basis_get_source_target_name (BASIS_UTILITIES_TARGET "basis.py" NAME)
3675 elseif (LANGUAGE MATCHES "PERL")
3676 basis_get_source_target_name (BASIS_UTILITIES_TARGET "Basis.pm" NAME)
3677 elseif (LANGUAGE MATCHES "BASH")
3678 basis_get_source_target_name (BASIS_UTILITIES_TARGET "basis.sh" NAME)
3680 if (BASIS_UTILITIES_TARGET)
3681 basis_get_target_uid (BASIS_UTILITIES_TARGET ${BASIS_UTILITIES_TARGET})
3683 if (TARGET ${BASIS_UTILITIES_TARGET})
3684 list (APPEND BASIS_UTILITIES_TARGETS ${BASIS_UTILITIES_TARGET})
3689 if (BASIS_UTILITIES_TARGETS)
3690 list (INSERT DEPENDS 0 ${BASIS_UTILITIES_TARGETS})
3693 # convert target names to UIDs
3695 foreach (LIB IN LISTS DEPENDS)
3696 basis_get_target_uid (UID "${LIB}")
3698 list (APPEND _DEPENDS "${UID}")
3700 list (APPEND _DEPENDS "${LIB}")
3703 set (DEPENDS "${_DEPENDS}")
3705 # recursively add link dependencies of dependencies
3706 # TODO implement it non-recursively for better performance
3707 foreach (LIB IN LISTS DEPENDS)
3709 list (FIND ARGN "${LIB}" IDX) # avoid recursive loop
3711 basis_get_target_link_libraries (LIB_DEPENDS ${LIB} ${ARGN} ${DEPENDS})
3712 list (APPEND DEPENDS ${LIB_DEPENDS})
3716 # remove duplicate entries
3718 list (REMOVE_DUPLICATES DEPENDS)
3721 set (${LINK_DEPENDS} "${DEPENDS}" PARENT_SCOPE)
3724 # ============================================================================
3725 # generator expressions
3726 # ============================================================================
3728 # ----------------------------------------------------------------------------
3729 ## @brief Process generator expressions in arguments.
3731 # This command evaluates the $<TARGET_FILE:tgt> and related generator
3732 # expressions also for custom targets such as scripts and MATLAB Compiler
3733 # targets. For other generator expressions whose argument is a target name,
3734 # this function replaces the target name by the target UID, i.e., the actual
3735 # CMake target name such that the expression can be evaluated by CMake.
3736 # The following generator expressions are directly evaluated by this function:
3739 # @tp <b><tt>$<TARGET_FILE:tgt></tt></b> @endtp
3740 # <td>Absolute file path of built target.</td>
3743 # @tp <b><tt>$<TARGET_FILE_POST_INSTALL:tgt></tt></b> @endtp
3744 # <td>Absolute path of target file after installation using the
3745 # current @c CMAKE_INSTALL_PREFIX.</td>
3748 # @tp <b><tt>$<TARGET_FILE_POST_INSTALL_RELATIVE:tgt></tt></b> @endtp
3749 # <td>Path of target file after installation relative to @c CMAKE_INSTALL_PREFIX.</td>
3752 # Additionally, the suffix <tt>_NAME</tt> or <tt>_DIR</tt> can be appended
3753 # to the name of each of these generator expressions to get only the basename
3754 # of the target file including the extension or the corresponding directory
3755 # path, respectively.
3757 # Generator expressions are in particular supported by basis_add_test().
3759 # @param [out] ARGS Name of output list variable.
3760 # @param [in] ARGN List of arguments to process.
3762 # @sa basis_add_test()
3763 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_test
3764 function (basis_process_generator_expressions ARGS)
3766 foreach (ARG IN LISTS ARGN)
3767 string (REGEX MATCHALL "\\$<.*TARGET.*:.*>" EXPRS "${ARG}")
3768 foreach (EXPR IN LISTS EXPRS)
3769 if (EXPR MATCHES "\\$<(.*):(.*)>")
3770 set (EXPR_NAME "${CMAKE_MATCH_1}")
3771 set (TARGET_NAME "${CMAKE_MATCH_2}")
3772 # TARGET_FILE* expression, including custom targets
3773 if (EXPR_NAME MATCHES "^TARGET_FILE(.*)")
3774 if (NOT CMAKE_MATCH_1)
3775 set (CMAKE_MATCH_1 "ABSOLUTE")
3777 string (REGEX REPLACE "^_" "" PART "${CMAKE_MATCH_1}")
3778 basis_get_target_location (ARG "${TARGET_NAME}" ${PART})
3779 # other generator expression supported by CMake
3780 # only replace target name, but do not evaluate expression
3782 basis_get_target_uid (TARGET_UID "${CMAKE_MATCH_2}")
3783 string (REPLACE "${EXPR}" "$<${CMAKE_MATCH_1}:${TARGET_UID}>" ARG "${ARG}")
3785 if (BASIS_DEBUG AND BASIS_VERBOSE)
3786 message ("** basis_process_generator_expressions():")
3787 message ("** Expression: ${EXPR}")
3788 message ("** Keyword: ${EXPR_NAME}")
3789 message ("** Argument: ${TARGET_NAME}")
3790 message ("** Replaced by: ${ARG}")
3794 list (APPEND ARGS_OUT "${ARG}")
3796 set (${ARGS} "${ARGS_OUT}" PARENT_SCOPE)
3801 # @brief basis_append_to_each takes an input list and appends a single element to each item in that list and appends it to the output list.
3802 # For example, this is useful for adding relative paths to the end of a list of paths.
3804 # @param OUTPUT_LIST Name of list that will be filled with appended names.
3805 # @param INPUT_LIST Name of list that contains items to have text appended.
3806 # @param ITEM_TO_APPEND text to append to each item in the input list.
3808 function(basis_append_to_each OUTPUT_LIST INPUT_LIST ITEM_TO_APPEND)
3809 foreach(PATH IN LISTS ${INPUT_LIST})
3810 list(APPEND ${OUTPUT_LIST} ${PATH}${ITEM_TO_APPEND} )
3814 set(${OUTPUT_LIST} ${${OUTPUT_LIST}} PARENT_SCOPE)
3820 # end of Doxygen group
cmake CMAKE_FIND_LIBRARY_SUFFIXES
option BASIS_DEBUG
Request debugging messages from BASIS functions.
macro find_package()
Overloaded find_package() command.