UtilitiesTools.cmake
Go to the documentation of this file.
00001 ############################################################################## 00002 # @file UtilitiesTools.cmake 00003 # @brief CMake functions related to configuration of BASIS utilities. 00004 # 00005 # Copyright (c) 2011, 2012, 2013 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 # C++ utilities 00019 # ============================================================================ 00020 00021 # ---------------------------------------------------------------------------- 00022 ## @brief Add build target for BASIS C++ utilities library. 00023 # 00024 # This function is called by the top-level project in order to add the "basis" 00025 # build target for the static project-specific BASIS utilities library for C++. 00026 # It is called by basis_project_impl() in the root CMakeLists.txt file of the 00027 # top-level project. 00028 # 00029 # The CMake function add_library() checks if the specified source code files 00030 # exist. If a source file is not found, an error is raised by CMake. The BASIS 00031 # utilities can, however, only be configured at the end of the configuration 00032 # step. Therefore, this function simply writes dummy C++ source files in order 00033 # to pass the existence check. The actual source files are configured by the 00034 # function basis_configure_utilities(). 00035 # 00036 # After writing these dummy source files, a library build target for the 00037 # project-specific BASIS C++ utilities is added. This build target is not 00038 # being build as part of the ALL target in case it is never used by any of 00039 # the build targets of the project. Only if build target links to this 00040 # library, it will be build and installed. 00041 # 00042 # @param [out] UID UID of added build target. 00043 function (basis_add_utilities_library UID) 00044 # target UID of "basis" library target 00045 basis_make_target_uid (TARGET_UID basis) 00046 if (NOT TARGET ${TARGET_UID}) 00047 if (PROJECT_IS_SUBPROJECT) 00048 # a subproject has it's own version of the project-specific BASIS utilities 00049 # as the targets and functions live in a separate namespace 00050 set (CODE_DIR "${BINARY_CODE_DIR}") 00051 set (INCLUDE_DIR "${BINARY_INCLUDE_DIR}") 00052 set (OUTPUT_DIR "${BINARY_ARCHIVE_DIR}") 00053 set (INSTALL_DIR "${INSTALL_ARCHIVE_DIR}") 00054 else () 00055 # modules, on the other side, share the library with the top-level project 00056 # the addition of the utilities target is in this case only required because 00057 # of the install(TARGETS) and install(EXPORT) commands. 00058 set (CODE_DIR "${BASIS_BINARY_CODE_DIR}") 00059 set (INCLUDE_DIR "${BASIS_BINARY_INCLUDE_DIR}") 00060 set (OUTPUT_DIR "${BASIS_BINARY_ARCHIVE_DIR}") 00061 set (INSTALL_DIR "${BASIS_INSTALL_ARCHIVE_DIR}") 00062 endif () 00063 # write dummy source files 00064 basis_library_prefix (PREFIX CXX) 00065 foreach (S IN ITEMS basis.h basis.cxx) 00066 if (S MATCHES "\\.h$") 00067 set (S "${INCLUDE_DIR}/${PREFIX}${S}") 00068 else () 00069 set (S "${CODE_DIR}/${S}") 00070 endif () 00071 if (NOT EXISTS "${S}") 00072 file (WRITE "${S}" 00073 "#error This dummy source file should have been replaced by the" 00074 " BASIS CMake function basis_configure_utilities()" 00075 ) 00076 endif () 00077 endforeach () 00078 # add library target if not present yet - only build if required 00079 add_library (${TARGET_UID} STATIC "${CODE_DIR}/basis.cxx") 00080 # define dependency on non-project specific utilities as the order in 00081 # which static libraries are listed on the command-line for the linker 00082 # matters; this will help CMake to get the order right 00083 target_link_libraries (${TARGET_UID} ${BASIS_CXX_UTILITIES_LIBRARY}) 00084 # set target properties 00085 _set_target_properties ( 00086 ${TARGET_UID} 00087 PROPERTIES 00088 BASIS_TYPE STATIC_LIBRARY 00089 OUTPUT_NAME basis 00090 ARCHIVE_OUTPUT_DIRECTORY "${OUTPUT_DIR}" 00091 ARCHIVE_INSTALL_DIRECTORY "${INSTALL_DIR}" 00092 ) 00093 # add installation rule 00094 install ( 00095 TARGETS ${TARGET_UID} 00096 EXPORT ${PROJECT_NAME} 00097 ARCHIVE 00098 DESTINATION "${INSTALL_DIR}" 00099 COMPONENT "${BASIS_LIBRARY_COMPONENT}" 00100 ) 00101 basis_set_project_property (APPEND PROPERTY EXPORT_TARGETS ${TARGET_UID}) 00102 basis_set_project_property (APPEND PROPERTY INSTALL_EXPORT_TARGETS ${TARGET_UID}) 00103 # debug message 00104 if (BASIS_DEBUG) 00105 message ("** Added BASIS utilities library ${TARGET_UID}") 00106 endif () 00107 endif () 00108 # done 00109 basis_set_project_property (PROPERTY PROJECT_USES_CXX_UTILITIES TRUE) 00110 set (${UID} "${TARGET_UID}" PARENT_SCOPE) 00111 endfunction () 00112 00113 # ============================================================================ 00114 # BASH utilities 00115 # ============================================================================ 00116 00117 # ---------------------------------------------------------------------------- 00118 ## @brief Absolute path of current BASH file. 00119 # 00120 # @note Does not resolve symbolic links. 00121 # 00122 # Example: 00123 # @code 00124 # readonly __MYMODULE=@BASIS_BASH___FILE__@ 00125 # @endcode 00126 # 00127 # @ingroup BasisBashUtilities 00128 set (BASIS_BASH___FILE__ "$(cd -- \"$(dirname -- \"\${BASH_SOURCE}\")\" && pwd -P)/$(basename -- \"$BASH_SOURCE\")") 00129 00130 # ---------------------------------------------------------------------------- 00131 ## @brief Absolute path of directory of current BASH file. 00132 # 00133 # @note Does not resolve symbolic links. 00134 # 00135 # Example: 00136 # @code 00137 # readonly __MYMODULE_dir=@BASIS_BASH___DIR__@ 00138 # @endcode 00139 # 00140 # @ingroup BasisBashUtilities 00141 set (BASIS_BASH___DIR__ "$(cd -- \"$(dirname -- \"\${BASH_SOURCE}\")\" && pwd -P)") 00142 00143 # ============================================================================ 00144 # determine which utilities are used 00145 # ============================================================================ 00146 00147 # ---------------------------------------------------------------------------- 00148 ## @brief Check whether the BASIS utilities are used within a given source file. 00149 # 00150 # This function matches the source code against specific import patterns which 00151 # are all valid imports of the BASIS utilities for the respective programming 00152 # language of the specified file. If the BASIS utilities are used within the 00153 # specified source file, the variable named @p VAR is set to @c TRUE. 00154 # Otherwise, it is set to @c FALSE. 00155 # 00156 # @param [out] VAR Whether the BASIS utilites are used. 00157 # @param [in] SOURCE_FILE Path of source file to check. 00158 # @param [in] ARGN Source code language. If not specified, the 00159 # programming language is determined automatically. 00160 function (basis_utilities_check VAR SOURCE_FILE) 00161 set (UTILITIES_USED FALSE) 00162 if (ARGC EQUAL 2) 00163 basis_get_source_language (LANGUAGE "${SOURCE_FILE}") 00164 elseif (ARGC EQUAL 3) 00165 set (LANGUAGE "${ARGN}") 00166 else () 00167 message (FATAL_ERROR "Too many arguments given!") 00168 endif () 00169 # -------------------------------------------------------------------------- 00170 # make file path absolute and append .in suffix if necessary 00171 get_filename_component (SOURCE_FILE "${SOURCE_FILE}" ABSOLUTE) 00172 if (NOT EXISTS "${SOURCE_FILE}" AND NOT SOURCE_FILE MATCHES "\\.in$" AND EXISTS "${SOURCE_FILE}.in") 00173 set (SOURCE_FILE "${SOURCE_FILE}.in") 00174 endif () 00175 # -------------------------------------------------------------------------- 00176 # C++ 00177 if (LANGUAGE MATCHES "CXX") 00178 # read script file 00179 file (READ "${SOURCE_FILE}" SOURCE) 00180 # match use/require statements 00181 basis_library_prefix (PREFIX ${LANGUAGE}) 00182 set (RE "[ \\t]*#[ \\t]*include[ \\t]+[<"](${PREFIX})?basis.h[">]") # e.g., #include "basis.h", #include <pkg/basis.h> 00183 if (SCRIPT MATCHES "(^|\n)[ \t]*${RE}([ \t]*//.*|[ \t]*)(\n|$)") 00184 set (UTILITIES_USED TRUE) 00185 break () 00186 endif () 00187 # -------------------------------------------------------------------------- 00188 # Python/Jython 00189 elseif (LANGUAGE MATCHES "[JP]YTHON") 00190 # read script file 00191 file (READ "${SOURCE_FILE}" SCRIPT) 00192 # deprecated BASIS_PYTHON_UTILITIES macro 00193 if (SCRIPT MATCHES "(^|\n|;)[ \t]*\@BASIS_PYTHON_UTILITIES\@") 00194 message (FATAL_ERROR "Script ${SOURCE_FILE} uses the deprecated BASIS macro \@BASIS_PYTHON_UTILITIES\@!") 00195 endif () 00196 basis_sanitize_for_regex (PYTHON_PACKAGE "${PROJECT_NAMESPACE_PYTHON}") 00197 # match use of package-specific utilities 00198 if (SCRIPT MATCHES "[^a-zA-Z._]${PYTHON_PACKAGE}.basis([.; \t\n]|$)") # e.g., basis = <package>.basis, <package>.basis.exedir() 00199 set (UTILITIES_USED TRUE) 00200 else () 00201 # match import statements 00202 foreach (RE IN ITEMS 00203 "import[ \\t]+basis" # e.g., import basis 00204 "import[ \\t]+${PYTHON_PACKAGE}\\.basis" # e.g., import <package>.basis 00205 "import[ \\t]+\\.\\.?basis" # e.g., import .basis, import ..basis 00206 "from[ \\t]+${PYTHON_PACKAGE}[ \\t]+import[ \\t]+basis" # e.g., from <package> import basis 00207 "from[ \\t]+${PYTHON_PACKAGE}.basis[ \\t]+import[ \\t].*" # e.g., from <package>.basis import which 00208 "from[ \\t]+\\.\\.?[ \\t]+import[ \\t]+basis" # e.g., from . import basis", "from .. import basis 00209 "from[ \\t]+\\.\\.?basis[ \\t]+import[ \\t].*" # e.g., from .basis import which, WhichError, from ..basis import which 00210 ) # foreach RE 00211 if (SCRIPT MATCHES "(^|\n|;)[ \t]*${RE}([ \t]*as[ \t]+.*)?([ \t]*#.*|[ \t]*)(;|\n|$)") 00212 set (UTILITIES_USED TRUE) 00213 break () 00214 endif () 00215 endforeach () 00216 endif () 00217 # -------------------------------------------------------------------------- 00218 # Perl 00219 elseif (LANGUAGE MATCHES "PERL") 00220 # read script file 00221 file (READ "${SOURCE_FILE}" SCRIPT) 00222 # deprecated BASIS_PERL_UTILITIES macro 00223 if (SCRIPT MATCHES "(^|\n|;)[ \t]*\@BASIS_PERL_UTILITIES\@") 00224 message (FATAL_ERROR "Script ${SOURCE_FILE} uses the deprecated BASIS macro \@BASIS_PERL_UTILITIES\@!") 00225 endif () 00226 # match use/require statements 00227 basis_sanitize_for_regex (PERL_PACKAGE "${PROJECT_NAMESPACE_PERL}") 00228 set (RE "(use|require)[ \\t]+${PERL_PACKAGE}::Basis([ \\t]+.*)?") # e.g., use <Package>::Basis qw(:everything); 00229 if (SCRIPT MATCHES "(^|\n|;)[ \t]*${RE}([ \t]*#.*|[ \t]*)(;|\n|$)") 00230 set (UTILITIES_USED TRUE) 00231 break () 00232 endif () 00233 # -------------------------------------------------------------------------- 00234 # Bash 00235 elseif (LANGUAGE MATCHES "BASH") 00236 # read script file 00237 file (READ "${SOURCE_FILE}" SCRIPT) 00238 # deprecated BASIS_BASH_UTILITIES macro 00239 if (SCRIPT MATCHES "(^|\n|;)[ \t]*\@BASIS_BASH_UTILITIES\@") 00240 message (FATAL_ERROR "Script ${SOURCE_FILE} uses the deprecated BASIS macro \@BASIS_BASH_UTILITIES\@!") 00241 endif () 00242 # match source/. built-ins 00243 set (RE "(source|\\.)[ \\t]+\\\"?\\\${?BASIS_BASH_UTILITIES}?\\\"?[ \\t]*(\\|\\|.*|&&.*)?(#.*)?") # e.g., . ${BASIS_BASH_UTILITIES} || exit 1 00244 if (SCRIPT MATCHES "(^|\n|;)[ \t]*(${RE})[ \t]*(;|\n|$)") 00245 set (UTILITIES_USED TRUE) 00246 endif () 00247 endif () 00248 # return 00249 set (${VAR} "${UTILITIES_USED}" PARENT_SCOPE) 00250 endfunction () 00251 00252 # ============================================================================ 00253 # configuration 00254 # ============================================================================ 00255 00256 # ---------------------------------------------------------------------------- 00257 ## @brief Configure BASIS utilities. 00258 # 00259 # This function configures the following source files which can be used 00260 # within the source code of the project. 00261 # 00262 # <table border="0"> 00263 # <tr> 00264 # @tp @b basis.h @endtp 00265 # <td>Header file declaring the BASIS utilities for C++.</td> 00266 # </tr> 00267 # <tr> 00268 # @tp @b basis.cxx @endtp 00269 # <td>Definitions of the constants and functions declared in basis.h.</td> 00270 # </tr> 00271 # <tr> 00272 # @tp @b basis.py @endtp 00273 # <td>Module defining the BASIS utilities for Python.</td> 00274 # </tr> 00275 # <tr> 00276 # @tp @b Basis.pm @endtp 00277 # <td>Module defining the BASIS utilities for Perl.</td> 00278 # </tr> 00279 # <tr> 00280 # @tp @b basis.sh @endtp 00281 # <td>Module defining the BASIS utilities for Bash.</td> 00282 # </tr> 00283 # </table> 00284 # 00285 # @note Dummy versions of the C++ source files have been written by the 00286 # function basis_configure_auxiliary_sources() beforehand. This is 00287 # necessary because CMake's add_executable() and add_library() commands 00288 # raise an error if any of the specified source files does not exist. 00289 function (basis_configure_utilities) 00290 set (CXX TRUE) 00291 basis_get_project_property (PYTHON PROPERTY PROJECT_USES_PYTHON_UTILITIES) 00292 basis_get_project_property (PERL PROPERTY PROJECT_USES_PERL_UTILITIES) 00293 basis_get_project_property (BASH PROPERTY PROJECT_USES_BASH_UTILITIES) 00294 if (NOT CXX AND NOT PYTHON AND NOT PERL AND NOT BASH) 00295 return () 00296 endif () 00297 message (STATUS "Configuring BASIS utilities...") 00298 # -------------------------------------------------------------------------- 00299 # executable target information 00300 _basis_generate_executable_target_info(${CXX} ${PYTHON} ${PERL} ${BASH}) 00301 # -------------------------------------------------------------------------- 00302 # project ID -- used by print_version() in particular 00303 set (PROJECT_ID "${PROJECT_PACKAGE}") 00304 if (NOT PROJECT_NAME MATCHES "${PROJECT_PACKAGE}") 00305 set (PROJECT_ID "${PROJECT_ID}, ${PROJECT_NAME}") 00306 endif () 00307 # -------------------------------------------------------------------------- 00308 # C++ 00309 if (CXX) 00310 # paths - build tree 00311 set (BUILD_ROOT_PATH_CONFIG "${CMAKE_BINARY_DIR}") 00312 set (RUNTIME_BUILD_PATH_CONFIG "${BINARY_RUNTIME_DIR}") 00313 set (LIBEXEC_BUILD_PATH_CONFIG "${BINARY_LIBEXEC_DIR}") 00314 set (LIBRARY_BUILD_PATH_CONFIG "${BINARY_LIBRARY_DIR}") 00315 set (DATA_BUILD_PATH_CONFIG "${PROJECT_DATA_DIR}") 00316 # paths - installation 00317 file (RELATIVE_PATH RUNTIME_PATH_PREFIX_CONFIG "${CMAKE_INSTALL_PREFIX}/${INSTALL_RUNTIME_DIR}" "${CMAKE_INSTALL_PREFIX}") 00318 string (REGEX REPLACE "/$|\\$" "" RUNTIME_PATH_PREFIX_CONFIG "${RUNTIME_PATH_PREFIX_CONFIG}") 00319 file (RELATIVE_PATH LIBEXEC_PATH_PREFIX_CONFIG "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBEXEC_DIR}" "${CMAKE_INSTALL_PREFIX}") 00320 string (REGEX REPLACE "/$|\\$" "" LIBEXEC_PATH_PREFIX_CONFIG "${LIBEXEC_PATH_PREFIX_CONFIG}") 00321 set (RUNTIME_PATH_CONFIG "${INSTALL_RUNTIME_DIR}") 00322 set (LIBEXEC_PATH_CONFIG "${INSTALL_LIBEXEC_DIR}") 00323 set (LIBRARY_PATH_CONFIG "${INSTALL_LIBRARY_DIR}") 00324 set (DATA_PATH_CONFIG "${INSTALL_DATA_DIR}") 00325 # namespace 00326 set (PROJECT_NAMESPACE_CXX_BEGIN "namespace ${PROJECT_PACKAGE_L} {") 00327 set (PROJECT_NAMESPACE_CXX_END "}") 00328 if (PROJECT_IS_SUBPROJECT) 00329 set (PROJECT_NAMESPACE_CXX_BEGIN "${PROJECT_NAMESPACE_CXX_BEGIN} namespace ${PROJECT_NAME_L} {") 00330 set (PROJECT_NAMESPACE_CXX_END "${PROJECT_NAMESPACE_CXX_END} }") 00331 endif () 00332 # executable target information 00333 set (EXECUTABLE_TARGET_INFO "${EXECUTABLE_TARGET_INFO_CXX}") 00334 # configure source files 00335 basis_library_prefix (PREFIX CXX) 00336 configure_file ("${BASIS_CXX_TEMPLATES_DIR}/basis.h.in" "${BINARY_INCLUDE_DIR}/${PREFIX}basis.h" @ONLY) 00337 configure_file ("${BASIS_CXX_TEMPLATES_DIR}/basis.cxx.in" "${BINARY_CODE_DIR}/basis.cxx" @ONLY) 00338 source_group (BASIS FILES "${BINARY_INCLUDE_DIR}/${PREFIX}basis.h" "${BINARY_CODE_DIR}/basis.cxx") 00339 endif () 00340 # -------------------------------------------------------------------------- 00341 # Python 00342 if (PYTHON) 00343 # utilities available? 00344 if (NOT BASIS_UTILITIES_ENABLED MATCHES "PYTHON") 00345 message (FATAL_ERROR "BASIS Python utilities required by this package" 00346 " but BASIS was built without Python utilities." 00347 " Rebuild BASIS with Python utilities enabled.") 00348 endif () 00349 # add project-specific utilities 00350 basis_library_prefix (PREFIX PYTHON) 00351 basis_add_library (basis_py "${BASIS_PYTHON_TEMPLATES_DIR}/basis.py") 00352 set (COMPILE_DEFINITIONS 00353 "if (BUILD_INSTALL_SCRIPT) 00354 set (EXECUTABLE_TARGET_INFO \"${EXECUTABLE_TARGET_INFO_PYTHON_I}\") 00355 else () 00356 set (EXECUTABLE_TARGET_INFO \"${EXECUTABLE_TARGET_INFO_PYTHON_B}\") 00357 endif ()" 00358 ) 00359 if (PROJECT_NAME MATCHES "^BASIS$") 00360 set (COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}\nbasis_set_script_path (_BASIS_PYTHONPATH \"${BINARY_PYTHON_LIBRARY_DIR}\" \"${INSTALL_PYTHON_LIBRARY_DIR}\")") 00361 elseif (BUNDLE_PROJECTS MATCHES "(^|;)BASIS(;|$)") 00362 set (COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}\nbasis_set_script_path (_BASIS_PYTHONPATH \"${BASIS_PYTHONPATH}\")") 00363 else () 00364 set (COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}\nset (_BASIS_PYTHONPATH \"${BASIS_PYTHONPATH}\")") 00365 endif () 00366 basis_set_target_properties ( 00367 basis_py 00368 PROPERTIES 00369 SOURCE_DIRECTORY "${BASIS_PYTHON_TEMPLATES_DIR}" 00370 BINARY_DIRECTORY "${BINARY_CODE_DIR}" 00371 LIBRARY_OUTPUT_DIRECTORY "${BINARY_PYTHON_LIBRARY_DIR}" 00372 LIBRARY_INSTALL_DIRECTORY "${INSTALL_PYTHON_LIBRARY_DIR}" 00373 PREFIX "${PREFIX}" 00374 COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}" 00375 ) 00376 # dependencies 00377 basis_target_link_libraries (basis_py ${BASIS_PYTHON_UTILITIES_LIBRARY}) 00378 endif () 00379 # -------------------------------------------------------------------------- 00380 # Perl 00381 if (PERL) 00382 # utilities available? 00383 if (NOT BASIS_UTILITIES_ENABLED MATCHES "PERL") 00384 message (FATAL_ERROR "BASIS Perl utilities required by this package" 00385 " but BASIS was built without Perl utilities." 00386 " Rebuild BASIS with Perl utilities enabled.") 00387 endif () 00388 # add project-specific utilities 00389 basis_library_prefix (PREFIX PERL) 00390 basis_add_library (Basis_pm "${BASIS_PERL_TEMPLATES_DIR}/Basis.pm") 00391 basis_set_target_properties ( 00392 Basis_pm 00393 PROPERTIES 00394 SOURCE_DIRECTORY "${BASIS_PERL_TEMPLATES_DIR}" 00395 BINARY_DIRECTORY "${BINARY_CODE_DIR}" 00396 LIBRARY_OUTPUT_DIRECTORY "${BINARY_PERL_LIBRARY_DIR}" 00397 LIBRARY_INSTALL_DIRECTORY "${INSTALL_PERL_LIBRARY_DIR}" 00398 PREFIX "${PREFIX}" 00399 COMPILE_DEFINITIONS 00400 "if (BUILD_INSTALL_SCRIPT) 00401 set (EXECUTABLE_TARGET_INFO \"${EXECUTABLE_TARGET_INFO_PERL_I}\") 00402 else () 00403 set (EXECUTABLE_TARGET_INFO \"${EXECUTABLE_TARGET_INFO_PERL_B}\") 00404 endif ()" 00405 ) 00406 # dependencies 00407 basis_target_link_libraries (Basis_pm ${BASIS_PERL_UTILITIES_LIBRARY}) 00408 endif () 00409 # -------------------------------------------------------------------------- 00410 # Bash 00411 if (BASH) 00412 # utilities available? 00413 if (NOT UNIX) 00414 message (WARNING "Package uses BASIS Bash utilities but is build" 00415 " on a non-Unix system.") 00416 endif () 00417 # utilities available? 00418 if (NOT BASIS_UTILITIES_ENABLED MATCHES "BASH") 00419 message (FATAL_ERROR "BASIS Bash utilities required by this package" 00420 " but BASIS was built without Bash utilities." 00421 " Rebuild BASIS with Bash utilities enabled.") 00422 endif () 00423 # add project-specific utilities 00424 basis_library_prefix (PREFIX BASH) 00425 basis_add_library (basis_sh "${BASIS_BASH_TEMPLATES_DIR}/basis.sh") 00426 set (COMPILE_DEFINITIONS 00427 "if (BUILD_INSTALL_SCRIPT) 00428 set (EXECUTABLE_TARGET_INFO \"${EXECUTABLE_TARGET_INFO_BASH_I}\") 00429 else () 00430 set (EXECUTABLE_TARGET_INFO \"${EXECUTABLE_TARGET_INFO_BASH_B}\") 00431 endif () 00432 set (EXECUTABLE_ALIASES \"${EXECUTABLE_TARGET_INFO_BASH_A}\n\n # define short aliases for this project's targets\n ${EXECUTABLE_TARGET_INFO_BASH_S}\")" 00433 ) 00434 if (PROJECT_NAME MATCHES "^BASIS$") 00435 set (COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}\nbasis_set_script_path (_BASIS_BASH_LIBRARY_DIR \"${BINARY_BASH_LIBRARY_DIR}\" \"${INSTALL_BASH_LIBRARY_DIR}\")") 00436 elseif (BUNDLE_PROJECTS MATCHES "(^|;)BASIS(;|$)") 00437 set (COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}\nbasis_set_script_path (_BASIS_BASH_LIBRARY_DIR \"${BASIS_BASHPATH}\")") 00438 else () 00439 set (COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}\nset (_BASIS_BASH_LIBRARY_DIR \"${BASIS_BASHPATH}\")") 00440 endif () 00441 basis_set_target_properties ( 00442 basis_sh 00443 PROPERTIES 00444 SOURCE_DIRECTORY "${BASIS_BASH_TEMPLATES_DIR}" 00445 BINARY_DIRECTORY "${BINARY_CODE_DIR}" 00446 LIBRARY_OUTPUT_DIRECTORY "${BINARY_BASH_LIBRARY_DIR}" 00447 LIBRARY_INSTALL_DIRECTORY "${INSTALL_BASH_LIBRARY_DIR}" 00448 PREFIX "${PREFIX}" 00449 COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}" 00450 ) 00451 # dependencies 00452 basis_target_link_libraries (basis_sh ${BASIS_BASH_UTILITIES_LIBRARY}) 00453 endif () 00454 00455 message (STATUS "Configuring BASIS utilities... - done") 00456 endfunction () 00457 00458 # ---------------------------------------------------------------------------- 00459 ## @brief Generate code for initialization of executable target information. 00460 # 00461 # This macro generates the initialization code of the executable target 00462 # information dictionaries for different supported programming languages. 00463 # In case of C++, the source file has been configured and copied to the binary 00464 # tree in a first configuration pass such that it could be used in basis_add_*() 00465 # commands which check the existence of the arguments immediately. 00466 # As the generation of the initialization code requires a complete list of 00467 # build targets (cached in @c BASIS_TARGETS), this function has to be called 00468 # after all targets have been added and finalized (in case of custom targets). 00469 # 00470 # @param [in] CXX Request code for C++. 00471 # @param [in] PYTHON Request code for Python. 00472 # @param [in] PERL Request code for Perl. 00473 # @param [in] BASH Request code for Bash. 00474 # 00475 # @returns Sets the following variables for each requested language. 00476 # 00477 # @retval EXECUTABLE_TARGET_INFO_CXX C++ code for both build tree and installation. 00478 # @retval EXECUTABLE_TARGET_INFO_PYTHON_B Python code for build tree. 00479 # @retval EXECUTABLE_TARGET_INFO_PYTHON_I Python code for installation. 00480 # @retval EXECUTABLE_TARGET_INFO_PERL_B Perl code for build tree. 00481 # @retval EXECUTABLE_TARGET_INFO_PERL_I Perl code for installation. 00482 # @retval EXECUTABLE_TARGET_INFO_BASH_B Bash code for build tree. 00483 # @retval EXECUTABLE_TARGET_INFO_BASH_I Bash code for installation. 00484 # @retval EXECUTABLE_TARGET_INFO_BASH_A Bash code to set aliases. 00485 # @retval EXECUTABLE_TARGET_INFO_BASH_S Bash code to set short aliases. 00486 function (_basis_generate_executable_target_info CXX PYTHON PERL BASH) 00487 # -------------------------------------------------------------------------- 00488 if (NOT CXX AND NOT PYTHON AND NOT PERL AND NOT BASH) 00489 return () 00490 endif () 00491 # -------------------------------------------------------------------------- 00492 # local constants 00493 basis_sanitize_for_regex (PROJECT_NAMESPACE_CMAKE_RE "${PROJECT_NAMESPACE_CMAKE}") 00494 # -------------------------------------------------------------------------- 00495 # lists of executable targets and their location 00496 set (EXECUTABLE_TARGETS) 00497 set (BUILD_LOCATIONS) 00498 set (INSTALL_LOCATIONS) 00499 # project targets 00500 basis_get_project_property (TARGETS) 00501 foreach (TARGET IN LISTS TARGETS) 00502 basis_get_target_type (TYPE ${TARGET}) 00503 if (TYPE MATCHES "EXECUTABLE") 00504 basis_get_target_location (BUILD_LOCATION ${TARGET} ABSOLUTE) 00505 basis_get_target_location (INSTALL_LOCATION ${TARGET} POST_INSTALL) 00506 if (BUILD_LOCATION) 00507 list (APPEND EXECUTABLE_TARGETS "${TARGET}") 00508 list (APPEND BUILD_LOCATIONS "${BUILD_LOCATION}") 00509 list (APPEND INSTALL_LOCATIONS "${INSTALL_LOCATION}") 00510 else () 00511 message (FATAL_ERROR "Failed to determine build location of target ${TARGET}!") 00512 endif () 00513 endif () 00514 endforeach () 00515 # imported targets 00516 basis_get_project_property (IMPORTED_TARGETS) 00517 basis_get_project_property (IMPORTED_TYPES) 00518 basis_get_project_property (IMPORTED_LOCATIONS) 00519 set (I 0) 00520 list (LENGTH IMPORTED_TARGETS N) 00521 while (I LESS N) 00522 list (GET IMPORTED_TARGETS ${I} TARGET) 00523 list (GET IMPORTED_TYPES ${I} TYPE) 00524 list (GET IMPORTED_LOCATIONS ${I} LOCATION) 00525 if (TYPE MATCHES "EXECUTABLE") 00526 # get corresponding UID (target may be imported from other module) 00527 basis_get_target_uid (UID ${TARGET}) 00528 # skip already considered executables 00529 list (FIND EXECUTABLE_TARGETS ${UID} IDX) 00530 if (IDX EQUAL -1) 00531 if (LOCATION MATCHES "^NOTFOUND$") 00532 message (WARNING "Imported target ${TARGET} has no location property!") 00533 else () 00534 list (APPEND EXECUTABLE_TARGETS ${TARGET}) 00535 list (APPEND BUILD_LOCATIONS "${LOCATION}") 00536 list (APPEND INSTALL_LOCATIONS "${LOCATION}") 00537 endif () 00538 endif () 00539 endif () 00540 math (EXPR I "${I} + 1") 00541 endwhile () 00542 # -------------------------------------------------------------------------- 00543 # determine maximum length of target alias for prettier output 00544 set (MAX_ALIAS_LENGTH 0) 00545 foreach (TARGET_UID IN LISTS EXECUTABLE_TARGETS) 00546 if (TARGET_UID MATCHES "^\\.") 00547 string (LENGTH "${TARGET_UID}" LENGTH) 00548 else () 00549 string (LENGTH "${BASIS_PROJECT_NAMESPACE_CMAKE}.${TARGET_UID}" LENGTH) 00550 endif () 00551 if (LENGTH GREATER MAX_ALIAS_LENGTH) 00552 set (MAX_ALIAS_LENGTH ${LENGTH}) 00553 endif () 00554 endforeach () 00555 # -------------------------------------------------------------------------- 00556 # generate source code 00557 set (CC) # C++ - build tree and install tree version, constructor block 00558 set (PY_B) # Python - build tree version 00559 set (PY_I) # Python - install tree version 00560 set (PL_B) # Perl - build tree version, hash entries 00561 set (PL_I) # Perl - install tree version, hash entries 00562 set (SH_B) # Bash - build tree version 00563 set (SH_I) # Bash - install tree version 00564 set (SH_A) # Bash - aliases 00565 set (SH_S) # Bash - short aliases 00566 00567 if (CXX) 00568 set (CC "// the following code was automatically generated by the BASIS") 00569 set (CC "${CC}\n // CMake function basis_configure_ExecutableTargetInfo()") 00570 endif () 00571 00572 set (I 0) 00573 list (LENGTH EXECUTABLE_TARGETS N) 00574 while (I LESS N) 00575 # ------------------------------------------------------------------------ 00576 # get executable information 00577 list (GET EXECUTABLE_TARGETS ${I} TARGET_UID) 00578 list (GET BUILD_LOCATIONS ${I} BUILD_LOCATION) 00579 list (GET INSTALL_LOCATIONS ${I} INSTALL_LOCATION) 00580 get_target_property (BUNDLED ${TARGET_UID} BUNDLED) 00581 get_target_property (IMPORTED ${TARGET_UID} IMPORTED) 00582 # insert $(IntDir) for Visual Studio build location 00583 if (CMAKE_GENERATOR MATCHES "Visual Studio") 00584 basis_get_target_type (TYPE ${TARGET_UID}) 00585 if (TYPE MATCHES "^EXECUTABLE$") 00586 get_filename_component (DIRECTORY "${BUILD_LOCATION}" PATH) 00587 get_filename_component (FILENAME "${BUILD_LOCATION}" NAME) 00588 set (BUILD_LOCATION_WITH_INTDIR "${DIRECTORY}/$(IntDir)/${FILENAME}") 00589 else () 00590 set (BUILD_LOCATION_WITH_INTDIR "${BUILD_LOCATION}") 00591 endif () 00592 else () 00593 set (BUILD_LOCATION_WITH_INTDIR "${BUILD_LOCATION}") 00594 endif () 00595 # installation path (relative) to different library paths 00596 foreach (L LIBRARY PYTHON_LIBRARY PERL_LIBRARY BASH_LIBRARY) 00597 if (INSTALL_LOCATION AND (NOT IMPORTED OR BUNDLED)) 00598 file ( 00599 RELATIVE_PATH INSTALL_LOCATION_REL2${L} 00600 "${CMAKE_INSTALL_PREFIX}/${INSTALL_${L}_DIR}/<package>" 00601 "${INSTALL_LOCATION}" 00602 ) 00603 else () 00604 set (INSTALL_LOCATION_REL2${L} "${INSTALL_LOCATION}") 00605 endif () 00606 endforeach () 00607 # target UID including project namespace 00608 if (IMPORTED OR TARGET_UID MATCHES "^\\.") 00609 set (ALIAS "${TARGET_UID}") 00610 elseif (NOT BASIS_USE_FULLY_QUALIFIED_TARGET_UIDS AND BASIS_PROJECT_NAMESPACE_CMAKE) 00611 set (ALIAS "${BASIS_PROJECT_NAMESPACE_CMAKE}.${TARGET_UID}") 00612 endif () 00613 # indentation after dictionary key, i.e., alias 00614 string (LENGTH "${ALIAS}" ALIAS_LENGTH) 00615 math (EXPR NUM "${MAX_ALIAS_LENGTH} - ${ALIAS_LENGTH} + 1") 00616 if (NUM GREATER 1) 00617 string (RANDOM LENGTH ${NUM} ALPHABET " " S) 00618 else () 00619 set (S " ") 00620 endif () 00621 # ------------------------------------------------------------------------ 00622 # C++ 00623 if (CXX) 00624 get_filename_component (EXEC_NAME "${BUILD_LOCATION}" NAME) 00625 get_filename_component (BUILD_DIR "${BUILD_LOCATION}" PATH) 00626 if (INSTALL_LOCATION) 00627 get_filename_component (INSTALL_DIR "${INSTALL_LOCATION}" PATH) 00628 endif () 00629 00630 set (CC "${CC}\n") 00631 set (CC "${CC}\n // ${TARGET_UID}") 00632 set (CC "${CC}\n _exec_names [\"${ALIAS}\"]${S}= \"${EXEC_NAME}\";") 00633 set (CC "${CC}\n _build_dirs [\"${ALIAS}\"]${S}= \"${BUILD_DIR}\";") 00634 set (CC "${CC}\n _install_dirs[\"${ALIAS}\"]${S}= \"${INSTALL_DIR}\";") 00635 endif () 00636 # ------------------------------------------------------------------------ 00637 # Python 00638 if (PYTHON) 00639 set (PY_B "${PY_B} '${ALIAS}':${S}'${BUILD_LOCATION_WITH_INTDIR}',\n") 00640 if (INSTALL_LOCATION) 00641 set (PY_I "${PY_I} '${ALIAS}':${S}'${INSTALL_LOCATION_REL2PYTHON_LIBRARY}',\n") 00642 else () 00643 set (PY_I "${PY_I} '${ALIAS}':${S}'',\n") 00644 endif () 00645 endif () 00646 # ------------------------------------------------------------------------ 00647 # Perl 00648 if (PERL) 00649 if (PL_B) 00650 set (PL_B "${PL_B},\n") 00651 endif () 00652 set (PL_B "${PL_B} '${ALIAS}'${S}=> '${BUILD_LOCATION_WITH_INTDIR}'") 00653 if (PL_I) 00654 set (PL_I "${PL_I},\n") 00655 endif () 00656 if (INSTALL_LOCATION) 00657 set (PL_I "${PL_I} '${ALIAS}'${S}=> '${INSTALL_LOCATION_REL2PERL_LIBRARY}'") 00658 else () 00659 set (PL_I "${PL_I} '${ALIAS}'${S}=> ''") 00660 endif () 00661 endif () 00662 # ------------------------------------------------------------------------ 00663 # Bash 00664 if (BASH) 00665 # hash entry 00666 set (SH_B "${SH_B}\n _basis_executabletargetinfo_add '${ALIAS}'${S}LOCATION '${BUILD_LOCATION}'") 00667 if (INSTALL_LOCATION) 00668 set (SH_I "${SH_I}\n _basis_executabletargetinfo_add '${ALIAS}'${S}LOCATION '${INSTALL_LOCATION_REL2BASH_LIBRARY}'") 00669 else () 00670 set (SH_I "${SH_I}\n _basis_executabletargetinfo_add '${ALIAS}'${S}LOCATION ''") 00671 endif () 00672 # alias 00673 set (SH_A "${SH_A}\n alias '${ALIAS}'=`get_executable_path '${ALIAS}'`") 00674 # short alias (if target belongs to this project) 00675 if (ALIAS MATCHES "^${PROJECT_NAMESPACE_CMAKE_RE}\\.") 00676 basis_get_target_name (TARGET_NAME "${ALIAS}") 00677 set (SH_S "${SH_S}\n alias '${TARGET_NAME}'='${ALIAS}'") 00678 endif () 00679 endif () 00680 # ------------------------------------------------------------------------ 00681 # next executable target 00682 math (EXPR I "${I} + 1") 00683 endwhile () 00684 # -------------------------------------------------------------------------- 00685 # remove unnecessary leading newlines 00686 string (STRIP "${CC}" CC) 00687 string (STRIP "${PY_B}" PY_B) 00688 string (STRIP "${PY_I}" PY_I) 00689 string (STRIP "${PL_B}" PL_B) 00690 string (STRIP "${PL_I}" PL_I) 00691 string (STRIP "${SH_B}" SH_B) 00692 string (STRIP "${SH_I}" SH_I) 00693 string (STRIP "${SH_A}" SH_A) 00694 string (STRIP "${SH_S}" SH_S) 00695 # -------------------------------------------------------------------------- 00696 # return 00697 set (EXECUTABLE_TARGET_INFO_CXX "${CC}" PARENT_SCOPE) 00698 set (EXECUTABLE_TARGET_INFO_PYTHON_B "${PY_B}" PARENT_SCOPE) 00699 set (EXECUTABLE_TARGET_INFO_PYTHON_I "${PY_I}" PARENT_SCOPE) 00700 set (EXECUTABLE_TARGET_INFO_PERL_B "${PL_B}" PARENT_SCOPE) 00701 set (EXECUTABLE_TARGET_INFO_PERL_I "${PL_I}" PARENT_SCOPE) 00702 set (EXECUTABLE_TARGET_INFO_BASH_B "${SH_B}" PARENT_SCOPE) 00703 set (EXECUTABLE_TARGET_INFO_BASH_I "${SH_I}" PARENT_SCOPE) 00704 set (EXECUTABLE_TARGET_INFO_BASH_A "${SH_A}" PARENT_SCOPE) 00705 set (EXECUTABLE_TARGET_INFO_BASH_S "${SH_S}" PARENT_SCOPE) 00706 endfunction () 00707 00708 00709 ## @} 00710 # end of Doxygen group