BASIS  version 1.2.3 (revision 2104)
UtilitiesTools.cmake
Go to the documentation of this file.
00001 ##############################################################################
00002 # @file  UtilitiesTools.cmake
00003 # @brief CMake functions used to configure auxiliary source files.
00004 #
00005 # Copyright (c) 2011, 2012 University of Pennsylvania. All rights reserved.<br />
00006 # See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file.
00007 #
00008 # Contact: SBIA Group <sbia-software at uphs.upenn.edu>
00009 #
00010 # @ingroup CMakeTools
00011 ##############################################################################
00012 
00013 ## @addtogroup CMakeUtilities
00014 #  @{
00015 
00016 
00017 # ============================================================================
00018 # Python utilities
00019 # ============================================================================
00020 
00021 # ----------------------------------------------------------------------------
00022 ## @brief Include BASIS utilities for Python.
00023 #
00024 # The substituted Python code appends the root directory of the build or
00025 # installed Python modules to the search path and then imports the 'basis'
00026 # module of this project. Note that every BASIS project has its own 'basis'
00027 # module, which belong to different packages, however.
00028 #
00029 # Example:
00030 # @code
00031 # #! /usr/bin/env python
00032 # @BASIS_PYTHON_UTILITIES@
00033 # ...
00034 # @endcode
00035 #
00036 # @ingroup BasisPythonUtilities
00037 set (BASIS_PYTHON_UTILITIES "
00038 def _basis_init_sys_path():
00039     import os
00040     import sys
00041     module_dir  = os.path.dirname(os.path.realpath(__file__))
00042     sitelib_dir = os.path.normpath(os.path.join(module_dir, '\@BASIS_PYTHON_LIBRARY_DIR\@'))
00043     if sitelib_dir not in sys.path:
00044         sys.path.insert(0, sitelib_dir)
00045     sitelib_dir = os.path.normpath(os.path.join(module_dir, '\@PYTHON_LIBRARY_DIR\@'))
00046     if sitelib_dir not in sys.path:
00047         sys.path.insert(0, sitelib_dir)
00048 
00049 _basis_init_sys_path()
00050 from \@PROJECT_NAMESPACE_PYTHON\@ import basis
00051 "
00052 )
00053 
00054 # ============================================================================
00055 # Perl utilities
00056 # ============================================================================
00057 
00058 # ----------------------------------------------------------------------------
00059 ## @brief Include BASIS utilities for Perl.
00060 #
00061 # Example:
00062 # @code
00063 # #! /usr/bin/env perl
00064 # @BASIS_PERL_UTILITIES@
00065 # ...
00066 # @endcode
00067 #
00068 # @ingroup BasisPerlUtilities
00069 set (BASIS_PERL_UTILITIES "
00070 use Cwd qw(realpath);
00071 use File::Basename;
00072 use lib realpath(dirname(realpath(__FILE__)) . '/\@BASIS_PERL_LIBRARY_DIR\@');
00073 use lib realpath(dirname(realpath(__FILE__)) . '/\@PERL_LIBRARY_DIR\@');
00074 use lib dirname(realpath(__FILE__));
00075 
00076 package Basis;
00077 use \@PROJECT_NAMESPACE_PERL\@::Basis qw(:everything);
00078 package main;
00079 "
00080 )
00081 
00082 # ============================================================================
00083 # BASH utilities
00084 # ============================================================================
00085 
00086 # ----------------------------------------------------------------------------
00087 ## @brief Absolute path of current BASH file.
00088 #
00089 # @note Does not resolve symbolic links.
00090 #
00091 # Example:
00092 # @code
00093 # readonly __MYMODULE=@BASIS_BASH___FILE__@
00094 # @endcode
00095 #
00096 # @ingroup BasisBashUtilities
00097 set (BASIS_BASH___FILE__ "$(cd -P -- \"$(dirname -- \"\${BASH_SOURCE}\")\" && pwd -P)/$(basename -- \"$BASH_SOURCE\")")
00098 
00099 # ----------------------------------------------------------------------------
00100 ## @brief Absolute path of directory of current BASH file.
00101 #
00102 # @note Does not resolve symbolic links.
00103 #
00104 # Example:
00105 # @code
00106 # readonly __MYMODULE_dir=@BASIS_BASH___DIR__@
00107 # @endcode
00108 #
00109 # @ingroup BasisBashUtilities
00110 set (BASIS_BASH___DIR__ "$(cd -P -- \"$(dirname -- \"\${BASH_SOURCE}\")\" && pwd -P)")
00111 
00112 # ----------------------------------------------------------------------------
00113 ## @brief Definition of realpath() function.
00114 #
00115 # Example:
00116 # @code
00117 # #! /usr/bin/env bash
00118 # @BASIS_BASH_FUNCTION_realpath@
00119 # exec_dir=$(realpath $0)
00120 # @endcode
00121 #
00122 # @sa http://stackoverflow.com/questions/7665/how-to-resolve-symbolic-links-in-a-shell-script
00123 #
00124 # @ingroup BasisBashUtilities
00125 set (BASIS_BASH_FUNCTION_realpath "
00126 # ----------------------------------------------------------------------------
00127 ## @brief Get real path of given file or directory.
00128 #
00129 # @note This function was substituted by BASIS either for the string
00130 #       \\\@BASIS_BASH_UTILITIES\\\@ or \\\@BASIS_BASH_FUNCTION_realpath\\\@.
00131 #
00132 # Example:
00133 # @code
00134 # exec_dir=`realpath $0`
00135 # @endcode
00136 #
00137 # @param [in] path File or directory path.
00138 #
00139 # @returns Canonical path.
00140 #
00141 # @sa http://stackoverflow.com/questions/7665/how-to-resolve-symbolic-links-in-a-shell-script
00142 function realpath
00143 {
00144     local path=$1
00145 
00146     local linkdir=''
00147     local symlink=''
00148 
00149     while [ -h \${path} ]; do
00150         # 1) change to directory of the symbolic link
00151         # 2) change to directory where the symbolic link points to
00152         # 3) get the current working directory
00153         # 4) append the basename
00154         linkdir=$(dirname -- \"\${path}\")
00155         symlink=$(readlink \${path})
00156         path=$(cd \"\${linkdir}\" && cd $(dirname -- \"\${symlink}\") && pwd)/$(basename -- \"\${symlink}\")
00157     done
00158 
00159     echo -n \"$(cd -P -- \"$(dirname \"\${path}\")\" && pwd -P)/$(basename -- \"\${path}\")\"
00160 }
00161 "
00162 )
00163 
00164 # ----------------------------------------------------------------------------
00165 ## @brief Include BASIS utilities for BASH.
00166 #
00167 # Example:
00168 # @code
00169 # #! /usr/bin/env bash
00170 # @BASIS_BASH_UTILITIES@
00171 # get_executable_directory exec_dir
00172 # get_executable_name      exec_name
00173 #
00174 # echo "The executable ${exec_name} is located in ${exec_dir}."
00175 # @endcode
00176 #
00177 # @ingroup BasisBashUtilities
00178 set (BASIS_BASH_UTILITIES "
00179 # constants used by the shflags.sh module
00180 HELP_COMMAND='\@NAME\@ (\@PROJECT_NAME\@)'
00181 HELP_CONTACT='SBIA Group <sbia-software at uphs.upenn.edu>'
00182 HELP_VERSION='\@PROJECT_VERSION_AND_REVISION\@'
00183 HELP_COPYRIGHT='Copyright (c) University of Pennsylvania. All rights reserved.
00184 See https://www.rad.upenn.edu/sbia/software/license.html or COPYING file.'
00185 
00186 ${BASIS_BASH_FUNCTION_realpath}
00187 readonly _\@PROJECT_NAMESPACE_BASH\@_\@NAMESPACE_UPPER\@_DIR=\"$(dirname -- \"$(realpath \"${BASIS_BASH___FILE__}\")\")\"
00188 source \"\${_\@PROJECT_NAMESPACE_BASH\@_\@NAMESPACE_UPPER\@_DIR}/\@LIBRARY_DIR\@/basis.sh\" || exit 1
00189 "
00190 )
00191 
00192 # ============================================================================
00193 # auxiliary sources
00194 # ============================================================================
00195 
00196 # ----------------------------------------------------------------------------
00197 ## @brief Configure auxiliary C++ source files.
00198 #
00199 # This function configures the following default auxiliary source files
00200 # which can be used by the projects which are making use of BASIS.
00201 #
00202 # <table border="0">
00203 #   <tr>
00204 #     @tp @b basis.h @endtp
00205 #     <td>Main include file which includes all the header files of the
00206 #         BASIS utilities including both, non-project specific utilities
00207 #         which are installed as part of BASIS, and project specific
00208 #         utilities configured by this function.</td>
00209 #   </tr>
00210 #   <tr>
00211 #     @tp @b config.h @endtp
00212 #     <td>This file is intended to be included by all source files.
00213 #         Hence, other projects will indirectly include this file when
00214 #         they use a library of this project. Therefore, it is
00215 #         important to avoid potential name conflicts.</td>
00216 #   </tr>
00217 #   <tr>
00218 #     @tp @b config.cxx @endtp
00219 #     <td>Definition of constants declared in config.h file.
00220 #         In particular, the paths of the installation directories
00221 #         relative to the executables are defined by this file.
00222 #         These constants are used by the auxiliary functions
00223 #         implemented in stdaux.h.</td>
00224 #   </tr>
00225 #   <tr>
00226 #     @tp @b stdaux.h @endtp
00227 #     <td>Declares auxiliary functions such as functions to get absolute path
00228 #         to the subdirectories of the installation.</td>
00229 #   </tr>
00230 #   <tr>
00231 #     @tp @b stdaux.cxx @endtp
00232 #     <td>Definition of auxiliary functions declared in stdaux.h.</td>
00233 #   </tr>
00234 #   <tr>
00235 #     @tp @b ExecutableTargetInfo.h @endtp
00236 #     <td>Declares ExecutableTargetInfo class which can be used at runtime
00237 #         to obtain information about an executable using the name of the
00238 #         corresponding BASIS/CMake build target.</td>
00239 #   </tr>
00240 #   <tr>
00241 #     @tp @b ExecutableTargetInfo.cxx @endtp
00242 #     <td>Definition of ExecutableTargetInfo class. The constructor of
00243 #         this singleton class is created during the configuration step of
00244 #         CMake by the function basis_configure_ExecutableTargetInfo().</td>
00245 #   </tr>
00246 # </table>
00247 #
00248 # @note If there exists a *.in file of the corresponding source file in the
00249 #       PROJECT_CONFIG_DIR, it will be used as template. Otherwise, the
00250 #       template file of BASIS is used.
00251 #
00252 # @param [out] SOURCES        Configured auxiliary source files.
00253 # @param [out] HEADERS        Configured auxiliary header files.
00254 # @param [out] PUBLIC_HEADERS Auxiliary headers that should be installed.
00255 #
00256 # @returns Sets the variables specified by the @c [out] parameters.
00257 function (basis_configure_auxiliary_sources SOURCES HEADERS PUBLIC_HEADERS)
00258   if (BASIS_VERBOSE)
00259     message (STATUS "Configuring auxiliary sources...")
00260   endif ()
00261 
00262   set (SOURCES_OUT        "")
00263   set (HEADERS_OUT        "")
00264   set (PUBLIC_HEADERS_OUT "")
00265 
00266   # set variables to be substituted within auxiliary source files
00267   set (BUILD_ROOT_PATH_CONFIG    "${CMAKE_BINARY_DIR}")
00268   set (RUNTIME_BUILD_PATH_CONFIG "${BINARY_RUNTIME_DIR}")
00269   set (LIBEXEC_BUILD_PATH_CONFIG "${BINARY_LIBEXEC_DIR}")
00270   set (LIBRARY_BUILD_PATH_CONFIG "${BINARY_LIBRARY_DIR}")
00271   set (DATA_BUILD_PATH_CONFIG    "${PROJECT_DATA_DIR}")
00272 
00273   file (RELATIVE_PATH RUNTIME_PATH_PREFIX_CONFIG "${INSTALL_PREFIX}/${INSTALL_RUNTIME_DIR}" "${INSTALL_PREFIX}")
00274   file (RELATIVE_PATH LIBEXEC_PATH_PREFIX_CONFIG "${INSTALL_PREFIX}/${INSTALL_LIBEXEC_DIR}" "${INSTALL_PREFIX}")
00275 
00276   string (REGEX REPLACE "/$|\\$" "" RUNTIME_PATH_PREFIX_CONFIG "${RUNTIME_PATH_PREFIX_CONFIG}")
00277   string (REGEX REPLACE "/$|\\$" "" LIBEXEC_PATH_PREFIX_CONFIG "${LIBEXEC_PATH_PREFIX_CONFIG}")
00278 
00279   set (RUNTIME_PATH_CONFIG "${INSTALL_RUNTIME_DIR}")
00280   set (LIBEXEC_PATH_CONFIG "${INSTALL_LIBEXEC_DIR}")
00281   set (LIBRARY_PATH_CONFIG "${INSTALL_LIBRARY_DIR}")
00282   set (DATA_PATH_CONFIG    "${INSTALL_DATA_DIR}")
00283 
00284   # configure public auxiliary header files
00285   set (
00286     SOURCES_NAMES
00287       "config.h"
00288   )
00289 
00290   foreach (SOURCE ${SOURCES_NAMES})
00291     set (TEMPLATE "${PROJECT_INCLUDE_DIR}/sbia/${PROJECT_NAME_LOWER}/${SOURCE}.in")
00292     if (NOT EXISTS "${TEMPLATE}")
00293       set (TEMPLATE "${BASIS_CXX_TEMPLATES_DIR}/${SOURCE}.in")
00294     endif ()
00295     set  (SOURCE_OUT "${BINARY_INCLUDE_DIR}/sbia/${PROJECT_NAME_LOWER}/${SOURCE}")
00296     configure_file ("${TEMPLATE}" "${SOURCE_OUT}" @ONLY)
00297     list (APPEND PUBLIC_HEADERS_OUT "${SOURCE_OUT}")
00298   endforeach ()
00299 
00300   list (APPEND HEADERS ${PUBLIC_HEADERS_OUT})
00301 
00302   # configure private auxiliary source files
00303   set (
00304     SOURCES_NAMES
00305       "basis.h"
00306       "config.cxx"
00307       "stdaux.h"
00308       "stdaux.cxx"
00309       "ExecutableTargetInfo.h"
00310   )
00311 
00312   foreach (SOURCE ${SOURCES_NAMES})
00313     set (TEMPLATE "${PROJECT_CODE_DIR}/${SOURCE}.in")
00314     if (NOT EXISTS "${TEMPLATE}")
00315       set (TEMPLATE "${BASIS_CXX_TEMPLATES_DIR}/${SOURCE}.in")
00316     endif ()
00317     set  (SOURCE_OUT "${BINARY_CODE_DIR}/${SOURCE}")
00318     configure_file ("${TEMPLATE}" "${SOURCE_OUT}" @ONLY)
00319     if (SOURCE MATCHES ".h$")
00320       list (APPEND HEADERS_OUT "${SOURCE_OUT}")
00321     else ()
00322       list (APPEND SOURCES_OUT "${SOURCE_OUT}")
00323     endif ()
00324   endforeach ()
00325 
00326   # ExecutableTargetInfo.cxx
00327   #
00328   # Create here only if non-existent as otherwise a build target
00329   # using it cannot be added because CMake checks for the existence
00330   # of the source files at this moment. The actual configuration of
00331   # the ExecutableTargetInfo.cxx source file is done by
00332   # basis_configure_ExecutableTargetInfo().
00333   set (SOURCE_OUT "${BINARY_CODE_DIR}/ExecutableTargetInfo.cxx")
00334   if (NOT EXISTS "${SOURCE_OUT}")
00335     file (WRITE "${SOURCE_OUT}"
00336       "#error Should have been replaced by the CMake function "
00337       "basis_configure_ExecutableTargetInfo()"
00338     )
00339   endif ()
00340   list (APPEND SOURCES_OUT "${SOURCE_OUT}")
00341 
00342   # return
00343   set (${SOURCES}        "${SOURCES_OUT}"        PARENT_SCOPE)
00344   set (${HEADERS}        "${HEADERS_OUT}"        PARENT_SCOPE)
00345   set (${PUBLIC_HEADERS} "${PUBLIC_HEADERS_OUT}" PARENT_SCOPE)
00346 
00347   if (BASIS_VERBOSE)
00348     message (STATUS "Configuring auxiliary sources... - done")
00349   endif ()
00350 endfunction ()
00351 
00352 # ----------------------------------------------------------------------------
00353 ## @brief Add include directories of auxiliary sources to search path.
00354 #
00355 # @param [in] SOURCES_LIST Name of list of source files.
00356 # @param [in] HEADERS_LIST Name of list of header files.
00357 function (basis_use_auxiliary_sources SOURCES_LIST HEADERS_LIST)
00358   # Attention: BASIS includes public header files which are named the
00359   #            same as system-wide header files. Therefore, avoid to add
00360   #            include/sbia/basis/ to the include search path.
00361   #
00362   #            For all other projects, this path was already added to the
00363   #            standard include search path (or not if not desired).
00364   #            In any case, do not add this path at this point.
00365   string (REGEX REPLACE "/$" "" EXCLUDE_DIRS "${BINARY_INCLUDE_DIR}/${INCLUDE_PREFIX}")
00366   # get list of paths to auxiliary header files
00367   set (INCLUDE_DIRS)
00368   foreach (H IN LISTS ${HEADERS_LIST})
00369     get_filename_component (D "${H}" PATH)
00370     list (FIND EXCLUDE_DIRS "${D}" IDX)
00371     if (IDX EQUAL -1)
00372       list (APPEND INCLUDE_DIRS "${D}")
00373     endif ()
00374   endforeach ()
00375   # remove duplicates
00376   if (INCLUDE_DIRS)
00377     list (REMOVE_DUPLICATES INCLUDE_DIRS)
00378   endif ()
00379   # add include directories
00380   if (INCLUDE_DIRS)
00381     basis_include_directories (BEFORE ${INCLUDE_DIRS})
00382   endif ()
00383   # define source groups
00384   if (${HEADERS_LIST})
00385     source_group ("Default" FILES ${${HEADERS_LIST}})
00386   endif ()
00387   if (${SOURCES_LIST})
00388     source_group ("Default" FILES ${${SOURCES_LIST}})
00389   endif ()
00390 endfunction ()
00391 
00392 # ----------------------------------------------------------------------------
00393 ## @brief Configure auxiliary modules for scripting languages.
00394 function (basis_configure_auxiliary_modules)
00395   basis_get_project_property (PYTHON PROPERTY PROJECT_USES_PYTHON_UTILITIES)
00396   basis_get_project_property (PERL   PROPERTY PROJECT_USES_PERL_UTILITIES)
00397   basis_get_project_property (BASH   PROPERTY PROJECT_USES_BASH_UTILITIES)
00398 
00399   if (NOT PYTHON AND NOT PERL AND NOT BASH)
00400     return ()
00401   endif ()
00402 
00403   if (BASIS_VERBOSE)
00404     message (STATUS "Configuring auxiliary modules...")
00405   endif ()
00406 
00407   # --------------------------------------------------------------------------
00408   # Python
00409   if (PYTHON)
00410     if (NOT BASIS_UTILITIES_ENABLED MATCHES "PYTHON")
00411       message (FATAL_ERROR "BASIS Python utilities required by this package"
00412                            " but BASIS was built without Python utilities."
00413                            " Rebuild BASIS with Python utilities enabled.")
00414     endif ()
00415 
00416     foreach (MODULE basis stdaux)
00417       basis_get_source_target_name (TARGET_NAME "${MODULE}.py" NAME)
00418       basis_add_library (
00419         ${TARGET_NAME} "${BASIS_PYTHON_TEMPLATES_DIR}/${MODULE}.py"
00420         MODULE
00421           BINARY_DIRECTORY "${BINARY_CODE_DIR}"
00422       )
00423       basis_set_target_properties (
00424         ${TARGET_NAME}
00425         PROPERTIES
00426           OUTPUT_NAME "${MODULE}"
00427           SUFFIX      ".py"
00428       )
00429     endforeach ()
00430   endif ()
00431 
00432   # --------------------------------------------------------------------------
00433   # Perl
00434   if (PERL)
00435     if (NOT BASIS_UTILITIES_ENABLED MATCHES "PYTHON")
00436       message (FATAL_ERROR "BASIS Perl utilities required by this package"
00437                            " but BASIS was built without Perl utilities."
00438                            " Rebuild BASIS with Perl utilities enabled.")
00439     endif ()
00440 
00441     foreach (MODULE Basis StdAux)
00442       basis_get_source_target_name (TARGET_NAME "${MODULE}.pm" NAME)
00443       basis_add_library (
00444         ${TARGET_NAME} "${BASIS_PERL_TEMPLATES_DIR}/${MODULE}.pm"
00445         MODULE
00446           BINARY_DIRECTORY "${BINARY_CODE_DIR}"
00447       )
00448       basis_set_target_properties (
00449         ${TARGET_NAME}
00450         PROPERTIES
00451           OUTPUT_NAME "${MODULE}"
00452           SUFFIX      ".pm"
00453       )
00454     endforeach ()
00455   endif ()
00456 
00457   # --------------------------------------------------------------------------
00458   # BASH
00459   if (BASH)
00460     if (NOT UNIX)
00461       message (FATAL_ERROR "Package uses BASIS BASH utilities but is build"
00462                            " on a non-Unix system.")
00463     endif ()
00464 
00465     foreach (MODULE basis stdaux)
00466       basis_get_source_target_name (TARGET_NAME "${MODULE}.sh" NAME)
00467       basis_add_library (
00468         ${TARGET_NAME} "${BASIS_BASH_TEMPLATES_DIR}/${MODULE}.sh"
00469         MODULE
00470           BINARY_DIRECTORY "${BINARY_CODE_DIR}"
00471       )
00472       basis_set_target_properties (
00473         ${TARGET_NAME}
00474         PROPERTIES
00475           OUTPUT_NAME "${MODULE}"
00476           SUFFIX      ".sh"
00477       )
00478     endforeach ()
00479   endif ()
00480 
00481   if (BASIS_VERBOSE)
00482     message (STATUS "Configuring auxiliary modules... - done")
00483   endif ()
00484 endfunction ()
00485 
00486 # ----------------------------------------------------------------------------
00487 ## @brief Configure ExecutibleTargetInfo modules.
00488 #
00489 # This function generates the initialization code of the ExecutableTargetInfo
00490 # module for different supported programming languages. In case of C++, the
00491 # source file has been configured and copied to the binary tree in a first
00492 # configuration pass such that it could be used in basis_add_*() commands
00493 # which check the existence of the arguments immediately.
00494 # As the generation of the initialization code requires a complete list of
00495 # build targets (cached in @c BASIS_TARGETS), this function has to be called
00496 # after all targets have been added and finalized (in case of custom targets).
00497 #
00498 # @returns Nothing.
00499 function (basis_configure_ExecutableTargetInfo)
00500   # --------------------------------------------------------------------------
00501   # ExecutableTargetInfo not used?
00502 
00503   set (CXX TRUE)
00504   foreach (LANG PYTHON PERL BASH)
00505     basis_get_project_property (${LANG} PROPERTY PROJECT_USES_${LANG}_UTILITIES)
00506   endforeach ()
00507 
00508   if (NOT CXX AND NOT PYTHON AND NOT PERL AND NOT BASH)
00509     return ()
00510   endif ()
00511 
00512   if (BASIS_VERBOSE)
00513     message (STATUS "Configuring ExecutableTargetInfo...")
00514   endif ()
00515 
00516   # --------------------------------------------------------------------------
00517   # lists of executable targets and their location
00518   set (EXECUTABLE_TARGETS)
00519   set (BUILD_LOCATIONS)
00520   set (INSTALL_LOCATIONS)
00521 
00522   # project targets
00523   foreach (P IN ITEMS ${PROJECT_NAME} ${PROJECT_MODULES_ENABLED})
00524     basis_get_project_property (TARGETS ${P})
00525     foreach (TARGET IN LISTS TARGETS)
00526       basis_get_target_type (TYPE ${TARGET})
00527       if (TYPE MATCHES "EXECUTABLE")
00528         basis_get_target_location (BUILD_LOCATION   ${TARGET} ABSOLUTE)
00529         basis_get_target_location (INSTALL_LOCATION ${TARGET} POST_INSTALL)
00530         if (BUILD_LOCATION AND INSTALL_LOCATION)
00531           list (APPEND EXECUTABLE_TARGETS "${TARGET}")
00532           list (APPEND BUILD_LOCATIONS    "${BUILD_LOCATION}")
00533           list (APPEND INSTALL_LOCATIONS  "${INSTALL_LOCATION}")
00534         else ()
00535           message (FATAL_ERROR "Failed to determine build or install location of target ${TARGET}!")
00536         endif ()
00537       endif ()
00538     endforeach ()
00539   endforeach ()
00540 
00541   # imported targets - exclude targets imported from other module
00542   foreach (P IN ITEMS ${PROJECT_NAME} ${PROJECT_MODULES_ENABLED})
00543     basis_get_project_property (IMPORTED_TARGETS   ${P})
00544     basis_get_project_property (IMPORTED_TYPES     ${P})
00545     basis_get_project_property (IMPORTED_LOCATIONS ${P})
00546     set (I 0)
00547     list (LENGTH IMPORTED_TARGETS N)
00548     while (I LESS N)
00549       list (GET IMPORTED_TARGETS   ${I} TARGET)
00550       list (GET IMPORTED_TYPES     ${I} TYPE)
00551       list (GET IMPORTED_LOCATIONS ${I} LOCATION)
00552       if (TYPE MATCHES "EXECUTABLE")
00553         # get corresponding UID to recognize targets imported from other modules
00554         basis_get_target_uid (UID ${TARGET})
00555         # skip already considered executables
00556         list (FIND EXECUTABLE_TARGETS ${UID} IDX)
00557         if (IDX EQUAL -1)
00558           if (LOCATION MATCHES "^NOTFOUND$")
00559             message (WARNING "Imported target ${TARGET} has no location property!")
00560           else ()
00561             list (APPEND EXECUTABLE_TARGETS ${TARGET})
00562             list (APPEND BUILD_LOCATIONS    "${LOCATION}")
00563             list (APPEND INSTALL_LOCATIONS  "${LOCATION}")
00564           endif ()
00565         endif ()
00566       endif ()
00567       math (EXPR I "${I} + 1")
00568     endwhile ()
00569   endforeach ()
00570 
00571   # --------------------------------------------------------------------------
00572   # generate source code
00573 
00574   set (CC)   # C++    - build tree and install tree version, constructor block
00575   set (PY_B) # Python - build tree version
00576   set (PY_I) # Python - install tree version
00577   set (PL_B) # Perl   - build tree version, hash entries
00578   set (PL_I) # Perl   - install tree version, hash entries
00579   set (SH_A) # BASH   - aliases
00580   set (SH_B) # BASH   - build tree version
00581   set (SH_I) # BASH   - install tree version
00582 
00583   if (CXX)
00584     set (CC            "// the following code was automatically generated by the BASIS")
00585     set (CC "${CC}\n    // CMake function basis_configure_ExecutableTargetInfo()")
00586   endif ()
00587 
00588   if (PYTHON)
00589     set (PY_B "${PY_B}    _locations = {\n")
00590     set (PY_I "${PY_I}    _locations = {\n")
00591   endif ()
00592 
00593   set (I 0)
00594   list (LENGTH EXECUTABLE_TARGETS N)
00595   while (I LESS N)
00596     # get executable information
00597     list (GET EXECUTABLE_TARGETS ${I} TARGET_UID)
00598     list (GET BUILD_LOCATIONS    ${I} BUILD_LOCATION)
00599     list (GET INSTALL_LOCATIONS  ${I} INSTALL_LOCATION)
00600 
00601     # insert $(IntDir) for Visual Studio build location
00602     if (CMAKE_GENERATOR MATCHES "Visual Studio")
00603       basis_get_target_type (TYPE ${TARGET_UID})
00604       if (TYPE MATCHES "^EXECUTABLE$")
00605         get_filename_component (DIRECTORY "${BUILD_LOCATION}" PATH)
00606         get_filename_component (FILENAME  "${BUILD_LOCATION}" NAME)
00607         set (BUILD_LOCATION_WITH_INTDIR "${DIRECTORY}/$(IntDir)/${FILENAME}")
00608       else ()
00609         set (BUILD_LOCATION_WITH_INTDIR "${BUILD_LOCATION}")
00610       endif ()
00611     else ()
00612       set (BUILD_LOCATION_WITH_INTDIR "${BUILD_LOCATION}")
00613     endif ()
00614 
00615     # installation path relative to different library paths
00616     foreach (L LIBRARY PYTHON_LIBRARY PERL_LIBRARY)
00617       file (
00618         RELATIVE_PATH INSTALL_LOCATION_REL2${L}
00619           "${INSTALL_PREFIX}/${INSTALL_${L}_DIR}"
00620           "${INSTALL_LOCATION}"
00621       )
00622       if (NOT INSTALL_LOCATION_REL2${L})
00623         set (INSTALL_LOCATION_REL2${L} ".")
00624       endif ()
00625     endforeach ()
00626 
00627     # target UID including project namespace
00628     if (TARGET_UID MATCHES "\\.")
00629       set (ALIAS "${TARGET_UID}")
00630     else ()
00631       set (ALIAS "${PROJECT_NAMESPACE_CMAKE}.${TARGET_UID}")
00632     endif ()
00633 
00634     # C++
00635     if (CXX)
00636       get_filename_component (EXEC_NAME   "${BUILD_LOCATION}"   NAME)
00637       get_filename_component (BUILD_DIR   "${BUILD_LOCATION}"   PATH)
00638       get_filename_component (INSTALL_DIR "${INSTALL_LOCATION}" PATH)
00639 
00640       set (CC "${CC}\n")
00641       set (CC "${CC}\n    // ${TARGET_UID}")
00642       set (CC "${CC}\n    _exec_names  [\"${ALIAS}\"] = \"${EXEC_NAME}\";")
00643       set (CC "${CC}\n    _build_dirs  [\"${ALIAS}\"] = \"${BUILD_DIR}\";")
00644       set (CC "${CC}\n    _install_dirs[\"${ALIAS}\"] = \"${INSTALL_DIR}\";")
00645     endif ()
00646 
00647     # Python
00648     if (PYTHON)
00649       set (PY_B "${PY_B}        '${ALIAS}' : '${BUILD_LOCATION_WITH_INTDIR}',\n")
00650       set (PY_I "${PY_I}        '${ALIAS}' : '../../${INSTALL_LOCATION_REL2PYTHON_LIBRARY}',\n")
00651     endif ()
00652 
00653     # Perl
00654     if (PERL)
00655       if (PL_B)
00656         set (PL_B "${PL_B},\n")
00657       endif ()
00658       set (PL_B "${PL_B}    '${ALIAS}' => '${BUILD_LOCATION_WITH_INTDIR}'")
00659       if (PL_I)
00660         set (PL_I "${PL_I},\n")
00661       endif ()
00662       set (PL_I "${PL_I}    '${ALIAS}' => '../../${INSTALL_LOCATION_REL2PERL_LIBRARY}'")
00663     endif ()
00664 
00665     # BASH
00666     if (BASH)
00667       # hash entry
00668       set (SH_B "${SH_B}\n    _executabletargetinfo_add '${ALIAS}' LOCATION '${BUILD_LOCATION}'")
00669       set (SH_I "${SH_I}\n    _executabletargetinfo_add '${ALIAS}' LOCATION '${INSTALL_LOCATION_REL2LIBRARY}'")
00670       # alias
00671       set (SH_A "${SH_A}\nalias '${ALIAS}'=`get_executable_path '${ALIAS}'`")
00672       # short alias (if target belongs to this project)
00673       if (TARGET_UID MATCHES "^${PROJECT_NAMESPACE_CMAKE_REGEX}\\.")
00674         basis_get_target_name (TARGET_NAME "${TARGET_UID}")
00675         set (SH_S "${SH_S}\nalias '${TARGET_NAME}'='${ALIAS}'")
00676       endif ()
00677     endif ()
00678 
00679     # next executable target
00680     math (EXPR I "${I} + 1")
00681   endwhile ()
00682 
00683   set (PY_B "${PY_B}    }")
00684   set (PY_I "${PY_I}    }")
00685 
00686   # --------------------------------------------------------------------------
00687   # remove unnecessary leading newlines
00688 
00689   string (STRIP "${CC}"   CC)
00690   string (STRIP "${PY_B}" PY_B)
00691   string (STRIP "${PY_I}" PY_I)
00692   string (STRIP "${PL_B}" PL_B)
00693   string (STRIP "${PL_I}" PL_I)
00694   string (STRIP "${SH_B}" SH_B)
00695   string (STRIP "${SH_A}" SH_A)
00696   string (STRIP "${SH_B}" SH_B)
00697   string (STRIP "${SH_I}" SH_I)
00698 
00699   # --------------------------------------------------------------------------
00700   # configure source files
00701 
00702   # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00703   # C++
00704 
00705   if (CXX)
00706     set (EXECUTABLE_TARGET_INFO "${CC}")
00707     configure_file (
00708       "${BASIS_CXX_TEMPLATES_DIR}/ExecutableTargetInfo.cxx.in"
00709       "${BINARY_CODE_DIR}/ExecutableTargetInfo.cxx"
00710       @ONLY
00711     )
00712   endif ()
00713 
00714   # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00715   # Python
00716 
00717   if (PYTHON)
00718     # script configuration
00719     set (CONFIG "${CONFIG}if (BUILD_INSTALL_SCRIPT)\n")
00720     set (CONFIG "${CONFIG}  set (EXECUTABLE_TARGET_INFO \"${PY_I}\")\n")
00721     set (CONFIG "${CONFIG}else ()\n")
00722     set (CONFIG "${CONFIG}  set (EXECUTABLE_TARGET_INFO \"${PY_B}\")\n")
00723     set (CONFIG "${CONFIG}endif ()\n")
00724 
00725     # add module
00726     set (TEMPLATE_FILE "${BASIS_PYTHON_TEMPLATES_DIR}/executabletargetinfo.py")
00727     basis_get_source_target_name (TARGET_NAME "${TEMPLATE_FILE}" NAME)
00728     basis_add_library (
00729       ${TARGET_NAME}
00730         "${TEMPLATE_FILE}"
00731       MODULE
00732         BINARY_DIRECTORY "${BINARY_CODE_DIR}"
00733         CONFIG "${CONFIG}"
00734     )
00735     basis_set_target_properties (
00736       ${TARGET_NAME}
00737       PROPERTIES
00738         OUTPUT_NAME "executabletargetinfo"
00739         SUFFIX      ".py"
00740     )
00741   endif ()
00742 
00743   # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00744   # Perl
00745 
00746   if (PERL)
00747     # script configuration
00748     set (CONFIG "${CONFIG}if (BUILD_INSTALL_SCRIPT)\n")
00749     set (CONFIG "${CONFIG}  set (EXECUTABLE_TARGET_INFO \"${PL_I}\")\n")
00750     set (CONFIG "${CONFIG}else ()\n")
00751     set (CONFIG "${CONFIG}  set (EXECUTABLE_TARGET_INFO \"${PL_B}\")\n")
00752     set (CONFIG "${CONFIG}endif ()\n")
00753 
00754     # add module
00755     set (TEMPLATE_FILE "${BASIS_PERL_TEMPLATES_DIR}/ExecutableTargetInfo.pm")
00756     basis_get_source_target_name (TARGET_NAME "${TEMPLATE_FILE}" NAME)
00757     basis_add_library (
00758       ${TARGET_NAME}
00759         "${TEMPLATE_FILE}"
00760       MODULE
00761         BINARY_DIRECTORY "${BINARY_CODE_DIR}"
00762         CONFIG "${CONFIG}"
00763     )
00764     basis_set_target_properties (
00765       ${TARGET_NAME}
00766       PROPERTIES
00767         OUTPUT_NAME "ExecutableTargetInfo"
00768         SUFFIX      ".pm"
00769     )
00770   endif ()
00771 
00772   # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00773   # BASH
00774 
00775   if (BASH)
00776     # script configuration
00777     set (CONFIG "${CONFIG}if (BUILD_INSTALL_SCRIPT)\n")
00778     set (CONFIG "${CONFIG}  set (EXECUTABLE_TARGET_INFO \"${SH_I}\")\n")
00779     set (CONFIG "${CONFIG}  set (EXECUTABLE_ALIASES \"${SH_A}\n\n# define short aliases for this project's targets\n${SH_S}\")\n")
00780     set (CONFIG "${CONFIG}else ()\n")
00781     set (CONFIG "${CONFIG}  set (EXECUTABLE_TARGET_INFO \"${SH_B}\")\n")
00782     set (CONFIG "${CONFIG}  set (EXECUTABLE_ALIASES \"${SH_A}\n\n# define short aliases for this project's targets\n${SH_S}\")\n")
00783     set (CONFIG "${CONFIG}endif ()\n")
00784 
00785     # add module
00786     set (TEMPLATE_FILE "${BASIS_BASH_TEMPLATES_DIR}/executabletargetinfo.sh")
00787     basis_get_source_target_name (TARGET_NAME "${TEMPLATE_FILE}" NAME)
00788     basis_add_library (
00789       ${TARGET_NAME}
00790         "${TEMPLATE_FILE}"
00791       MODULE
00792         BINARY_DIRECTORY "${BINARY_CODE_DIR}"
00793         CONFIG "${CONFIG}"
00794     )
00795     basis_set_target_properties (
00796       ${TARGET_NAME}
00797       PROPERTIES
00798         OUTPUT_NAME "executabletargetinfo"
00799         SUFFIX      ".sh"
00800     )
00801   endif ()
00802 
00803   # --------------------------------------------------------------------------
00804   # done
00805   if (BASIS_VERBOSE)
00806     message (STATUS "Configuring ExecutableTargetInfo... - done")
00807   endif ()
00808 endfunction ()
00809 
00810 
00811 ## @}
00812 # end of Doxygen group