BASIS  r3148
TargetTools.cmake
Go to the documentation of this file.
00001 ##############################################################################
00002 # @file  TargetTools.cmake
00003 # @brief Functions and macros to add executable and library targets.
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 if (__BASIS_TARGETTOOLS_INCLUDED)
00014   return ()
00015 else ()
00016   set (__BASIS_TARGETTOOLS_INCLUDED TRUE)
00017 endif ()
00018 
00019 
00020 ## @addtogroup CMakeUtilities
00021 #  @{
00022 
00023 
00024 # ============================================================================
00025 # properties
00026 # ============================================================================
00027 
00028 # ----------------------------------------------------------------------------
00029 ## @brief Set properties on a target.
00030 #
00031 # This function replaces CMake's
00032 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set_target_properties">
00033 # set_target_properties()</a> command and extends its functionality.
00034 # In particular, it maps the given target names to the corresponding target UIDs.
00035 #
00036 # @note Due to a bug in CMake (http://www.cmake.org/Bug/view.php?id=12303),
00037 #       except of the first property given directly after the @c PROPERTIES keyword,
00038 #       only properties listed in @c BASIS_PROPERTIES_ON_TARGETS can be set.
00039 #
00040 # @param [in] ARGN List of arguments. See
00041 #                  <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set_target_properties">
00042 #                  set_target_properties()</a>.
00043 #
00044 # @returns Sets the specified properties on the given target.
00045 #
00046 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set_target_properties
00047 #
00048 # @ingroup CMakeAPI
00049 function (basis_set_target_properties)
00050   # convert target names to UIDs
00051   set (TARGET_UIDS)
00052   list (LENGTH ARGN N)
00053   if (N EQUAL 0)
00054     message (FATAL_ERROR "basis_set_target_properties(): Missing arguments!")
00055   endif ()
00056   list (GET ARGN 0 ARG)
00057   while (NOT ARG MATCHES "^PROPERTIES$")
00058     basis_get_target_uid (TARGET_UID "${ARG}")
00059     list (APPEND TARGET_UIDS "${TARGET_UID}")
00060     list (REMOVE_AT ARGN 0)
00061     list (LENGTH ARGN N)
00062     if (N EQUAL 0)
00063       break ()
00064     else ()
00065       list (GET ARGN 0 ARG)
00066     endif ()
00067   endwhile ()
00068   if (NOT ARG MATCHES "^PROPERTIES$")
00069     message (FATAL_ERROR "Missing PROPERTIES argument!")
00070   elseif (NOT TARGET_UIDS)
00071     message (FATAL_ERROR "No target specified!")
00072   endif ()
00073   # remove PROPERTIES keyword
00074   list (REMOVE_AT ARGN 0)
00075   math (EXPR N "${N} - 1")
00076   # set targets properties
00077   #
00078   # Note: By iterating over the properties, the empty property values
00079   #       are correctly passed on to CMake's set_target_properties()
00080   #       command, while
00081   #       _set_target_properties(${TARGET_UIDS} PROPERTIES ${ARGN})
00082   #       (erroneously) discards the empty elements in ARGN.
00083   if (BASIS_DEBUG)
00084     message ("** basis_set_target_properties:")
00085     message ("**   Target(s):  ${TARGET_UIDS}")
00086     message ("**   Properties: [${ARGN}]")
00087   endif ()
00088   while (N GREATER 1)
00089     list (GET ARGN 0 PROPERTY)
00090     list (GET ARGN 1 VALUE)
00091     list (REMOVE_AT ARGN 0 1)
00092     list (LENGTH ARGN N)
00093     # The following loop is only required b/c CMake's ARGV and ARGN
00094     # lists do not support arguments which are themselves lists.
00095     # Therefore, we need a way to decide when the list of values for a
00096     # property is terminated. Hence, we only allow known properties
00097     # to be set, except for the first property where the name follows
00098     # directly after the PROPERTIES keyword.
00099     while (N GREATER 0)
00100       list (GET ARGN 0 ARG)
00101       if (ARG MATCHES "${BASIS_PROPERTIES_ON_TARGETS_RE}")
00102         break ()
00103       endif ()
00104       list (APPEND VALUE "${ARG}")
00105       list (REMOVE_AT ARGN 0)
00106       list (LENGTH ARGN N)
00107     endwhile ()
00108     if (BASIS_DEBUG)
00109       message ("**   -> ${PROPERTY} = [${VALUE}]")
00110     endif ()
00111     # check property name
00112     if (PROPERTY MATCHES "^$") # remember: STREQUAL is buggy and evil!
00113       message (FATAL_ERROR "Empty property name given!")
00114     endif ()
00115     # set target property
00116     _set_target_properties (${TARGET_UIDS} PROPERTIES ${PROPERTY} "${VALUE}")
00117   endwhile ()
00118   # make sure that every property had a corresponding value
00119   if (NOT N EQUAL 0)
00120     message (FATAL_ERROR "No value given for target property ${ARGN}")
00121   endif ()
00122 endfunction ()
00123 
00124 # ----------------------------------------------------------------------------
00125 ## @brief Get value of property set on target.
00126 #
00127 # This function replaces CMake's
00128 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set_target_properties">
00129 # get_target_properties()</a> command and extends its functionality.
00130 # In particular, it maps the given @p TARGET_NAME to the corresponding target UID.
00131 #
00132 # @param [out] VAR         Name of output variable.
00133 # @param [in]  TARGET_NAME Name of build target.
00134 # @param [in]  ARGN        Remaining arguments for
00135 #                          <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:get_target_properties">
00136 #                          get_target_properties()</a>.
00137 #
00138 # @returns Sets @p VAR to the value of the requested property.
00139 #
00140 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:get_target_property
00141 #
00142 # @ingroup CMakeAPI
00143 function (basis_get_target_property VAR TARGET_NAME)
00144   basis_get_target_uid (TARGET_UID "${TARGET_NAME}")
00145   get_target_property (VALUE "${TARGET_UID}" ${ARGN})
00146   set (${VAR} "${VALUE}" PARENT_SCOPE)
00147 endfunction ()
00148 
00149 # ============================================================================
00150 # definitions
00151 # ============================================================================
00152 
00153 # ----------------------------------------------------------------------------
00154 ## @brief Add compile definitions.
00155 #
00156 # This function replaces CMake's
00157 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_definitions">
00158 # add_definitions()</a> command.
00159 #
00160 # @param [in] ARGN List of arguments for
00161 #                  <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_definitions">
00162 #                  add_definitions()</a>.
00163 #
00164 # @returns Adds the given definitions.
00165 #
00166 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_definitions
00167 #
00168 # @ingroup CMakeAPI
00169 function (basis_add_definitions)
00170   add_definitions (${ARGN})
00171 endfunction ()
00172 
00173 # ----------------------------------------------------------------------------
00174 ## @brief Remove previously added compile definitions.
00175 #
00176 # This function replaces CMake's
00177 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:remove_definitions">
00178 # remove_definitions()</a> command.
00179 #
00180 # @param [in] ARGN List of arguments for
00181 #                  <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:remove_definitions">
00182 #                  remove_definitions()</a>.
00183 #
00184 # @returns Removes the specified definitions.
00185 #
00186 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:remove_definition
00187 #
00188 # @ingroup CMakeAPI
00189 function (basis_remove_definitions)
00190   remove_definitions (${ARGN})
00191 endfunction ()
00192 
00193 # ============================================================================
00194 # directories
00195 # ============================================================================
00196 
00197 # ----------------------------------------------------------------------------
00198 ## @brief Add directories to search path for include files.
00199 #
00200 # Overwrites CMake's
00201 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:include_directories">
00202 # include_directories()</a> command. This is required because the
00203 # basis_include_directories() function is not used by other projects in their
00204 # package use files. Therefore, this macro is an alias for
00205 # basis_include_directories().
00206 #
00207 # @param [in] ARGN List of arguments for basis_include_directories().
00208 #
00209 # @returns Adds the given paths to the search path for include files.
00210 #
00211 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:include_directories
00212 macro (include_directories)
00213   basis_include_directories (${ARGN})
00214 endmacro ()
00215 
00216 # ----------------------------------------------------------------------------
00217 ## @brief Add directories to search path for include files.
00218 #
00219 # This function replaces CMake's
00220 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:include_directories">
00221 # include_directories()</a> command. Besides invoking CMake's internal command
00222 # with the given arguments, it updates the @c PROJECT_INCLUDE_DIRECTORIES
00223 # property on the current project (see basis_set_project_property()). This list
00224 # contains a list of all include directories used by a project, regardless of
00225 # the directory in which the basis_include_directories() function was used.
00226 #
00227 # @param ARGN List of arguments for
00228 #             <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:include_directories">
00229 #             include_directories()</a> command.
00230 #
00231 # @returns Nothing.
00232 #
00233 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:include_directories
00234 #
00235 # @ingroup CMakeAPI
00236 function (basis_include_directories)
00237   # CMake's include_directories ()
00238   _include_directories (${ARGN})
00239 
00240   # parse arguments
00241   CMAKE_PARSE_ARGUMENTS (ARGN "AFTER;BEFORE;SYSTEM" "" "" ${ARGN})
00242 
00243   # make relative paths absolute
00244   set (DIRS)
00245   foreach (P IN LISTS ARGN_UNPARSED_ARGUMENTS)
00246     get_filename_component (P "${P}" ABSOLUTE)
00247     list (APPEND DIRS "${P}")
00248   endforeach ()
00249 
00250   if (DIRS)
00251     # append directories to "global" list of include directories
00252     basis_get_project_property (INCLUDE_DIRS PROPERTY PROJECT_INCLUDE_DIRS)
00253     if (BEFORE)
00254       list (INSERT INCLUDE_DIRS 0 ${DIRS})
00255     else ()
00256       list (APPEND INCLUDE_DIRS ${DIRS})
00257     endif ()
00258     if (INCLUDE_DIRS)
00259       list (REMOVE_DUPLICATES INCLUDE_DIRS)
00260     endif ()
00261     if (BASIS_DEBUG)
00262       message ("** basis_include_directories():")
00263       if (BEFORE)
00264         message ("**    Add before:  ${DIRS}")
00265       else ()
00266         message ("**    Add after:   ${DIRS}")
00267       endif ()
00268       if (BASIS_VERBOSE)
00269         message ("**    Directories: ${INCLUDE_DIRS}")
00270       endif ()
00271     endif ()
00272     basis_set_project_property (PROPERTY PROJECT_INCLUDE_DIRS ${INCLUDE_DIRS})
00273   endif ()
00274 endfunction ()
00275 
00276 # ----------------------------------------------------------------------------
00277 ## @brief Add directories to search path for libraries.
00278 #
00279 # Overwrites CMake's
00280 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:link_directories">
00281 # link_directories()</a> command. This is required because the
00282 # basis_link_directories() function is not used by other projects in their
00283 # package use files. Therefore, this macro is an alias for
00284 # basis_link_directories().
00285 #
00286 # @param [in] ARGN List of arguments for basis_link_directories().
00287 #
00288 # @returns Adds the given paths to the search path for libraries.
00289 #
00290 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:link_directories
00291 macro (link_directories)
00292   basis_link_directories (${ARGN})
00293 endmacro ()
00294 
00295 # ----------------------------------------------------------------------------
00296 ## @brief Add directories to search path for libraries.
00297 #
00298 # This function replaces CMake's
00299 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:link_directories">
00300 # link_directories()</a> command. Even though this function yet only invokes
00301 # CMake's internal command, it should be used in BASIS projects to enable the
00302 # extension of this command's functionality as part of BASIS if required.
00303 #
00304 # @param [in] ARGN List of arguments for
00305 #                  <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:link_directories">
00306 #                  link_directories()</a>.
00307 #
00308 # @returns Adds the given paths to the search path for libraries.
00309 #
00310 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:link_directories
00311 #
00312 # @ingroup CMakeAPI
00313 function (basis_link_directories)
00314   # CMake's link_directories() command
00315   _link_directories (${ARGN})
00316   # make relative paths absolute
00317   set (DIRS)
00318   foreach (P IN LISTS ARGN)
00319     get_filename_component (P "${P}" ABSOLUTE)
00320     list (APPEND DIRS "${P}")
00321   endforeach ()
00322   if (DIRS)
00323     # append directories to "global" list of link directories
00324     basis_get_project_property (LINK_DIRS PROPERTY PROJECT_LINK_DIRS)
00325     list (APPEND LINK_DIRS ${DIRS})
00326     if (LINK_DIRS)
00327       list (REMOVE_DUPLICATES LINK_DIRS)
00328     endif ()
00329     if (BASIS_DEBUG)
00330       message ("** basis_link_directories():")
00331       message ("**    Add:         [${DIRS}]")
00332       if (BASIS_VERBOSE)
00333         message ("**    Directories: [${LINK_DIRS}]")
00334       endif ()
00335     endif ()
00336     basis_set_project_property (PROPERTY PROJECT_LINK_DIRS "${LINK_DIRS}")
00337     # if the directories are added by an external project's <Pkg>Use.cmake
00338     # file which is part of the same superbuild as this project, add the
00339     # directories further to the list of directories that may be added to
00340     # the RPATH. see basis_set_target_install_rpath().
00341     if (BUNDLE_PROJECT) # set in basis_use_package()
00342       basis_get_project_property (LINK_DIRS PROPERTY BUNDLE_LINK_DIRS)
00343       list (APPEND LINK_DIRS ${DIRS})
00344       if (LINK_DIRS)
00345         list (REMOVE_DUPLICATES LINK_DIRS)
00346       endif ()
00347       basis_set_project_property (PROPERTY BUNDLE_LINK_DIRS "${LINK_DIRS}")
00348     endif ()
00349   endif ()
00350 endfunction ()
00351 
00352 # ============================================================================
00353 # dependencies
00354 # ============================================================================
00355 
00356 # ----------------------------------------------------------------------------
00357 ## @brief Add dependencies to build target.
00358 #
00359 # This function replaces CMake's
00360 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_dependencies">
00361 # add_dependencies()</a> command and extends its functionality.
00362 # In particular, it maps the given target names to the corresponding target UIDs.
00363 #
00364 # @param [in] ARGN Arguments for
00365 #                  <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_dependencies">
00366 #                  add_dependencies()</a>.
00367 #
00368 # @returns Adds the given dependencies of the specified build target.
00369 #
00370 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_dependencies
00371 #
00372 # @ingroup CMakeAPI
00373 function (basis_add_dependencies)
00374   set (ARGS)
00375   foreach (ARG ${ARGN})
00376     basis_get_target_uid (UID "${ARG}")
00377     if (TARGET "${UID}")
00378       list (APPEND ARGS "${UID}")
00379     else ()
00380       list (APPEND ARGS "${ARG}")
00381     endif ()
00382   endforeach ()
00383   add_dependencies (${ARGS})
00384 endfunction ()
00385 
00386 # ----------------------------------------------------------------------------
00387 ## @brief Add link dependencies to build target.
00388 #
00389 # This function replaces CMake's
00390 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:target_link_libraries">
00391 # target_link_libraries()</a> command.
00392 #
00393 # The main reason for replacing this function is to treat libraries such as
00394 # MEX-files which are supposed to be compiled into a MATLAB executable added
00395 # by basis_add_executable() special. In this case, these libraries are added
00396 # to the LINK_DEPENDS property of the given MATLAB Compiler target. Similarly,
00397 # executable scripts and modules written in a scripting language may depend
00398 # on other modules.
00399 #
00400 # Another reason is the mapping of build target names to fully-qualified
00401 # build target names as used by BASIS (see basis_get_target_uid()).
00402 #
00403 # Example:
00404 # @code
00405 # basis_add_library (MyMEXFunc MEX myfunc.c)
00406 # basis_add_executable (MyMATLABApp main.m)
00407 # basis_target_link_libraries (MyMATLABApp MyMEXFunc OtherMEXFunc.mexa64)
00408 # @endcode
00409 #
00410 # @param [in] TARGET_NAME Name of the target.
00411 # @param [in] ARGN        Link libraries.
00412 #
00413 # @returns Adds link dependencies to the specified build target.
00414 #          For custom targets, the given libraries are added to the
00415 #          @c LINK_DEPENDS property of these targets, in particular.
00416 #
00417 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:target_link_libraries
00418 #
00419 # @ingroup CMakeAPI
00420 function (basis_target_link_libraries TARGET_NAME)
00421   basis_get_target_uid (TARGET_UID "${TARGET_NAME}")
00422   if (NOT TARGET "${TARGET_UID}")
00423     message (FATAL_ERROR "basis_target_link_libraries(): Unknown target ${TARGET_UID}.")
00424   endif ()
00425   # get type of named target
00426   get_target_property (BASIS_TYPE ${TARGET_UID} BASIS_TYPE)
00427   # substitute non-fully qualified target names
00428   set (ARGS)
00429   foreach (ARG ${ARGN})
00430     basis_get_target_uid (UID "${ARG}")
00431     if (TARGET "${UID}")
00432       if (UID MATCHES "^${TARGET_UID}$")
00433         message (FATAL_ERROR "Cannot add link library as dependency of itself!")
00434       endif ()
00435       list (APPEND ARGS "${UID}")
00436     else ()
00437       list (APPEND ARGS "${ARG}")
00438     endif ()
00439   endforeach ()
00440   # get current link libraries
00441   if (BASIS_TYPE MATCHES "^EXECUTABLE$|^(SHARED|STATIC|MODULE)_LIBRARY$")
00442     get_target_property (DEPENDS ${TARGET_UID} BASIS_LINK_DEPENDS)
00443   else ()
00444     get_target_property (DEPENDS ${TARGET_UID} LINK_DEPENDS)
00445   endif ()
00446   if (NOT DEPENDS)
00447     set (DEPENDS)
00448   endif ()
00449   # note that MCC does itself a dependency check and in case of scripts
00450   # the basis_get_target_link_libraries() function is used
00451   if (BASIS_TYPE MATCHES "MCC|SCRIPT")
00452     list (APPEND DEPENDS ${ARGS})
00453   # otherwise
00454   else ()
00455     list (APPEND DEPENDS ${ARGS})
00456     # pull implicit dependencies (e.g., ITK uses this)
00457     set (DEPENDENCY_ADDED 1)
00458     while (DEPENDENCY_ADDED)
00459       set (DEPENDENCY_ADDED 0)
00460       foreach (LIB IN LISTS DEPENDS)
00461         foreach (LIB_DEPEND IN LISTS ${LIB}_LIB_DEPENDS)
00462           if (NOT LIB_DEPEND MATCHES "^$|^general$")
00463             string (REGEX REPLACE "^-l" "" LIB_DEPEND "${LIB_DEPEND}")
00464             list (FIND DEPENDS ${LIB_DEPEND} IDX)
00465             if (IDX EQUAL -1)
00466               list (APPEND DEPENDS ${LIB_DEPEND})
00467               set (DEPENDENCY_ADDED 1)
00468             endif ()
00469           endif ()
00470         endforeach ()
00471       endforeach ()
00472     endwhile ()
00473   endif ()
00474   # update LINK_DEPENDS
00475   if (BASIS_TYPE MATCHES "^EXECUTABLE$|^(SHARED|STATIC|MODULE)_LIBRARY$")
00476     _set_target_properties (${TARGET_UID} PROPERTIES BASIS_LINK_DEPENDS "${DEPENDS}")
00477     target_link_libraries (${TARGET_UID} ${ARGS})
00478   else ()
00479     # FIXME cannot use LINK_DEPENDS for CMake targets as these depends are
00480     #       otherwise added as is to the Makefile. therefore, consider renaming
00481     #       LINK_DEPENDS in general to BASIS_LINK_DEPENDS.
00482     _set_target_properties (${TARGET_UID} PROPERTIES LINK_DEPENDS "${DEPENDS}")
00483   endif ()
00484 endfunction ()
00485 
00486 # ============================================================================
00487 # add targets
00488 # ============================================================================
00489 
00490 # ----------------------------------------------------------------------------
00491 ## @brief Add custom target.
00492 macro (basis_add_custom_target TARGET_NAME)
00493   basis_check_target_name ("${TARGET_NAME}")
00494   basis_make_target_uid (_UID "${TARGET_NAME}")
00495   add_custom_target (${_UID} ${ARGN})
00496   unset (_UID)
00497 endmacro ()
00498 
00499 # ----------------------------------------------------------------------------
00500 ## @brief Add executable target.
00501 #
00502 # This is the main function to add an executable target to the build system,
00503 # where an executable can be a binary file or a script written in a scripting
00504 # language. In general we refer to any output file which is part of the software
00505 # (i.e., excluding configuration files) and which can be executed
00506 # (e.g., a binary file in the ELF format) or interpreted (e.g., a Python script)
00507 # directly, as executable file. Natively, CMake supports only executables built
00508 # from C/C++ source code files. This function extends CMake's capabilities
00509 # by adding custom build commands for non-natively supported programming
00510 # languages and further standardizes the build of executable targets.
00511 # For example, by default, it is not necessary to specify installation rules
00512 # separately as these are added by this function already (see below).
00513 #
00514 # @par Programming languages
00515 # Besides adding usual executable targets build by the set <tt>C/CXX</tt>
00516 # language compiler, this function inspects the list of source files given and
00517 # detects whether this list contains sources which need to be build using a
00518 # different compiler. In particular, it supports the following languages:
00519 # @n
00520 # <table border="0">
00521 #   <tr>
00522 #     @tp @b CXX @endtp
00523 #     <td>The default behavior, adding an executable target build from C/C++
00524 #         source code. The target is added via CMake's add_executable() command.</td>
00525 #   </tr>
00526 #   <tr>
00527 #     @tp <b>PYTHON</b>|<b>JYTHON</b>|<b>PERL</b>|<b>BASH</b> @endtp
00528 #     <td>Executables written in one of the named scripting languages are built by
00529 #         configuring and/or copying the script files to the build tree and
00530 #         installation tree, respectively. During the build step, certain strings
00531 #         of the form \@VARIABLE\@ are substituted by the values set during the
00532 #         configure step. How these CMake variables are set is specified by a
00533 #         so-called script configuration, which itself is either a CMake script
00534 #         file or a string of CMake code set as value of the @c COMPILE_DEFINITIONS
00535 #         property of the executable target.</td>
00536 #   </tr>
00537 #   <tr>
00538 #     @tp @b MATLAB @endtp
00539 #     <td>Standalone application built from MATLAB sources using the
00540 #         MATLAB Compiler (mcc). This language option is used when the list
00541 #         of source files contains one or more *.m files. A custom target is
00542 #         added which depends on custom command(s) that build the executable.</td>
00543 #         @n@n
00544 #         Attention: The *.m file with the entry point/main function of the
00545 #                    executable has to be given before any other *.m file.
00546 #   </tr>
00547 # </table>
00548 #
00549 # @par Helper functions
00550 # If the programming language of the input source files is not specified
00551 # explicitly by providing the @p LANGUAGE argument, the extensions of the
00552 # source files and if necessary the first line of script files are inspected
00553 # by the basis_get_source_language() function. Once the programming language is
00554 # known, this function invokes the proper subcommand which adds the respective
00555 # build target. In particular, it calls basis_add_executable_target() for C++
00556 # sources (.cxx), basis_add_mcc_target() for MATLAB scripts (.m), and
00557 # basis_add_script() for all other source files.
00558 #
00559 # @note DO NOT use the mentioned subcommands directly. Always use
00560 #       basis_add_executable() to add an executable target to your project.
00561 #       Only refer to the documentation of the subcommands to learn about the
00562 #       available options of the particular subcommand and considered target
00563 #       properties.
00564 #
00565 # @par Output directories
00566 # The built executable file is output to the @c BINARY_RUNTIME_DIR or
00567 # @c BINARY_LIBEXEC_DIR if the @p LIBEXEC option is given.
00568 # If this function is used within the @c PROJECT_TESTING_DIR, however,
00569 # the built executable is output to the @c TESTING_RUNTIME_DIR or
00570 # @c TESTING_LIBEXEC_DIR instead.
00571 #
00572 # @par Installation
00573 # An install command for the added executable target is added by this function
00574 # as well. The executable will be installed as part of the specified @p COMPONENT
00575 # in the directory @c INSTALL_RUNTIME_DIR or @c INSTALL_LIBEXEC_DIR if the option
00576 # @p LIBEXEC is given. Executable targets are exported by default such that they
00577 # can be imported by other CMake-aware projects by including the CMake
00578 # configuration file of this package (&lt;Package&gt;Config.cmake file).
00579 # No installation rules are added, however, if this function is used within the
00580 # @c PROJECT_TESTING_DIR or if "none" (case-insensitive) is given as
00581 # @p DESTINATION. Test executables are further only exported as part of the
00582 # build tree, but not the installation as they are by default not installed.
00583 #
00584 # @param [in] TARGET_NAME Name of the target. If an existing source file is given
00585 #                         as first argument, it is added to the list of source files
00586 #                         and the build target name is derived from the name of this file.
00587 # @param [in] ARGN        This argument list is parsed and the following
00588 #                         arguments are extracted, all other arguments are passed
00589 #                         on to add_executable() or the respective custom
00590 #                         commands used to add an executable build target.
00591 # @par
00592 # <table border="0">
00593 #   <tr>
00594 #     @tp @b COMPONENT name @endtp
00595 #     <td>Name of component as part of which this executable will be installed
00596 #         if the specified @c DESTINATION is not "none".
00597 #         (default: @c BASIS_RUNTIME_COMPONENT)</td>
00598 #   </tr>
00599 #   <tr>
00600 #     @tp @b DESTINATION dir @endtp
00601 #     <td>Installation directory relative to @c CMAKE_INSTALL_PREFIX.
00602 #         If "none" (case-insensitive) is given as argument, no default
00603 #         installation rules are added for this executable target.
00604 #         (default: @c INSTALL_RUNTIME_DIR or @c INSTALL_LIBEXEC_DIR
00605 #         if the @p LIBEXEC option is given)</td>
00606 #   </tr>
00607 #   <tr>
00608 #     @tp @b LANGUAGE lang @endtp
00609 #     <td>Programming language in which source files are written (case-insensitive).
00610 #         If not specified, the programming language is derived from the file name
00611 #         extensions of the source files and, if applicable, the shebang directive
00612 #         on the first line of the script file. If the programming language could
00613 #         not be detected automatically, check the file name extensions of the
00614 #         source files and whether no unrecognized additional arguments were given
00615 #         or specify the programming language using this option.
00616 #         (default: auto-detected)</td>
00617 #   </tr>
00618 #   <tr>
00619 #     @tp @b LIBEXEC @endtp
00620 #     <td>Specifies that the built executable is an auxiliary executable which
00621 #         is only called by other executables. (default: @c FALSE)</td>
00622 #   </tr>
00623 #   <tr>
00624 #     @tp @b [NO]EXPORT @endtp
00625 #     <td>Whether to export this target. (default: @c TRUE)</td>
00626 #   </tr>
00627 #   <tr>
00628 #     @tp @b NO_BASIS_UTILITIES @endtp
00629 #     <td>Specify that the BASIS utilities are not used by this executable and hence
00630 #         no link dependency on the BASIS utilities shall be added.
00631 #         (default: @c NOT @c BASIS_UTILITIES)</td>
00632 #   </tr>
00633 #   <tr>
00634 #     @tp @b USE_BASIS_UTILITIES @endtp
00635 #     <td>Specify that the BASIS utilities are used and required by this executable
00636 #         and hence a link dependency on the BASIS utilities has to be added.
00637 #         (default: @c BASIS_UTILITIES)</td>
00638 #   </tr>
00639 # </table>
00640 #
00641 # @returns Adds an executable build target. In case of an executable which is
00642 #          not build from C++ source files, the function basis_finalize_targets()
00643 #          has to be invoked to finalize the addition of the custom build target.
00644 #          This is done at the end of the basis_project_impl() macro.
00645 #
00646 # @sa basis_add_executable_target()
00647 # @sa basis_add_script()
00648 # @sa basis_add_mcc_target()
00649 #
00650 # @ingroup CMakeAPI
00651 function (basis_add_executable TARGET_NAME)
00652   # --------------------------------------------------------------------------
00653   # parse arguments
00654   CMAKE_PARSE_ARGUMENTS (
00655     ARGN
00656       "EXECUTABLE;LIBEXEC;NO_BASIS_UTILITIES;USE_BASIS_UTILITIES;EXPORT;NOEXPORT"
00657       "COMPONENT;DESTINATION;LANGUAGE"
00658       ""
00659     ${ARGN}
00660   )
00661   # derive target name from path if existing source path is given as first argument instead
00662   # and get list of library source files
00663   get_filename_component (S "${TARGET_NAME}" ABSOLUTE)
00664   if (IS_DIRECTORY "${S}" AND NOT ARGN_UNPARSED_ARGUMENTS)
00665     set (SOURCES "${S}")
00666     basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE)
00667   elseif (EXISTS "${S}" AND NOT IS_DIRECTORY "${S}" OR (NOT S MATCHES "\\.in$" AND EXISTS "${S}.in" AND NOT IS_DIRECTORY "${S}.in"))
00668     set (SOURCES "${S}")
00669     basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE)
00670   else ()
00671     set (SOURCES)
00672   endif ()
00673   if (ARGN_UNPARSED_ARGUMENTS)
00674     list (APPEND SOURCES ${ARGN_UNPARSED_ARGUMENTS})
00675   endif ()
00676   # --------------------------------------------------------------------------
00677   # make target UID
00678   basis_check_target_name ("${TARGET_NAME}")
00679   basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
00680   # --------------------------------------------------------------------------
00681   # process globbing expressions to get complete list of source files
00682   basis_add_glob_target (${TARGET_UID} SOURCES ${SOURCES})
00683   # --------------------------------------------------------------------------
00684   # determine programming language
00685   if (NOT ARGN_LANGUAGE)
00686     basis_get_source_language (ARGN_LANGUAGE ${SOURCES})
00687     if (ARGN_LANGUAGE MATCHES "AMBIGUOUS|UNKNOWN")
00688       message ("Target ${TARGET_UID}: Given source code files:")
00689       foreach (SOURCE IN LISTS SOURCES)
00690         message ("  ${SOURCE}")
00691       endforeach ()
00692       if (ARGN_LANGUAGE MATCHES "AMBIGUOUS")
00693         message (FATAL_ERROR "Target ${TARGET_UID}: Ambiguous source code files! Try to set LANGUAGE manually and make sure that no unknown option was given.")
00694       elseif (ARGN_LANGUAGE MATCHES "UNKNOWN")
00695         message (FATAL_ERROR "Target ${TARGET_UID}: Unknown source code language! Try to set LANGUAGE manually and make sure that no unknown option was given.")
00696       endif ()
00697     endif ()
00698   endif ()
00699   string (TOUPPER "${ARGN_LANGUAGE}" ARGN_LANGUAGE)
00700   # --------------------------------------------------------------------------
00701   # prepare arguments for subcommand
00702   foreach (ARG IN LISTS ARGN_UNPARSED_ARGUMENTS)
00703     list (REMOVE_ITEM ARGN "${ARG}")
00704   endforeach ()
00705   list (APPEND ARGN ${SOURCES})
00706   # --------------------------------------------------------------------------
00707   # C++
00708   if (ARGN_LANGUAGE MATCHES "CXX")
00709     basis_add_executable_target (${TARGET_NAME} ${ARGN})
00710   # --------------------------------------------------------------------------
00711   # MATLAB
00712   elseif (ARGN_LANGUAGE MATCHES "MATLAB")
00713     if (ARGN_LIBEXEC)
00714       list (REMOVE_ITEM ARGN LIBEXEC)
00715       basis_add_mcc_target (${TARGET_NAME} LIBEXEC ${ARGN})
00716     else ()
00717       list (REMOVE_ITEM ARGN EXECUTABLE)
00718       basis_add_mcc_target (${TARGET_NAME} EXECUTABLE ${ARGN})
00719     endif ()
00720   # --------------------------------------------------------------------------
00721   # others
00722   else ()
00723     if (ARGN_LIBEXEC)
00724       list (REMOVE_ITEM ARGN LIBEXEC)
00725       basis_add_script (${TARGET_NAME} LIBEXEC ${ARGN})
00726     else ()
00727       list (REMOVE_ITEM ARGN EXECUTABLE)
00728       basis_add_script (${TARGET_NAME} EXECUTABLE ${ARGN})
00729     endif ()
00730   endif ()
00731   # --------------------------------------------------------------------------
00732   # re-glob source files before each build (if necessary)
00733   if (TARGET __${TARGET_UID})
00734     if (TARGET _${TARGET_UID})
00735       add_dependencies (_${TARGET_UID} __${TARGET_UID})
00736     endif ()
00737     add_dependencies (${TARGET_UID} __${TARGET_UID})
00738   endif ()
00739 endfunction ()
00740 
00741 # ----------------------------------------------------------------------------
00742 ## @brief Add library target.
00743 #
00744 # This is the main function to add a library target to the build system, where
00745 # a library can be a binary archive, shared library, a MEX-file or module(s)
00746 # written in a scripting language. In general we refer to any output file which
00747 # is part of the software (i.e., excluding configuration files), but cannot be
00748 # executed (e.g., a binary file in the ELF format) or interpreted
00749 # (e.g., a Python module) directly, as library file. Natively, CMake supports only
00750 # libraries built from C/C++ source code files. This function extends CMake's
00751 # capabilities by adding custom build commands for non-natively supported
00752 # programming languages and further standardizes the build of library targets.
00753 # For example, by default, it is not necessary to specify installation rules
00754 # separately as these are added by this function already (see below).
00755 #
00756 # @par Programming languages
00757 # Besides adding usual library targets built from C/C++ source code files,
00758 # this function can also add custom build targets for libraries implemented
00759 # in other programming languages. It therefore tries to detect the programming
00760 # language of the given source code files and delegates the addition of the
00761 # build target to the proper helper functions. It in particular supports the
00762 # following languages:
00763 # @n
00764 # <table border="0">
00765 #   <tr>
00766 #     @tp @b CXX @endtp
00767 #     <td>Source files written in C/C++ are by default built into either
00768 #         @p STATIC, @p SHARED, or @p MODULE libraries. If the @p MEX option
00769 #         is given, however, a MEX-file (a shared library) is build using
00770 #         the MEX script instead of using the default C++ compiler directly.</td>
00771 #   </tr>
00772 #   <tr>
00773 #     @tp <b>PYTHON</b>|<b>JYTHON</b>|<b>PERL</b>|<b>BASH</b> @endtp
00774 #     <td>Modules written in one of the named scripting languages are built similar
00775 #         to executable scripts except that the file name extension is preserved
00776 #         and no executable file permission is set on Unix. These modules are
00777 #         intended for import/inclusion in other modules or executables written
00778 #         in the particular scripting language only.</td>
00779 #   </tr>
00780 #   <tr>
00781 #     @tp @b MATLAB @endtp
00782 #     <td>Libraries of M-files or shared libraries built using the MATLAB Compiler (mcc).
00783 #         This language option is used when the list of source files contains one or
00784 #         more *.m files. A custom target is added which depends on custom command(s)
00785 #         that build the library. If the type of the library is @c SHARED, a shared
00786 #         library is build using the MATLAB Compiler. Otherwise, the M-files are
00787 #         configured and installed such that they can be used in MATLAB.</td>
00788 #   </tr>
00789 # </table>
00790 #
00791 # @par Helper functions
00792 # If the programming language of the input source files is not specified
00793 # explicitly by providing the @p LANGUAGE argument, the extensions of the
00794 # source files are inspected using basis_get_source_language(). Once the
00795 # programming language is known, this function invokes the proper subcommand.
00796 # In particular, it calls basis_add_library_target() for C++ sources (.cxx)
00797 # if the target is not a MEX-file target, basis_add_mex_file() for C++ sources
00798 # if the @p MEX option is given, basis_add_mcc_target() for MATLAB scripts (.m),
00799 # and basis_add_script_library() for all other source files.
00800 #
00801 # @note DO NOT use the mentioned subcommands directly. Always use
00802 #       basis_add_library() to add a library target to your project. Only refer
00803 #       to the documentation of the subcommands to learn about the available
00804 #       options of the particular subcommand and the considered target properties.
00805 #
00806 # @par Output directories
00807 # In case of modules written in a scripting language, the libraries are output to
00808 # the <tt>BINARY_&lt;LANGUAGE&gt;_LIBRARY_DIR</tt> if defined. Otherwise,
00809 # the built libraries are output to the @c BINARY_RUNTIME_DIR, @c BINARY_LIBRARY_DIR,
00810 # and/or @c BINARY_ARCHIVE_DIR. If this command is used within the @c PROJECT_TESTING_DIR,
00811 # however, the files are output to the corresponding directories in the testing tree,
00812 # instead.
00813 #
00814 # @par Installation
00815 # An installation rule for the added library target is added by this function
00816 # if the destination is not "none" (case-insensitive). Runtime libraries are
00817 # installed as part of the @p RUNTIME_COMPONENT to the @p RUNTIME_DESTINATION.
00818 # Library components are installed as part of the @p LIBRARY_COMPONENT to the
00819 # @p LIBRARY_DESTINATION. Library targets are further exported such that they
00820 # can be imported by other CMake-aware projects by including the CMake
00821 # configuration file of this package (&lt;Package&gt;Config.cmake file).
00822 # If this function is used within the @c PROJECT_TESTING_DIR, however, no
00823 # installation rules are added. Test library targets are further only exported
00824 # as part of the build tree.
00825 #
00826 # @par Example
00827 # @code
00828 # basis_add_library (MyLib1 STATIC mylib.cxx)
00829 # basis_add_library (MyLib2 STATIC mylib.cxx COMPONENT dev)
00830 #
00831 # basis_add_library (
00832 #   MyLib3 SHARED mylib.cxx
00833 #   RUNTIME_COMPONENT bin
00834 #   LIBRARY_COMPONENT dev
00835 # )
00836 #
00837 # basis_add_library (MyMex MEX mymex.cxx)
00838 # basis_add_library (PythonModule MyModule.py.in)
00839 # basis_add_library (ShellModule MODULE MyModule.sh.in)
00840 # @endcode
00841 #
00842 # @param [in] TARGET_NAME Name of build target. If an existing file is given as
00843 #                         argument, it is added to the list of source files and
00844 #                         the target name is derived from the name of this file.
00845 # @param [in] ARGN        This argument list is parsed and the following
00846 #                         arguments are extracted. All unparsed arguments are
00847 #                         treated as source files.
00848 # @par
00849 # <table border="0">
00850 #   <tr>
00851 #     @tp <b>STATIC</b>|<b>SHARED</b>|<b>MODULE</b>|<b>MEX</b> @endtp
00852 #     <td>Type of the library. (default: @c SHARED for C++ libraries if
00853 #         @c BUILD_SHARED_LIBS evaluates to true or @c STATIC otherwise,
00854 #         and @c MODULE in all other cases)</td>
00855 #   </tr>
00856 #   <tr>
00857 #     @tp @b COMPONENT name @endtp
00858 #     <td>Name of component as part of which this library will be installed
00859 #         if the @c RUNTIME_DESTINATION or @c LIBRARY_DESTINATION is not "none".
00860 #         Used only if @p RUNTIME_COMPONENT or @p LIBRARY_COMPONENT not specified.
00861 #         (default: see @p RUNTIME_COMPONENT and @p LIBRARY_COMPONENT)</td>
00862 #   </tr>
00863 #   <tr>
00864 #     @tp @b DESTINATION dir @endtp
00865 #     <td>Installation directory for runtime and library component relative
00866 #         to @c CMAKE_INSTALL_PREFIX. Used only if @p RUNTIME_DESTINATION or
00867 #         @p LIBRARY_DESTINATION not specified. If "none" (case-insensitive)
00868 #         is given as argument, no default installation rules are added.
00869 #         (default: see @p RUNTIME_DESTINATION and @p LIBRARY_DESTINATION)</td>
00870 #   </tr>
00871 #   <tr>
00872 #     @tp @b LANGUAGE lang @endtp
00873 #     <td>Programming language in which source files are written (case-insensitive).
00874 #         If not specified, the programming language is derived from the file name
00875 #         extensions of the source files and, if applicable, the shebang directive
00876 #         on the first line of the script file. If the programming language could
00877 #         not be detected automatically, check the file name extensions of the
00878 #         source files and whether no unrecognized additional arguments were given
00879 #         or specify the programming language using this option.
00880 #         (default: auto-detected)</td>
00881 #   </tr>
00882 #   <tr>
00883 #     @tp @b LIBRARY_COMPONENT name @endtp
00884 #     <td>Name of component as part of which import/static library will be intalled
00885 #         if @c LIBRARY_DESTINATION is not "none".
00886 #         (default: @c COMPONENT if specified or @c BASIS_LIBRARY_COMPONENT otherwise)</td>
00887 #   </tr>
00888 #   <tr>
00889 #     @tp @b LIBRARY_DESTINATION dir @endtp
00890 #     <td>Installation directory of the library component relative to
00891 #         @c CMAKE_INSTALL_PREFIX. If "none" (case-insensitive) is given as argument,
00892 #         no installation rule for the library component is added.
00893 #         (default: @c INSTALL_ARCHIVE_DIR)</td>
00894 #   </tr>
00895 #   <tr>
00896 #     @tp @b RUNTIME_COMPONENT name @endtp
00897 #     <td>Name of component as part of which runtime library will be installed
00898 #         if @c RUNTIME_DESTINATION is not "none".
00899 #         (default: @c COMPONENT if specified or @c BASIS_RUNTIME_COMPONENT otherwise)</td>
00900 #   </tr>
00901 #   <tr>
00902 #     @tp @b RUNTIME_DESTINATION dir @endtp
00903 #     <td>Installation directory of the runtime component relative to
00904 #         @c CMAKE_INSTALL_PREFIX. If "none" (case-insensitive) is given as argument,
00905 #         no installation rule for the runtime library is added.
00906 #         (default: @c INSTALL_LIBRARY_DIR on Unix or @c INSTALL_RUNTIME_DIR Windows)</td>
00907 #   </tr>
00908 #   <tr>
00909 #     @tp @b [NO]EXPORT @endtp
00910 #     <td>Whether to export this target. (default: @c TRUE)</td>
00911 #   </tr>
00912 #   <tr>
00913 #     @tp @b NO_BASIS_UTILITIES @endtp
00914 #     <td>Specify that the BASIS utilities are not used by this executable and hence
00915 #         no link dependency on the BASIS utilities shall be added.
00916 #         (default: @c NOT @c BASIS_UTILITIES)</td>
00917 #   </tr>
00918 #   <tr>
00919 #     @tp @b USE_BASIS_UTILITIES @endtp
00920 #     <td>Specify that the BASIS utilities are used and required by this executable
00921 #         and hence a link dependency on the BASIS utilities has to be added.
00922 #         (default: @c BASIS_UTILITIES)</td>
00923 #   </tr>
00924 # </table>
00925 #
00926 # @returns Adds a library build target. In case of a library not written in C++
00927 #          or MEX-file targets, basis_finalize_targets() has to be invoked
00928 #          to finalize the addition of the build target(s). This is done
00929 #          at the end of the basis_project_impl() macro.
00930 #
00931 # @sa basis_add_library_target()
00932 # @sa basis_add_script_library()
00933 # @sa basis_add_mex_file()
00934 # @sa basis_add_mcc_target()
00935 #
00936 # @ingroup CMakeAPI
00937 function (basis_add_library TARGET_NAME)
00938   # --------------------------------------------------------------------------
00939   # parse arguments
00940   CMAKE_PARSE_ARGUMENTS (
00941     ARGN
00942       "STATIC;SHARED;MODULE;MEX;USE_BASIS_UTILITIES;NO_BASIS_UTILITIES;EXPORT;NOEXPORT"
00943       "COMPONENT;RUNTIME_COMPONENT;LIBRARY_COMPONENT;DESTINATION;RUNTIME_DESTINATION;LIBRARY_DESTINATION;LANGUAGE"
00944       ""
00945     ${ARGN}
00946   )
00947   # derive target name from path if existing source path is given as first argument instead
00948   # and get list of library source files
00949   get_filename_component (S "${TARGET_NAME}" ABSOLUTE)
00950   if (IS_DIRECTORY "${S}" AND NOT ARGN_UNPARSED_ARGUMENTS)
00951     set (SOURCES "${S}")
00952     basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME)
00953   elseif (EXISTS "${S}" AND NOT IS_DIRECTORY "${S}" OR (NOT S MATCHES "\\.in$" AND EXISTS "${S}.in" AND NOT IS_DIRECTORY "${S}.in"))
00954     set (SOURCES "${S}")
00955     if (ARGN_MEX)
00956       basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE)
00957     else ()
00958       basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME)
00959     endif ()
00960   else ()
00961     set (SOURCES)
00962   endif ()
00963   if (ARGN_UNPARSED_ARGUMENTS)
00964     list (APPEND SOURCES ${ARGN_UNPARSED_ARGUMENTS})
00965   endif ()
00966   # --------------------------------------------------------------------------
00967   # make target UID
00968   basis_check_target_name ("${TARGET_NAME}")
00969   basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
00970   # --------------------------------------------------------------------------
00971   # process globbing expressions to get complete list of source files
00972   basis_add_glob_target (${TARGET_UID} SOURCES ${SOURCES})
00973   # --------------------------------------------------------------------------
00974   # determine programming language
00975   if (NOT ARGN_LANGUAGE)
00976     basis_get_source_language (ARGN_LANGUAGE ${SOURCES})
00977     if (ARGN_LANGUAGE MATCHES "AMBIGUOUS|UNKNOWN")
00978       message ("Target ${TARGET_UID}: Given source code files:")
00979       foreach (SOURCE IN LISTS SOURCES)
00980         message ("  ${SOURCE}")
00981       endforeach ()
00982       if (ARGN_LANGUAGE MATCHES "AMBIGUOUS")
00983         message (FATAL_ERROR "Target ${TARGET_UID}: Ambiguous source code files! Try to set LANGUAGE manually and make sure that no unknown option was given.")
00984       elseif (ARGN_LANGUAGE MATCHES "UNKNOWN")
00985         message (FATAL_ERROR "Target ${TARGET_UID}: Unknown source code language! Try to set LANGUAGE manually and make sure that no unknown option was given.")
00986       endif ()
00987     endif ()
00988   endif ()
00989   string (TOUPPER "${ARGN_LANGUAGE}" ARGN_LANGUAGE)
00990   # --------------------------------------------------------------------------
00991   # prepare arguments for subcommand
00992   foreach (ARG IN LISTS ARGN_UNPARSED_ARGUMENTS)
00993     list (REMOVE_ITEM ARGN "${ARG}")
00994   endforeach ()
00995   list (APPEND ARGN ${SOURCES})
00996   # --------------------------------------------------------------------------
00997   # C++
00998   if (ARGN_LANGUAGE MATCHES "CXX")
00999     # MEX-file
01000     if (ARGN_MEX)
01001       if (ARGN_STATIC)
01002         message (FATAL_ERROR "Target ${TARGET_UID}: Invalid library type! Only modules or shared libraries can be built by the MEX script.")
01003       endif ()
01004       list (REMOVE_ITEM ARGN MODULE)
01005       list (REMOVE_ITEM ARGN SHARED)
01006       list (REMOVE_ITEM ARGN MEX)
01007       basis_add_mex_file (${TARGET_NAME} ${ARGN})
01008     # library
01009     else ()
01010       basis_add_library_target (${TARGET_NAME} ${ARGN})
01011     endif ()
01012   # --------------------------------------------------------------------------
01013   # MATLAB
01014   elseif (ARGN_LANGUAGE MATCHES "MATLAB")
01015     if (ARGN_STATIC OR ARGN_MEX)
01016       message (FATAL_ERROR "Target ${TARGET_UID}: Invalid library type! Only shared libraries can be built by the MATLAB Compiler.")
01017     endif ()
01018     if (ARGN_SHARED)
01019       list (REMOVE_ITEM ARGN SHARED)
01020       basis_add_mcc_target (${TARGET_NAME} SHARED ${ARGN})
01021     else ()
01022       list (REMOVE_ITEM ARGN MODULE) # optional
01023       basis_add_script_library (${TARGET_NAME} ${ARGN})
01024     endif ()
01025   # --------------------------------------------------------------------------
01026   # other
01027   else ()
01028     if (ARGN_STATIC OR ARGN_SHARED OR ARGN_MEX)
01029       message (FATAL_ERROR "Target ${TARGET_UID}: Invalid library type! Only modules can be built from scripts.")
01030     endif ()
01031     list (REMOVE_ITEM ARGN MODULE)
01032     basis_add_script_library (${TARGET_NAME} ${ARGN})
01033   endif ()
01034   # --------------------------------------------------------------------------
01035   # re-glob source files before each build (if necessary)
01036   if (TARGET __${TARGET_UID})
01037     add_dependencies (${TARGET_UID} __${TARGET_UID})
01038   endif ()
01039 endfunction ()
01040 
01041 # ----------------------------------------------------------------------------
01042 ## @brief Add single arbitrary or executable script.
01043 #
01044 # @note This function should not be used directly for executable scripts or
01045 #       module libraries. Use basis_add_executable() or basis_add_library()
01046 #       in such (most) cases instead.
01047 #
01048 # This function can be used to add a single arbitrary script file (i.e., any
01049 # text file which is input to a program), such as a CTest script for example,
01050 # to the build if neither basis_add_executable() nor basis_add_library() are
01051 # appropriate choices. In all other cases, either basis_add_executable() or
01052 # basis_add_library() should be used. Note that the script file is by default
01053 # not considered to be an executable. Instead it is assumed that the program
01054 # which interprets/processes the script must be executed explicitly with this
01055 # script as argument. Only scripts built with the @p EXECUTABLE or @p LIBEXEC
01056 # type option are treated as executable files, where in case of Unix a shebang
01057 # directive implicitly states the program used by the shell to interpret the
01058 # script and on Windows a Windows Command which imitates the behavior of Unix
01059 # shells is generated by BASIS. Do not use these type options, however, but
01060 # only use the default @p MODULE option. The basis_add_executable() function
01061 # should be used instead to add an executable script. The basis_add_script()
01062 # function shall only be used for none-executable arbitrary script files which
01063 # cannot be built by basis_add_executable() or basis_add_library().
01064 #
01065 # If the script name ends in <tt>.in</tt>, the <tt>.in</tt> suffix is removed
01066 # from the output name. Further, in case of executable scripts, the file name
01067 # extension is removed from the output file name. Instead, a shebang directive
01068 # is added on Unix to the built script. In order to enable the convenient
01069 # execution of Python and Perl scripts also on Windows without requiring the
01070 # user to setup a proper associate between the filename extension with the
01071 # corresponding interpreter executable, a few lines of Batch code are added at
01072 # the top and bottom of executable Python and Perl scripts. This Batch code
01073 # invokes the configured interpreter with the script file and the given script
01074 # arguments as command-line arguments. Note that both the original script source
01075 # code and the Batch code are stored within the single file. The file name
01076 # extension of such modified scripts is by default set to <tt>.cmd</tt>, the
01077 # common extension for Windows NT Command Scripts. Scripts in other languages
01078 # are not modified and the extension of the original scripts script file is
01079 # preserved on Windows in this case. In case of non-executable scripts, the
01080 # file name extension is kept in any case.
01081 #
01082 # Certain CMake variables within the source file are replaced during the
01083 # built of the script. See the
01084 # <a href="http://www.rad.upenn.edu/sbia/software/basis/scripttargets/>
01085 # Build System Standard</a> for details.
01086 # Note, however, that source files are only configured if the file name
01087 # ends in the <tt>.in</tt> suffix.
01088 #
01089 # A custom CMake build target with the following properties is added by this
01090 # function to the build system. These properties are used by basis_build_script()
01091 # to generate a build script written in CMake code which is executed by a custom
01092 # CMake command. Before the invokation of basis_build_script(), the target
01093 # properties can be modified using basis_set_target_properties().
01094 #
01095 # @note Custom BASIS build targets are finalized by BASIS at the end of
01096 #       basis_project_impl(), i.e., the end of the root CMake configuration file
01097 #       of the (sub-)project.
01098 #
01099 # @par Properties on script targets
01100 # <table border=0>
01101 #   <tr>
01102 #     @tp @b BASIS_TYPE @endtp
01103 #     <td>Read-only property with value "SCRIPT_FILE" for arbitrary scripts,
01104 #         "SCRIPT_EXECUTABLE" for executable scripts, and "SCRIPT_LIBEXEC" for
01105 #          auxiliary executable scripts.
01106 #          (default: see @p MODULE, @p EXECUTABLE, @p LIBEXEC options)</td>
01107 #   </tr>
01108 #   <tr>
01109 #     @tp @b BASIS_UTILITIES @endtp
01110 #     <td>Whether the BASIS utilities are used by this script. For the supported
01111 #         scripting languages for which BASIS utilities are implemented, BASIS
01112 #         will in most cases automatically detect whether these utilities are
01113 #         used by a script or not. Otherwise, set this property manually or use
01114 #         either the @p USE_BASIS_UTILITIES or the @p NO_BASIS_UTILITIES option
01115 #         when adding the script target. (default: auto-detected or @c UNKNOWN)</td>
01116 #   </tr>
01117 #   <tr>
01118 #     @tp @b BINARY_DIRECTORY @endtp
01119 #     <td>Build tree directory of this target. (default: @c CMAKE_CURRENT_BINARY_DIR)</td>
01120 #   </tr>
01121 #   <tr>
01122 #     @tp @b COMPILE @endtp
01123 #     <td>Whether to compile the script if the programming language allows such
01124 #         pre-compilation as in case of Python, for example. If @c TRUE, only the
01125 #         compiled file is installed. (default: @c BASIS_COMPILE_SCRIPTS)</td>
01126 #   </tr>
01127 #   <tr>
01128 #     @tp @b COMPILE_DEFINITIONS @endtp
01129 #     <td>CMake code which is evaluated after the inclusion of the default script
01130 #         configuration files. This code can be used to set the replacement text of the
01131 #         CMake variables ("@VAR@" patterns) used in the source file.
01132 #         See <a href="https://www.cbica.upenn.edu/sbia/software/basis/standard/scripttargets.html#script-configuration">
01133 #         Build System Standard</a> for details. (default: "")</td>
01134 #   </tr>
01135 #   <tr>
01136 #     @tp @b COMPILE_DEFINITIONS_FILE @endtp
01137 #     <td>CMake script file with compile definitions, also referred to as script
01138 #         configuration file. The named files are included after the default BASIS
01139 #         script configuration and before the @c COMPILE_DEFINITIONS code is being
01140 #         evaluated. (default: @c BINARY_CONFIG_DIR/ScriptConfig.cmake)</td>
01141 #   </tr>
01142 #   <tr>
01143 #     @tp @b COMPONENT @endtp
01144 #     <td>Name of component as part of which this script is installed if
01145 #         @c INSTALL_DIRECTORY is not set to "none".
01146 #         (default: see @p COMPONENT argument)</td>
01147 #   </tr>
01148 #   <tr>
01149 #     @tp @b EXPORT @endtp
01150 #     <td>Whether to export this build target in which case an import library
01151 #         target is added to the custom exports file with the path to the
01152 #         built/installed script set as @c IMPORT_LOCATION. (default: @c TRUE)</td>
01153 #   </tr>
01154 #   <tr>
01155 #     @tp @b INSTALL_DIRECTORY @endtp
01156 #     <td>Installation directory of script file configured for use in installation tree
01157 #         relative to @c CMAKE_INSTALL_PREFIX. Set to "none" (case-insensitive) to skip the
01158 #         addition of an installation rule. (default: see @p DESTINATION argument)</td>
01159 #   </tr>
01160 #   <tr>
01161 #     @tp @b LANGUAGE @endtp
01162 #     <td>Read-only property of programming language of script file in uppercase letters.
01163 #         (default: see @p LANGUAGE argument)</td>
01164 #   </tr>
01165 #   <tr>
01166 #     @tp @b LINK_DEPENDS @endtp
01167 #     <td>Paths or target names of script modules and libraries used by this script.
01168 #         In case of an (auxiliary) executable script, the directories of these modules
01169 #         are added to the search path for modules of the given programming language
01170 #         if such search paths are supported by the language and BASIS knows how to set
01171 #         these (as in case of Python/Jython, Perl, and MATLAB, in particular).
01172 #         Moreover, for each listed build target a dependency is added between this
01173 #         script target and the named build targets. Use basis_target_link_libraries()
01174 #         to add additional link dependencies.
01175 #         (default: BASIS utilities module if used or empty list otherwise)</td>
01176 #   </tr>
01177 #   <tr>
01178 #     @tp @b OUTPUT_DIRECTORY @endtp
01179 #     <td>Output directory for built script file configured for use in build tree.
01180 #         (default: @c BINARY_LIBRARY_DIR for arbitrary scripts, @c BINARY_RUNTIME_DIR
01181 #         for executable scripts, and @c BINARY_LIBEXEC_DIR for auxiliary executables)</td>
01182 #   </tr>
01183 #   <tr>
01184 #     @tp @b OUTPUT_NAME @endtp
01185 #     <td>Name of built script file including file name extension (if any).
01186 #         (default: basename of script file for arbitrary scripts, without extension
01187 #         for executable scripts on Unix, and <tt>.cmd</tt> extension on Windows
01188 #         in case of executable Python/Jython or Perl script)</td>
01189 #   </tr>
01190 #   <tr>
01191 #     @tp @b SOURCE_DIRECTORY @endtp
01192 #     <td>Source directory of this target. (default: @c CMAKE_CURRENT_SOURCE_DIR)</td>
01193 #   </tr>
01194 #   <tr>
01195 #     @tp @b SOURCES @endtp
01196 #     <td>Read-only property which lists the source file of this script target.
01197 #         Note that the first element in this list actually names a directory
01198 #         in the build, the one where the build script for this target is located
01199 #         instead of a source file and thus should be ignored. The second entry
01200 #         corresponds to the source file of this script target.</td>
01201 #   </tr>
01202 # </table>
01203 #
01204 # @attention Properties documented as read-only must not be modified.
01205 #
01206 # @note If this function is used within the @c PROJECT_TESTING_DIR, the built
01207 #       executable is output to the @c BINARY_TESTING_DIR directory tree instead.
01208 #       Moreover, no installation rules are added. Test executables are further
01209 #       not exported, regardless of the @c EXPORT property.
01210 #
01211 # @param [in] TARGET_NAME Name of build target. If an existing file is given as
01212 #                         argument, it is added to the list of source files and
01213 #                         the target name is derived from the name of this file.
01214 # @param [in] ARGN        The remaining arguments are parsed and the following arguments
01215 #                         recognized. All unparsed arguments are treated as source files,
01216 #                         where in particular exactly one source file is required if the
01217 #                         @p TARGET_NAME argument does not name an existing source file.
01218 # @par
01219 # <table border=0>
01220 #   <tr>
01221 #     @tp <b>MODULE</b>|<b>EXECUTABLE</b>|<b>LIBEXEC</b> @endtp
01222 #     <td>Type of script to built, i.e., either arbitrary module script which
01223 #         cannot be executed directly, an executable script with proper shebang
01224 #         directive and execute permissions on Unix or Windows Command on Windows,
01225 #         or an auxiliary executable. The type of the script mainly changes the
01226 #         default values of the target properties such as the output and installation
01227 #         directories. To add an (auxiliary) executable script, use
01228 #         basis_add_executable(), however, instead of this function.
01229 #         The @c EXECUTABLE and @c LIBEXEC options are only intended for
01230 #         internal use by BASIS. (default: MODULE)</td>
01231 #   </tr>
01232 #   <tr>
01233 #     @tp @b COMPONENT name @endtp
01234 #     <td>Name of installation component as part of which this script is being
01235 #         installed if the @c INSTALL_DIRECTORY property is not "none".
01236 #         (default: @c BASIS_LIBRARY_COMPONENT for arbitrary scripts or
01237 #         @c BASIS_RUNTIME_COMPONENT for executable scripts)</td>
01238 #   </tr>
01239 #   <tr>
01240 #     @tp @b DESTINATION dir @endtp
01241 #     <td>Installation directory for script file relative to @c CMAKE_INSTALL_PREFIX.
01242 #         If an absolute path is given as argument, it is made relative to the
01243 #         configured installation prefix.
01244 #         (default: @c INSTALL_LIBRARY_DIR for arbitrary scripts,
01245 #         @c INSTALL_RUNTIME_DIR for executable scripts, and @c INSTALL_LIBEXEC_DIR
01246 #         for auxiliary executable scripts)</td>
01247 #   </tr>
01248 #   <tr>
01249 #     @tp @b LANGUAGE lang @endtp
01250 #     <td>Programming language in which script file is written (case-insensitive).
01251 #         If not specified, the programming language is derived from the file name
01252 #         extension of the source file and the shebang directive on the first line
01253 #         of the script if any. If the programming language could not be detected
01254 #         automatically, the @c LANGUAGE property is set to @c UNKNOWN. Note that
01255 #         for arbitrary script targets, the script file will still be built correctly
01256 #         even if the scripting language was not recognized. The automatic detection
01257 #         whether the BASIS utilities are used and required will fail, however.
01258 #         In this case, specify the programming language using this option.
01259 #         (default: auto-detected or @c UNKNOWN)</td>
01260 #   </tr>
01261 #   <tr>
01262 #     @tp @b [NO]EXPORT @endtp
01263 #     <td>Whether to export this target. (default: @c TRUE)</td>
01264 #   </tr>
01265 #   <tr>
01266 #     @tp @b NO_BASIS_UTILITIES @endtp
01267 #     <td>Specify that the BASIS utilities are not used by this script. If the
01268 #         programming language of the script is known and BASIS utilities are
01269 #         available for this language, BASIS will in most cases automatically
01270 #         detect whether these utilities are used by a script or not. Use this
01271 #         option to skip this check because the script does not make use of the
01272 #         BASIS utilities.</td>
01273 #   </tr>
01274 #   <tr>
01275 #     @tp @b USE_BASIS_UTILITIES @endtp
01276 #     <td>Specify that the BASIS utilities are used and thus required by this script.
01277 #         If the programming language of the script is known and BASIS utilities are
01278 #         available for this language, BASIS will in most cases automatically
01279 #         detect whether these utilities are used by a script or not. Use this option
01280 #         to skip this check because it is already known that the script makes use of
01281 #         the BASIS utilities. Note that an error is raised if this option is given,
01282 #         but no BASIS utilities are available for the programming language of this
01283 #         script or if the programming language is unknown, respectively, not detected
01284 #         correctly. In this case, consider the use of the @p LANGUAGE argument.</td>
01285 #   </tr>
01286 # </table>
01287 #
01288 # @returns Adds a custom CMake target with the documented properties. The actual custom
01289 #          command to build the script is added by basis_build_script().
01290 #
01291 # @ingroup CMakeAPI
01292 function (basis_add_script TARGET_NAME)
01293   # parse arguments
01294   CMAKE_PARSE_ARGUMENTS (
01295     ARGN
01296       "MODULE;EXECUTABLE;LIBEXEC;NO_BASIS_UTILITIES;USE_BASIS_UTILITIES;EXPORT;NOEXPORT"
01297       "COMPONENT;DESTINATION;LANGUAGE"
01298       ""
01299     ${ARGN}
01300   )
01301   if (NOT ARGN_MODULE AND NOT ARGN_EXECUTABLE AND NOT ARGN_LIBEXEC)
01302     set (ARGN_MODULE TRUE)
01303   endif ()
01304   if (ARGN_MODULE)
01305     set (TYPE MODULE)
01306   else ()
01307     set (TYPE EXECUTABLE)
01308   endif ()
01309   string (TOLOWER "${TYPE}" type)
01310   # derive target name from file name if existing source file given as first argument
01311   get_filename_component (S "${TARGET_NAME}" ABSOLUTE)
01312   if (EXISTS "${S}" AND NOT IS_DIRECTORY "${S}" OR (NOT S MATCHES "\\.in$" AND EXISTS "${S}.in" AND NOT IS_DIRECTORY "${S}.in"))
01313     set (SOURCES "${S}")
01314     if (ARGN_MODULE)
01315       basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME)
01316     else ()
01317       basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE)
01318     endif ()
01319   else ()
01320     set (SOURCES)
01321     set (OUTPUT_NAME "${TARGET_NAME}")
01322   endif ()
01323   # check target name
01324   basis_check_target_name ("${TARGET_NAME}")
01325   basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
01326   message (STATUS "Adding ${type} script ${TARGET_UID}...")
01327   if (ARGN_MODULE AND TYPE MATCHES "EXECUTABLE")
01328     message (FATAL_ERROR "Target ${TARGET_UID}: MODULE and EXECUTABLE or LIBEXEC options are mutually exclusive!")
01329   endif ()
01330   # check/set parsed arguments
01331   basis_set_flag (ARGN EXPORT ${BASIS_EXPORT})
01332   if (ARGN_USE_BASIS_UTILITIES AND ARGN_NO_BASIS_UTILITIES)
01333     message (FATAL_ERROR "Options USE_BASIS_UTILITIES and NO_BASIS_UTILITIES are mutually exclusive!")
01334   endif ()
01335   list (LENGTH ARGN_UNPARSED_ARGUMENTS N)
01336   if (SOURCES)
01337     math (EXPR N "${N} + 1")
01338   endif ()
01339   if (N GREATER 1)
01340     if (NOT SOURCES)
01341       list (REMOVE_AT ARGN_UNPARSED_ARGUMENTS 0)
01342     endif ()
01343     message (FATAL_ERROR "Target ${TARGET_UID}: Too many or unrecognized arguments: ${ARGN_UNPARSED_ARGUMENTS}!\n"
01344                          " Only one script can be built by each script target.")
01345   elseif (NOT SOURCES)
01346     set (SOURCES "${ARGN_UNPARSED_ARGUMENTS}")
01347     get_filename_component (SOURCES "${SOURCES}" ABSOLUTE)
01348   endif ()
01349   if (NOT EXISTS "${SOURCES}" AND NOT SOURCES MATCHES "\\.in$" AND EXISTS "${SOURCES}.in")
01350     set (SOURCES "${SOURCES}.in")
01351   endif ()
01352   if (NOT EXISTS "${SOURCES}")
01353     string (REGEX REPLACE "\\.in$" "" SOURCES "${SOURCES}")
01354     message (FATAL_ERROR "Target ${TARGET_UID}: Source file ${SOURCES}[.in] does not exist!")
01355   endif ()
01356   # dump CMake variables for configuration of script
01357   set (BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TARGET_UID}.dir")
01358   basis_dump_variables ("${BUILD_DIR}/cache.cmake")
01359   # auto-detect programming language (may be as well UNKNOWN)
01360   if (ARGN_LANGUAGE)
01361     string (TOUPPER "${ARGN_LANGUAGE}" ARGN_LANGUAGE)
01362   else ()
01363     basis_get_source_language (ARGN_LANGUAGE ${SOURCES})
01364   endif ()
01365   # TEST flag
01366   basis_sanitize_for_regex (RE "${PROJECT_TESTING_DIR}")
01367   if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${RE}")
01368     set (TEST TRUE)
01369   else ()
01370     set (TEST FALSE)
01371   endif ()
01372   # default directory infix used below
01373   if (ARGN_MODULE)
01374     set (TYPE_INFIX "LIBRARY")
01375   elseif (ARGN_LIBEXEC)
01376     set (TYPE_INFIX "LIBEXEC")
01377   else ()
01378     set (TYPE_INFIX "RUNTIME")
01379   endif ()
01380   # output name
01381   string (REGEX REPLACE "\\.in$" "" SOURCE_NAME "${SOURCES}")
01382   if (NOT OUTPUT_NAME)
01383     get_filename_component (OUTPUT_NAME "${SOURCE_NAME}" NAME_WE)
01384   endif ()
01385   if (ARGN_MODULE)
01386     get_filename_component (SUFFIX "${SOURCE_NAME}" EXT)
01387   else ()
01388     if (WIN32)
01389       if (ARGN_LANGUAGE MATCHES "[JP]YTHON|PERL")
01390         set (SUFFIX ".cmd")
01391       else ()
01392         get_filename_component (SUFFIX "${SOURCE_NAME}" EXT)
01393       endif ()
01394     else ()
01395       set (SUFFIX)
01396     endif ()
01397   endif ()
01398   # output directory
01399   if (TEST)
01400     set (OUTPUT_DIRECTORY "${TESTING_${TYPE_INFIX}_DIR}")
01401   else ()
01402     set (OUTPUT_DIRECTORY "${BINARY_${TYPE_INFIX}_DIR}")
01403   endif ()
01404   # installation component
01405   if (NOT ARGN_COMPONENT)
01406     if (ARGN_MODULE)
01407       set (ARGN_COMPONENT "${BASIS_LIBRARY_COMPONENT}")
01408     else ()
01409       set (ARGN_COMPONENT "${BASIS_RUNTIME_COMPONENT}")
01410     endif ()
01411   endif ()
01412   if (NOT ARGN_COMPONENT)
01413     set (ARGN_COMPONENT "Unspecified")
01414   endif ()
01415   # installation directory
01416   if (ARGN_DESTINATION)
01417     if (ARGN_DESTINATION MATCHES "^[nN][oO][nN][eE]$")
01418       set (ARGN_DESTINATION)
01419     elseif (IS_ABSOLUTE "${ARGN_DESTINATION}")
01420       file (RELATIVE_PATH ARGN_DESTINATION "${CMAKE_INSTALL_PREFIX}" "${ARGN_DESTINATION}")
01421     endif ()
01422   elseif (TEST)
01423     set (ARGN_DESTINATION) # do not install
01424   else ()
01425     set (ARGN_DESTINATION "${INSTALL_${TYPE_INFIX}_DIR}")
01426   endif ()
01427   # script configuration ("compile definitions")
01428   if (EXISTS "${BINARY_CONFIG_DIR}/ScriptConfig.cmake")
01429     set (CONFIG_FILE "${BINARY_CONFIG_DIR}/ScriptConfig.cmake")
01430   else ()
01431     set (CONFIG_FILE)
01432   endif ()
01433   # auto-detect use of BASIS utilities
01434   set (LINK_DEPENDS)
01435   if (ARGN_LANGUAGE MATCHES "[JP]YTHON")
01436     set (UTILITIES_LANGUAGE "PYTHON")
01437   else ()
01438     set (UTILITIES_LANGUAGE "${ARGN_LANGUAGE}")
01439   endif ()
01440   if (ARGN_USE_BASIS_UTILITIES)
01441     if (NOT BASIS_UTILITIES_ENABLED MATCHES "${UTILITIES_LANGUAGE}")
01442       message (FATAL_ERROR "Target ${TARGET_UID} requires the BASIS utilities for ${UTILITIES_LANGUAGE}"
01443                            " but BASIS was either build without the build of these utilities enabled"
01444                            " or no utilities for this programming language are implemented. Remove the"
01445                            " USE_BASIS_UTILITIES option if no BASIS utilities are used by the script"
01446                            " ${SOURCES} or specify the correct programming language if it was not"
01447                            " detected correctly.")
01448     endif ()
01449     set (USES_BASIS_UTILITIES TRUE)
01450   elseif (NOT ARGN_NO_BASIS_UTILITIES AND NOT UTILITIES_LANGUAGE MATCHES "UNKNOWN")
01451     basis_utilities_check (USES_BASIS_UTILITIES ${SOURCES} ${UTILITIES_LANGUAGE})
01452   else ()
01453     set (USES_BASIS_UTILITIES FALSE)
01454   endif ()
01455   if (USES_BASIS_UTILITIES)
01456     basis_set_project_property (PROPERTY PROJECT_USES_${UTILITIES_LANGUAGE}_UTILITIES TRUE)
01457     if (BASIS_DEBUG)
01458       message ("** Target ${TARGET_UID} uses the BASIS utilities for ${UTILITIES_LANGUAGE}.")
01459     endif ()
01460   endif ()
01461   # add custom target
01462   add_custom_target (${TARGET_UID} ALL SOURCES ${SOURCES})
01463   _set_target_properties (
01464     ${TARGET_UID}
01465     PROPERTIES
01466       LANGUAGE                 ${ARGN_LANGUAGE}
01467       BASIS_TYPE               SCRIPT_${TYPE}
01468       BASIS_UTILITIES          ${USES_BASIS_UTILITIES}
01469       SOURCE_DIRECTORY         "${CMAKE_CURRENT_SOURCE_DIR}"
01470       BINARY_DIRECTORY         "${CMAKE_CURRENT_BINARY_DIR}"
01471       OUTPUT_DIRECTORY         "${OUTPUT_DIRECTORY}"
01472       INSTALL_DIRECTORY        "${ARGN_DESTINATION}"
01473       COMPONENT                "${ARGN_COMPONENT}"
01474       OUTPUT_NAME              "${OUTPUT_NAME}"
01475       PREFIX                   ""
01476       SUFFIX                   "${SUFFIX}"
01477       COMPILE_DEFINITIONS      ""
01478       COMPILE_DEFINITIONS_FILE "${CONFIG_FILE}"
01479       LINK_DEPENDS             "${LINK_DEPENDS}"
01480       EXPORT                   ${EXPORT}
01481       COMPILE                  ${BASIS_COMPILE_SCRIPTS}
01482       TEST                     ${TEST}
01483       LIBEXEC                  ${ARGN_LIBEXEC}
01484   )
01485   # add target to list of targets
01486   basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET_UID}")
01487   message (STATUS "Adding ${type} script ${TARGET_UID}... - done")
01488 endfunction ()
01489 
01490 # ============================================================================
01491 # internal helpers
01492 # ============================================================================
01493 
01494 # ----------------------------------------------------------------------------
01495 ## @brief Add executable target.
01496 #
01497 # This BASIS function overwrites CMake's
01498 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_executable">
01499 # add_executable()</a> command in order to store information of imported targets
01500 # which is in particular used to generate the source code of the ExecutableTargetInfo
01501 # modules which are part of the BASIS utilities.
01502 #
01503 # @note Use basis_add_executable() instead where possible!
01504 #
01505 # @param [in] TARGET_UID Name of the target.
01506 # @param [in] ARGN       Further arguments of CMake's add_executable().
01507 #
01508 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_executable
01509 function (add_executable TARGET_UID)
01510   if (ARGC EQUAL 2 AND ARGV1 MATCHES "^IMPORTED$")
01511     _add_executable (${TARGET_UID} IMPORTED)
01512     basis_add_imported_target ("${TARGET_UID}" EXECUTABLE)
01513   else ()
01514     _add_executable (${TARGET_UID} ${ARGN})
01515     basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET_UID}")
01516   endif ()
01517 endfunction ()
01518 
01519 # ----------------------------------------------------------------------------
01520 ## @brief Add library target.
01521 #
01522 # This BASIS function overwrites CMake's
01523 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_library">
01524 # add_library()</a> command in order to store information of imported targets.
01525 #
01526 # @note Use basis_add_library() instead where possible!
01527 #
01528 # @param [in] TARGET_UID Name of the target.
01529 # @param [in] ARGN       Further arguments of CMake's add_library().
01530 #
01531 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_library
01532 function (add_library TARGET_UID)
01533   if (ARGC EQUAL 3 AND ARGV2 MATCHES "^IMPORTED$")
01534     _add_library (${TARGET_UID} "${ARGV1}" IMPORTED)
01535     basis_add_imported_target ("${TARGET_UID}" "${ARGV1}")
01536   else ()
01537     _add_library (${TARGET_UID} ${ARGN})
01538     basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET_UID}")
01539   endif ()
01540 endfunction ()
01541 
01542 # ----------------------------------------------------------------------------
01543 ## @brief Add executable built from C++ source code.
01544 #
01545 # @note This function should not be used directly. Instead, it is called
01546 #       by basis_add_executable() if the (detected) programming language
01547 #       of the given source code files is @c CXX (i.e., C/C++).
01548 #
01549 # This function adds an executable target for the build of an executable from
01550 # C++ source code files. Refer to the documentation of basis_add_executable()
01551 # for a description of general options for adding an executable target.
01552 #
01553 # By default, the BASIS C++ utilities library is added as link dependency.
01554 # If none of the BASIS C++ utilities are used by this target, the option
01555 # NO_BASIS_UTILITIES can be given. To enable this option by default, set the
01556 # variable @c BASIS_UTILITIES to @c FALSE, best in the <tt>Settings.cmake</tt>
01557 # file located in the @c PROJECT_CONFIG_DIR (add such file if missing).
01558 # If the use of the BASIS C++ utilities is disabled by default, the
01559 # @c USE_BASIS_UTILITIES option can be used to enable them for this target
01560 # only. Note that the utilities library is a static library and thus the linker
01561 # would simply not include any of the BASIS utility functions in the final
01562 # binary file if not used. The only advantage of setting @c BASIS_UTILITIES to
01563 # @c FALSE or to always specify @c NO_BASIS_UTILITIES if no target uses the
01564 # utilities is that the BASIS utilities library will not be build in this case.
01565 #
01566 # @param [in] TARGET_NAME Name of build target.
01567 # @param [in] ARGN        This argument list is parsed and the following
01568 #                         arguments are extracted, all other arguments are
01569 #                         considered to be source code files and simply passed
01570 #                         on to CMake's add_executable() command.
01571 # @par
01572 # <table border=0>
01573 #   <tr>
01574 #     @tp @b COMPONENT name @endtp
01575 #     <td>Name of component as part of which this executable will be installed
01576 #         if the specified @c DESTINATION is not "none".
01577 #         (default: @c BASIS_RUNTIME_COMPONENT)</td>
01578 #   </tr>
01579 #   <tr>
01580 #     @tp @b DESTINATION dir @endtp
01581 #     <td>Installation directory relative to @c CMAKE_INSTALL_PREFIX.
01582 #         If "none" (case-insensitive) is given as argument, no default
01583 #         installation rules are added for this executable target.
01584 #         (default: @c INSTALL_RUNTIME_DIR or @c INSTALL_LIBEXEC_DIR
01585 #         if @p LIBEXEC is given)</td>
01586 #   </tr>
01587 #   <tr>
01588 #     @tp @b LIBEXEC @endtp
01589 #     <td>Specifies that the built executable is an auxiliary executable which
01590 #         is only called by other executables. (default: @c FALSE)</td>
01591 #   </tr>
01592 #   <tr>
01593 #     @tp @b [NO]EXPORT @endtp
01594 #     <td>Whether to export this target. (default: @c TRUE)</td>
01595 #   </tr>
01596 #   <tr>
01597 #     @tp @b NO_BASIS_UTILITIES @endtp
01598 #     <td>Specify that the BASIS utilities are not used by this executable and hence
01599 #         no link dependency on the BASIS utilities library shall be added.
01600 #         (default: @c NOT @c BASIS_UTILITIES)</td>
01601 #   </tr>
01602 #   <tr>
01603 #     @tp @b USE_BASIS_UTILITIES @endtp
01604 #     <td>Specify that the BASIS utilities are used and required by this executable
01605 #         and hence a link dependency on the BASIS utilities library has to be added.
01606 #         (default: @c BASIS_UTILITIES)</td>
01607 #   </tr>
01608 # </table>
01609 #
01610 # @returns Adds executable target using CMake's add_executable() command.
01611 #
01612 # @sa basis_add_executable()
01613 function (basis_add_executable_target TARGET_NAME)
01614   # check target name
01615   basis_check_target_name (${TARGET_NAME})
01616   basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
01617   message (STATUS "Adding executable ${TARGET_UID}...")
01618   # parse arguments
01619   CMAKE_PARSE_ARGUMENTS (
01620     ARGN
01621       "USE_BASIS_UTILITIES;NO_BASIS_UTILITIES;EXPORT;NOEXPORT;LIBEXEC"
01622       "COMPONENT;DESTINATION"
01623       ""
01624     ${ARGN}
01625   )
01626   set (SOURCES ${ARGN_UNPARSED_ARGUMENTS})
01627   basis_set_flag (ARGN EXPORT  ${BASIS_EXPORT})
01628   if (ARGN_USE_BASIS_UTILITIES AND ARGN_NO_BASIS_UTILITIES)
01629     message (FATAL_ERROR "Target ${TARGET_UID}: Options USE_BASIS_UTILITIES and NO_BASIS_UTILITIES are mutually exclusive!")
01630   endif ()
01631   if (ARGN_USE_BASIS_UTILITIES)
01632     set (USES_BASIS_UTILITIES TRUE)
01633   elseif (ARGN_NO_BASIS_UTILITIES)
01634     set (USES_BASIS_UTILITIES FALSE)
01635   else ()
01636     set (USES_BASIS_UTILITIES ${BASIS_UTILITIES})
01637   endif ()
01638   # TEST flag
01639   basis_sanitize_for_regex (RE "${PROJECT_TESTING_DIR}")
01640   if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${RE}")
01641     set (TEST TRUE)
01642   else ()
01643     set (TEST FALSE)
01644   endif ()
01645   # installation component
01646   if (NOT ARGN_COMPONENT)
01647     set (ARGN_COMPONENT "${BASIS_RUNTIME_COMPONENT}")
01648   endif ()
01649   if (NOT ARGN_COMPONENT)
01650     set (ARGN_COMPONENT "Unspecified")
01651   endif ()
01652   # installation directory
01653   if (ARGN_DESTINATION)
01654     if (ARGN_DESTINATION MATCHES "^[nN][oO][nN][eE]$")
01655       set (ARGN_DESTINATION)
01656     elseif (IS_ABSOLUTE "${ARGN_DESTINATION}")
01657       file (RELATIVE_PATH ARGN_DESTINATION "${CMAKE_INSTALL_PREFIX}" "${ARGN_DESTINATION}")
01658     endif ()
01659   elseif (ARGN_LIBEXEC)
01660     set (ARGN_DESTINATION "${INSTALL_LIBEXEC_DIR}")
01661   else ()
01662     set (ARGN_DESTINATION "${INSTALL_RUNTIME_DIR}")
01663   endif ()
01664   # configure (.in) source files
01665   basis_configure_sources (SOURCES ${SOURCES})
01666   # add executable target
01667   add_executable (${TARGET_UID} ${SOURCES})
01668   basis_make_target_uid (HEADERS_TARGET headers)
01669   if (TARGET "${HEADERS_TARGET}")
01670     add_dependencies (${TARGET_UID} ${HEADERS_TARGET})
01671   endif ()
01672   if (TARGET __${TARGET_UID}) # re-glob source files
01673     add_dependencies (_${TARGET_UID} __${TARGET_UID})
01674   endif ()
01675   _set_target_properties (${TARGET_UID} PROPERTIES BASIS_TYPE "EXECUTABLE" OUTPUT_NAME "${TARGET_NAME}")
01676   if (ARGN_LIBEXEC)
01677     _set_target_properties (${TARGET_UID} PROPERTIES LIBEXEC 1 COMPILE_DEFINITIONS LIBEXEC)
01678   else ()
01679     _set_target_properties (${TARGET_UID} PROPERTIES LIBEXEC 0)
01680   endif ()
01681   _set_target_properties (${TARGET_UID} PROPERTIES TEST ${TEST})
01682   # output directory
01683   if (TEST)
01684     if (ARGN_LIBEXEC)
01685       _set_target_properties (${TARGET_UID} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_LIBEXEC_DIR}")
01686     else ()
01687       _set_target_properties (${TARGET_UID} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_RUNTIME_DIR}")
01688     endif ()
01689   elseif (ARGN_LIBEXEC)
01690     _set_target_properties (${TARGET_UID} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BINARY_LIBEXEC_DIR}")
01691   else ()
01692     _set_target_properties (${TARGET_UID} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BINARY_RUNTIME_DIR}")
01693   endif ()
01694   # installation directory
01695   _set_target_properties (${TARGET_UID} PROPERTIES RUNTIME_INSTALL_DIRECTORY "${ARGN_DESTINATION}")
01696   # link to BASIS utilities
01697   if (USES_BASIS_UTILITIES)
01698     if (NOT TARGET ${BASIS_CXX_UTILITIES_LIBRARY})
01699       message (FATAL_ERROR "Target ${TARGET_UID} seems to make use of the BASIS C++"
01700                            " utilities but BASIS was built without C++ utilities enabled."
01701                            " Either specify the option NO_BASIS_UTILITIES, set the global"
01702                            " variable BASIS_UTILITIES to FALSE"
01703                            " (in ${PROJECT_CONFIG_DIR}/Settings.cmake) or"
01704                            " rebuild BASIS with C++ utilities enabled.")
01705     endif ()
01706     # add project-specific library target if not present yet
01707     basis_add_utilities_library (BASIS_UTILITIES_TARGET)
01708     # non-project specific utilities build as part of BASIS
01709     basis_target_link_libraries (${TARGET_UID} ${BASIS_CXX_UTILITIES_LIBRARY})
01710     # project-specific utilities build as part of this project
01711     basis_target_link_libraries (${TARGET_UID} ${BASIS_UTILITIES_TARGET})
01712   endif ()
01713   _set_target_properties (${TARGET_UID} PROPERTIES BASIS_UTILITIES ${USES_BASIS_UTILITIES})
01714   # export
01715   set (EXPORT_OPT)
01716   if (EXPORT)
01717     if (TEST)
01718       basis_set_project_property (APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}")
01719     else ()
01720       basis_set_project_property (APPEND PROPERTY EXPORT_TARGETS "${TARGET_UID}")
01721       if (ARGN_DESTINATION)
01722         basis_set_project_property (APPEND PROPERTY INSTALL_EXPORT_TARGETS "${TARGET_UID}")
01723       endif ()
01724       set (EXPORT_OPT "EXPORT" "${PROJECT_NAME}") # for install() below
01725     endif ()
01726   endif ()
01727   # installation
01728   if (ARGN_DESTINATION)
01729     if (TEST)
01730       # TODO install (selected?) tests
01731     else ()
01732       install (
01733         TARGETS ${TARGET_UID} ${EXPORT_OPT}
01734         DESTINATION "${ARGN_DESTINATION}"
01735         COMPONENT   "${ARGN_COMPONENT}"
01736       )
01737     endif ()
01738   endif ()
01739   # done
01740   message (STATUS "Adding executable ${TARGET_UID}... - done")
01741 endfunction ()
01742 
01743 # ----------------------------------------------------------------------------
01744 ## @brief Add library built from C++ source code.
01745 #
01746 # @note This function should not be used directly. Instead, it is called
01747 #       by basis_add_library() if the (detected) programming language
01748 #       of the given source code files is @c CXX (i.e., C/C++) and the
01749 #       option @c MEX is not given.
01750 #
01751 # This function adds a library target which builds a library from C++ source
01752 # code files. Refer to the documentation of basis_add_library() for a
01753 # description of the general options for adding a library target.
01754 #
01755 # By default, the BASIS C++ utilities library is added as link dependency.
01756 # If none of the BASIS C++ utilities are used by this target, the option
01757 # NO_BASIS_UTILITIES can be given. To enable this option by default, set the
01758 # variable @c BASIS_UTILITIES to @c FALSE, best in the <tt>Settings.cmake</tt>
01759 # file located in the @c PROJECT_CONFIG_DIR (add such file if missing).
01760 # If the use of the BASIS C++ utilities is disabled by default, the
01761 # @c USE_BASIS_UTILITIES option can be used to enable them for this target
01762 # only. Note that the utilities library is a static library and thus the linker
01763 # would simply not include any of the BASIS utility functions in the final
01764 # binary file if not used. The only advantage of setting @c BASIS_UTILITIES to
01765 # @c FALSE or to always specify @c NO_BASIS_UTILITIES if no target uses the
01766 # utilities is that the BASIS utilities library will not be build in this case.
01767 #
01768 # @param [in] TARGET_NAME Name of build target.
01769 # @param [in] ARGN        This argument list is parsed and the following
01770 #                         arguments are extracted. All other arguments are
01771 #                         considered to be source code files and simply
01772 #                         passed on to CMake's add_library() command.
01773 # @par
01774 # <table border=0>
01775 #   <tr>
01776 #     @tp <b>STATIC</b>|<b>SHARED</b>|<b>MODULE</b> @endtp
01777 #     <td>Type of the library. (default: @c SHARED if @c BUILD_SHARED_LIBS
01778 #         evaluates to true or @c STATIC otherwise)</td>
01779 #   </tr>
01780 #   <tr>
01781 #     @tp @b COMPONENT name @endtp
01782 #     <td>Name of component as part of which this library will be installed
01783 #         if either the @c RUNTIME_INSTALL_DIRECTORY or
01784 #         @c LIBRARY_INSTALL_DIRECTORY property is not "none". Used only if
01785 #         either @p RUNTIME_COMPONENT or @p LIBRARY_COMPONENT not specified.
01786 #         (default: see @p RUNTIME_COMPONENT and @p LIBRARY_COMPONENT)</td>
01787 #   </tr>
01788 #   <tr>
01789 #     @tp @b DESTINATION dir @endtp
01790 #     <td>Installation directory for runtime and library component relative
01791 #         to @c CMAKE_INSTALL_PREFIX. Used only if either @p RUNTIME_DESTINATION
01792 #         or @p LIBRARY_DESTINATION not specified. If "none" (case-insensitive)
01793 #         is given as argument, no default installation rules are added.
01794 #         (default: see @p RUNTIME_DESTINATION and @p LIBRARY_DESTINATION)</td>
01795 #   </tr>
01796 #   <tr>
01797 #     @tp @b LIBRARY_COMPONENT name @endtp
01798 #     <td>Name of component as part of which import/static library will be intalled
01799 #         if @c LIBRARY_INSTALL_DIRECTORY property is not "none".
01800 #         (default: @c COMPONENT if specified or @c BASIS_LIBRARY_COMPONENT otherwise)</td>
01801 #   </tr>
01802 #   <tr>
01803 #     @tp @b LIBRARY_DESTINATION dir @endtp
01804 #     <td>Installation directory of the library component relative to
01805 #         @c CMAKE_INSTALL_PREFIX. If "none" (case-insensitive) is given as argument,
01806 #         no installation rule for the library component is added.
01807 #         (default: @c INSTALL_ARCHIVE_DIR)</td>
01808 #   </tr>
01809 #   <tr>
01810 #     @tp @b RUNTIME_COMPONENT name @endtp
01811 #     <td>Name of component as part of which runtime library will be installed
01812 #         if @c RUNTIME_INSTALL_DIRECTORY property is not "none".
01813 #         (default: @c COMPONENT if specified or @c BASIS_RUNTIME_COMPONENT otherwise)</td>
01814 #   </tr>
01815 #   <tr>
01816 #     @tp @b RUNTIME_DESTINATION dir @endtp
01817 #     <td>Installation directory of the runtime component relative to
01818 #         @c CMAKE_INSTALL_PREFIX. If "none" (case-insensitive) is given as argument,
01819 #         no installation rule for the runtime library is added.
01820 #         (default: @c INSTALL_LIBRARY_DIR on Unix or @c INSTALL_RUNTIME_DIR Windows)</td>
01821 #   </tr>
01822 #   <tr>
01823 #     @tp @b [NO]EXPORT @endtp
01824 #     <td>Whether to export this target. (default: @c TRUE)</td>
01825 #   </tr>
01826 #   <tr>
01827 #     @tp @b NO_BASIS_UTILITIES @endtp
01828 #     <td>Specify that the BASIS utilities are not used by this executable and hence
01829 #         no link dependency on the BASIS utilities library shall be added.
01830 #         (default: @c NOT BASIS_UTILITIES)</td>
01831 #   </tr>
01832 #   <tr>
01833 #     @tp @b USE_BASIS_UTILITIES @endtp
01834 #     <td>Specify that the BASIS utilities are used and required by this executable
01835 #         and hence a link dependency on the BASIS utilities library shall be added.
01836 #         (default: @c BASIS_UTILITIES)</td>
01837 #   </tr>
01838 # </table>
01839 #
01840 # @returns Adds library target using CMake's add_library() command.
01841 #
01842 # @sa basis_add_library()
01843 function (basis_add_library_target TARGET_NAME)
01844   # On UNIX-based systems setting the VERSION property only creates
01845   # annoying files with the version string as suffix.
01846   # Moreover, MEX-files may NEVER have a suffix after the MEX extension!
01847   # Otherwise, the MATLAB Compiler when using the symbolic link
01848   # without this suffix will create code that fails on runtime
01849   # with an .auth file missing error.
01850   #
01851   # Thus, do NOT set VERSION and SOVERSION properties on library targets!
01852 
01853   # check target name
01854   basis_check_target_name (${TARGET_NAME})
01855   basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
01856   # parse arguments
01857   CMAKE_PARSE_ARGUMENTS (
01858     ARGN
01859       "STATIC;SHARED;MODULE;USE_BASIS_UTILITIES;NO_BASIS_UTILITIES;EXPORT;NOEXPORT"
01860       "COMPONENT;RUNTIME_COMPONENT;LIBRARY_COMPONENT;DESTINATION;RUNTIME_DESTINATION;LIBRARY_DESTINATION"
01861       ""
01862     ${ARGN}
01863   )
01864   set (SOURCES ${ARGN_UNPARSED_ARGUMENTS})
01865   basis_set_flag (ARGN EXPORT ${BASIS_EXPORT})
01866   if (ARGN_USE_BASIS_UTILITIES AND ARGN_NO_BASIS_UTILITIES)
01867     message (FATAL_ERROR "Target ${TARGET_UID}: Options USE_BASIS_UTILITIES and NO_BASIS_UTILITIES are mutually exclusive!")
01868   endif ()
01869   if (ARGN_USE_BASIS_UTILITIES)
01870     set (USES_BASIS_UTILITIES TRUE)
01871   elseif (ARGN_NO_BASIS_UTILITIES)
01872     set (USES_BASIS_UTILITIES FALSE)
01873   else ()
01874     set (USES_BASIS_UTILITIES ${BASIS_UTILITIES})
01875   endif ()
01876   # TEST flag
01877   basis_sanitize_for_regex (RE "${PROJECT_TESTING_DIR}")
01878   if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${RE}")
01879     set (TEST TRUE)
01880   else ()
01881     set (TEST FALSE)
01882   endif ()
01883   # library type
01884   if (NOT ARGN_SHARED AND NOT ARGN_STATIC AND NOT ARGN_MODULE)
01885     if (BUILD_SHARED_LIBS)
01886       set (ARGN_SHARED TRUE)
01887     else ()
01888       set (ARGN_STATIC TRUE)
01889     endif ()
01890   endif ()
01891   set (TYPE)
01892   if (ARGN_STATIC)
01893     if (TYPE)
01894       message (FATAL_ERROR "More than one library type specified for target ${TARGET_UID}!")
01895     endif ()
01896     set (TYPE "STATIC")
01897   endif ()
01898   if (ARGN_SHARED)
01899     if (TYPE)
01900       message (FATAL_ERROR "More than one library type specified for target ${TARGET_UID}!")
01901     endif ()
01902     set (TYPE "SHARED")
01903   endif ()
01904   if (ARGN_MODULE)
01905     if (TYPE)
01906       message (FATAL_ERROR "More than one library type specified for target ${TARGET_UID}!")
01907     endif ()
01908     set (TYPE "MODULE")
01909   endif ()
01910   string (TOLOWER "${TYPE}" type)
01911   # status message
01912   message (STATUS "Adding ${type} library ${TARGET_UID}...")
01913   # installation component
01914   if (ARGN_COMPONENT)
01915     if (NOT ARGN_RUNTIME_COMPONENT)
01916       set (ARGN_RUNTIME_COMPONENT "${ARGN_COMPONENT}")
01917     endif ()
01918     if (NOT ARGN_LIBRARY_COMPONENT)
01919       set (ARGN_LIBRARY_COMPONENT "${ARGN_COMPONENT}")
01920     endif ()
01921   endif ()
01922   if (NOT ARGN_RUNTIME_COMPONENT)
01923     set (ARGN_RUNTIME_COMPONENT "${BASIS_RUNTIME_COMPONENT}")
01924   endif ()
01925   if (NOT ARGN_RUNTIME_COMPONENT)
01926     set (ARGN_RUNTIME_COMPONENT "Unspecified")
01927   endif ()
01928   if (NOT ARGN_LIBRARY_COMPONENT)
01929     set (ARGN_LIBRARY_COMPONENT "${BASIS_LIBRARY_COMPONENT}")
01930   endif ()
01931   if (NOT ARGN_LIBRARY_COMPONENT)
01932     set (ARGN_LIBRARY_COMPONENT "Unspecified")
01933   endif ()
01934   # installation directories
01935   if (ARGN_DESTINATION)
01936     if (NOT ARGN_STATIC AND NOT ARGN_RUNTIME_DESTINATION)
01937       set (ARGN_RUNTIME_DESTINATION "${ARGN_DESTINATION}")
01938     endif ()
01939     if (NOT ARGN_LIBRARY_DESTINATION)
01940       set (ARGN_LIBRARY_DESTINATION "${ARGN_DESTINATION}")
01941     endif ()
01942   endif ()
01943   if (NOT ARGN_RUNTIME_DESTINATION)
01944     set (ARGN_RUNTIME_DESTINATION "${INSTALL_RUNTIME_DIR}")
01945   endif ()
01946   if (NOT ARGN_LIBRARY_DESTINATION)
01947     set (ARGN_LIBRARY_DESTINATION "${INSTALL_LIBRARY_DIR}")
01948   endif ()
01949   if (ARGN_STATIC OR ARGN_RUNTIME_DESTINATION MATCHES "^[nN][oO][nN][eE]$")
01950     set (ARGN_RUNTIME_DESTINATION)
01951   endif ()
01952   if (ARGN_LIBRARY_DESTINATION MATCHES "^[nN][oO][nN][eE]$")
01953     set (ARGN_LIBRARY_DESTINATION)
01954   endif ()
01955   # configure (.in) source files
01956   basis_configure_sources (SOURCES ${SOURCES})
01957   # add library target
01958   add_library (${TARGET_UID} ${TYPE} ${SOURCES})
01959   basis_make_target_uid (HEADERS_TARGET headers)
01960   if (TARGET ${HEADERS_TARGET})
01961     add_dependencies (${TARGET_UID} ${HEADERS_TARGET})
01962   endif ()
01963   if (TARGET __${TARGET_UID}) # re-glob source files
01964     add_dependencies (_${TARGET_UID} __${TARGET_UID})
01965   endif ()
01966   _set_target_properties (${TARGET_UID} PROPERTIES BASIS_TYPE "${TYPE}_LIBRARY" OUTPUT_NAME "${TARGET_NAME}")
01967   # output directory
01968   if (TEST)
01969     _set_target_properties (
01970       ${TARGET_UID}
01971       PROPERTIES
01972         RUNTIME_OUTPUT_DIRECTORY "${TESTING_RUNTIME_DIR}"
01973         LIBRARY_OUTPUT_DIRECTORY "${TESTING_LIBRARY_DIR}"
01974         ARCHIVE_OUTPUT_DIRECTORY "${TESTING_ARCHIVE_DIR}"
01975     )
01976   else ()
01977     _set_target_properties (
01978       ${TARGET_UID}
01979       PROPERTIES
01980         RUNTIME_OUTPUT_DIRECTORY "${BINARY_RUNTIME_DIR}"
01981         LIBRARY_OUTPUT_DIRECTORY "${BINARY_LIBRARY_DIR}"
01982         ARCHIVE_OUTPUT_DIRECTORY "${BINARY_ARCHIVE_DIR}"
01983     )
01984   endif ()
01985   # installation directory
01986   # these properties are used by basis_get_target_location() in particular
01987   _set_target_properties (
01988     ${TARGET_UID}
01989     PROPERTIES
01990       RUNTIME_INSTALL_DIRECTORY "${ARGN_RUNTIME_DESTINATION}"
01991       LIBRARY_INSTALL_DIRECTORY "${ARGN_LIBRARY_DESTINATION}"
01992       ARCHIVE_INSTALL_DIRECTORY "${ARGN_LIBRARY_DESTINATION}"
01993   )
01994   # link to BASIS utilities
01995   if (USES_BASIS_UTILITIES)
01996     if (NOT TARGET ${BASIS_CXX_UTILITIES_LIBRARY})
01997       message (FATAL_ERROR "Target ${TARGET_UID} makes use of the BASIS C++ utilities"
01998                            " but BASIS was build without C++ utilities enabled."
01999                            " Either specify the option NO_BASIS_UTILITIES, set the global"
02000                            " variable BASIS_UTILITIES to FALSE"
02001                            " (in ${PROJECT_CONFIG_DIR}/Settings.cmake) or"
02002                            " rebuild BASIS with C++ utilities enabled.")
02003     endif ()
02004     # add project-specific library target if not present yet
02005     basis_add_utilities_library (BASIS_UTILITIES_TARGET)
02006     # non-project specific utilities build as part of BASIS
02007     basis_target_link_libraries (${TARGET_UID} ${BASIS_CXX_UTILITIES_LIBRARY})
02008     # project-specific utilities build as part of this project
02009     basis_target_link_libraries (${TARGET_UID} ${BASIS_UTILITIES_TARGET})
02010   endif ()
02011   _set_target_properties (${TARGET_UID} PROPERTIES BASIS_UTILITIES ${USES_BASIS_UTILITIES})
02012   # installation
02013   if (TEST)
02014     # TODO At the moment, no tests are installed. Once there is a way to
02015     #      install selected tests, the shared libraries they depend on
02016     #      need to be installed as well.
02017     if (EXPORT)
02018       basis_set_project_property (APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}")
02019     endif ()
02020   else ()
02021     if (EXPORT)
02022       set (EXPORT_OPT "EXPORT" "${PROJECT_NAME}")
02023       basis_set_project_property (APPEND PROPERTY EXPORT_TARGETS "${TARGET_UID}")
02024       if (ARGN_RUNTIME_DESTINATION OR ARGN_LIBRARY_DESTINATION)
02025         basis_set_project_property (APPEND PROPERTY INSTALL_EXPORT_TARGETS "${TARGET_UID}")
02026       endif ()
02027     else ()
02028       set (EXPORT_OPT)
02029     endif ()
02030     if (ARGN_RUNTIME_DESTINATION)
02031       install (
02032         TARGETS ${TARGET_UID} ${EXPORT_OPT}
02033         RUNTIME
02034           DESTINATION "${ARGN_RUNTIME_DESTINATION}"
02035           COMPONENT   "${ARGN_RUNTIME_COMPONENT}"
02036       )
02037     endif ()
02038     if (ARGN_LIBRARY_DESTINATION)
02039       install (
02040         TARGETS ${TARGET_UID} ${EXPORT_OPT}
02041         LIBRARY
02042           DESTINATION "${ARGN_LIBRARY_DESTINATION}"
02043           COMPONENT   "${ARGN_LIBRARY_COMPONENT}"
02044         ARCHIVE
02045           DESTINATION "${ARGN_LIBRARY_DESTINATION}"
02046           COMPONENT   "${ARGN_LIBRARY_COMPONENT}"
02047       )
02048     endif ()
02049   endif ()
02050   # done
02051   message (STATUS "Adding ${type} library ${TARGET_UID}... - done")
02052 endfunction ()
02053 
02054 # ----------------------------------------------------------------------------
02055 ## @brief Add script library target.
02056 #
02057 # @note This function should not be used directly. Instead, it is called
02058 #       by basis_add_library() if the (detected) programming language
02059 #       of the given source code files is neither @c CXX (i.e., C/C++) nor
02060 #       @c MATLAB.
02061 #
02062 # This function adds a build target for libraries which are a collection of
02063 # one or more modules written in a scripting language. The relative paths
02064 # of the modules relative to the library's @p SOURCE_DIRECTORY property are
02065 # preserved. This is important for the most widely used scripting languages
02066 # such as Python, Perl, or MATLAB, where the file path relative to the
02067 # package root directory defines the package namespace.
02068 #
02069 # A custom CMake build target with the following properties is added by this
02070 # function to the build system. These properties are used by
02071 # basis_build_script_library() to generate a build script written in CMake
02072 # code which is executed by a custom CMake command. Before the invokation of
02073 # basis_build_script_library(), the target properties can be modified using
02074 # basis_set_target_properties().
02075 #
02076 # @note Custom BASIS build targets are finalized by BASIS at the end of
02077 #       basis_project_impl(), i.e., the end of the root CMake configuration file
02078 #       of the (sub-)project.
02079 #
02080 # @par Properties on script library targets
02081 # <table border=0>
02082 #   <tr>
02083 #     @tp @b BASIS_TYPE @endtp
02084 #     <td>Read-only property with value "SCRIPT_LIBRARY" for script library targets.</td>
02085 #   </tr>
02086 #   <tr>
02087 #     @tp @b BASIS_UTILITIES @endtp
02088 #     <td>Whether the BASIS utilities are used by any module of this library.
02089 #         For the supported scripting languages for which BASIS utilities are
02090 #         implemented, BASIS will in most cases automatically detect whether
02091 #         these utilities are used by a module or not. Otherwise, set this
02092 #         property manually or use either the @p USE_BASIS_UTILITIES or the
02093 #         @p NO_BASIS_UTILITIES option when adding the library target.
02094 #         (default: auto-detected or @c UNKNOWN)</td>
02095 #   </tr>
02096 #   <tr>
02097 #     @tp @b BINARY_DIRECTORY @endtp
02098 #     <td>Build tree directory of this target. (default: @c CMAKE_CURRENT_BINARY_DIR)</td>
02099 #   </tr>
02100 #   <tr>
02101 #     @tp @b COMPILE @endtp
02102 #     <td>Whether to compile the library, respectively, it's modules if the
02103 #         programming language allows such pre-compilation as in case of Python,
02104 #         for example. If @c TRUE, only the compiled files are installed.
02105 #         (default: @c BASIS_COMPILE_SCRIPTS)</td>
02106 #   </tr>
02107 #   <tr>
02108 #     @tp @b COMPILE_DEFINITIONS @endtp
02109 #     <td>CMake code which is evaluated after the inclusion of the default script
02110 #         configuration files. This code can be used to set the replacement text of the
02111 #         CMake variables ("@VAR@" patterns) used in the source files.
02112 #         See <a href="http://www.rad.upenn.edu/sbia/software/basis/standard/scripttargets.html#script-configuration">
02113 #         Build System Standard</a> for details. (default: "")</td>
02114 #   </tr>
02115 #   <tr>
02116 #     @tp @b COMPILE_DEFINITIONS_FILE @endtp
02117 #     <td>CMake script file with compile definitions, also referred to as script
02118 #         configuration file. The named files are included after the default BASIS
02119 #         script configuration and before the @c COMPILE_DEFINITIONS code is being
02120 #         evaluated. (default: @c BINARY_CONFIG_DIR/ScriptConfig.cmake)</td>
02121 #   </tr>
02122 #   <tr>
02123 #     @tp @b EXPORT @endtp
02124 #     <td>Whether to export this build target in which case an import library
02125 #         target is added to the custom exports file with the path to the
02126 #         built/installed modules set as @c IMPORT_LOCATION. (default: @c TRUE)</td>
02127 #   </tr>
02128 #   <tr>
02129 #     @tp @b LANGUAGE @endtp
02130 #     <td>Read-only property of programming language of modules in uppercase letters.
02131 #         (default: see @p LANGUAGE argument)</td>
02132 #   </tr>
02133 #   <tr>
02134 #     @tp @b LIBRARY_COMPONENT @endtp
02135 #     <td>Name of component as part of which this library is installed if
02136 #         @c LIBRARY_INSTALL_DIRECTORY is not set to "none".
02137 #         (default: see @p COMPONENT argument)</td>
02138 #   </tr>
02139 #   <tr>
02140 #     @tp @b LIBRARY_INSTALL_DIRECTORY @endtp
02141 #     <td>Installation directory of library configured for use in installation tree
02142 #         relative to @c CMAKE_INSTALL_PREFIX. Set to "none" (case-insensitive) to skip the
02143 #         addition of an installation rule.
02144 #         (default: <tt>INSTALL_&lt;LANGUAGE&gt;_LIBRARY_DIR</tt> if defined or
02145 #         @c INSTALL_LIBRARY_DIR otherwise)</td>
02146 #   </tr>
02147 #   <tr>
02148 #     @tp @b LIBRARY_OUTPUT_DIRECTORY @endtp
02149 #     <td>Output directory of library configured for use within the build tree.
02150 #         (default: <tt>BINARY_&lt;LANGUAGE&gt;_LIBRARY_DIR</tt> if defined or
02151 #         @c BINARY_LIBRARY_DIR otherwise)</td>
02152 #   </tr>
02153 #   <tr>
02154 #     @tp @b LINK_DEPENDS @endtp
02155 #     <td>Paths or target names of script modules and libraries used by this script.
02156 #         For each listed build target, a dependency is added between this
02157 #         library target and the named build targets. Use basis_target_link_libraries()
02158 #         to add additional link dependencies. Further note that if this library is
02159 #         a link dependency of an executable script added by basis_add_executable()
02160 #         (i.e., basis_add_script() actually), the link dependencies of this library
02161 #         are inherited by the executable script.
02162 #         (default: BASIS utilities module if used or empty list otherwise)</td>
02163 #   </tr>
02164 #   <tr>
02165 #     @tp @b PREFIX @endtp
02166 #     <td>Common module prefix. The given directory path is appended to both
02167 #         @c LIBRAR_OUTPUT_DIRECTORY and @c LIBRARY_INSTALL_DIRECTORY and can,
02168 #         for example, be used to install modules of a Python package as part of
02169 #         another Python package, where @c LIBRARY_OUTPUT_DIRECTORY or
02170 #         @c LIBRARY_INSTALL_DIRECTORY, respectively, is the directory of the
02171 #         main package which is added to the @c PYTHONPATH. Possibly missing
02172 #         __init__.py files in case of Python are generated by the _initpy target
02173 #         which is automatically added by BASIS in that case and further added to
02174 #         the dependencies of this library target.
02175 #         (default: @c PROJECT_NAMESPACE_PYTHON if @c LANGUAGE is @c PYTHON with
02176 #         periods (.) replaced by slashes (/), @c PROJECT_NAMESPACE_PERL if
02177 #         @c LANGUAGE is @c PERL with <tt>::</tt> replaced by slashes (/),
02178 #         and "" otherwise)</td>
02179 #   </tr>
02180 #   <tr>
02181 #     @tp @b SOURCE_DIRECTORY @endtp
02182 #     <td>Source directory of this target. This directory is in particular
02183 #         used to convert the paths of the given source files to relative paths.
02184 #         The built modules within the build and installation tree will have the
02185 #         same relative path (relative to the @c LIBRARY_OUTPUT_DIRECTORY or
02186 #         @c LIBRARY_INSTALL_DIRECTORY, respectively).
02187 #         (default: @c CMAKE_CURRENT_SOURCE_DIR)</td>
02188 #   </tr>
02189 #   <tr>
02190 #     @tp @b SOURCES @endtp
02191 #     <td>Read-only property which lists the source files of this library.
02192 #         Note that the first element in this list actually names a directory
02193 #         in the build, the one where the build script for this target is located
02194 #         instead of a source file and thus should be ignored.</td>
02195 #   </tr>
02196 # </table>
02197 #
02198 # @attention Properties documented as read-only must not be modified.
02199 #
02200 # @param [in] TARGET_NAME Name of build target.
02201 # @param [in] ARGN        The remaining arguments are parsed and the following
02202 #                         arguments extracted. All unparsed arguments are treated
02203 #                         as the module files of the script library.
02204 # @par
02205 # <table border=0>
02206 #   <tr>
02207 #     @tp @b COMPONENT name @endtp
02208 #     <td>Name of installation component as part of which this library is being
02209 #         installed if the @c LIBRARY_INSTALL_DIRECTORY property is not "none".
02210 #         (default: @c BASIS_LIBRARY_COMPONENT)</td>
02211 #   </tr>
02212 #   <tr>
02213 #     @tp @b DESTINATION dir @endtp
02214 #     <td>Installation directory for library relative to @c CMAKE_INSTALL_PREFIX.
02215 #         If an absolute path is given as argument, it is made relative to the
02216 #         configured installation prefix. (default: @c INSTALL_LIBRARY_DIR)</td>
02217 #   </tr>
02218 #   <tr>
02219 #     @tp @b LANGUAGE lang @endtp
02220 #     <td>Programming language in which modules are written (case-insensitive).
02221 #         If not specified, the programming language is derived from the file name
02222 #         extensions of the source files and the shebang directive on the first line
02223 #         of each module if any. If the programming language could not be detected
02224 #         automatically, the @c LANGUAGE property is set to @c UNKNOWN. Note that
02225 #         for script library targets, the library may still be built correctly
02226 #         even if the scripting language was not recognized. The automatic detection
02227 #         whether the BASIS utilities are used and required will fail, however.
02228 #         In this case, specify the programming language using this option.
02229 #         (default: auto-detected or @c UNKNOWN)</td>
02230 #   </tr>
02231 #   <tr>
02232 #     @tp @b [NO]EXPORT @endtp
02233 #     <td>Whether to export this target. (default: @c TRUE)</td>
02234 #   </tr>
02235 #   <tr>
02236 #     @tp @b NO_BASIS_UTILITIES @endtp
02237 #     <td>Specify that the BASIS utilities are not used by this library. If the
02238 #         programming language of the modules is known and BASIS utilities are
02239 #         available for this language, BASIS will in most cases automatically
02240 #         detect whether these utilities are used by any module of this library.
02241 #         Use this option to skip this check in the case that no module makes
02242 #         use of the BASIS utilities.</td>
02243 #   </tr>
02244 #   <tr>
02245 #     @tp @b USE_BASIS_UTILITIES @endtp
02246 #     <td>Specify that the BASIS utilities are used and thus required by this library.
02247 #         If the programming language of the modules is known and BASIS utilities are
02248 #         available for this language, BASIS will in most cases automatically
02249 #         detect whether these utilities are used by any module of this library.
02250 #         Use this option to skip this check when it is already known that no module
02251 #         makes use of the BASIS utilities. Note that an error is raised if this option
02252 #         is given, but no BASIS utilities are available for the programming language
02253 #         of this script or if the programming language is unknown, respectively, not
02254 #         detected correctly. In this case, consider the use of the @p LANGUAGE argument.</td>
02255 #   </tr>
02256 # </table>
02257 #
02258 # @returns Adds a custom CMake target with the documented properties. The actual custom
02259 #          command to build the library is added by basis_build_script_library().
02260 #
02261 # @sa basis_add_library()
02262 function (basis_add_script_library TARGET_NAME)
02263   # check target name
02264   basis_check_target_name ("${TARGET_NAME}")
02265   basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
02266   message (STATUS "Adding script library ${TARGET_UID}...")
02267   # dump CMake variables for configuration of script
02268   set (BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TARGET_UID}.dir")
02269   basis_dump_variables ("${BUILD_DIR}/cache.cmake")
02270   # parse arguments
02271   CMAKE_PARSE_ARGUMENTS (
02272     ARGN
02273       "NO_BASIS_UTILITIES;USE_BASIS_UTILITIES;EXPORT;NOEXPORT"
02274       "COMPONENT;DESTINATION;LANGUAGE"
02275       ""
02276     ${ARGN}
02277   )
02278   basis_set_flag (ARGN EXPORT ${BASIS_EXPORT})
02279   set (SOURCES "${ARGN_UNPARSED_ARGUMENTS}")
02280   # TEST flag
02281   basis_sanitize_for_regex (RE "${PROJECT_TESTING_DIR}")
02282   if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${RE}")
02283     set (TEST TRUE)
02284   else ()
02285     set (TEST FALSE)
02286   endif ()
02287   # check source files
02288   set (_SOURCES)
02289   foreach (S IN LISTS SOURCES)
02290     get_filename_component (S "${S}" ABSOLUTE)
02291     if (NOT EXISTS "${S}" AND NOT S MATCHES "\\.in$" AND EXISTS "${S}.in" AND NOT IS_DIRECTORY "${S}.in")
02292       set (S "${S}.in")
02293     elseif (IS_DIRECTORY "${S}")
02294       message (FATAL_ERROR "Target ${TARGET_UID}: Directory ${S} given where file name expected!")
02295     endif ()
02296     if (NOT EXISTS "${S}")
02297       string (REGEX REPLACE "\\.in$" "" S "${S}")
02298       message (FATAL_ERROR "Target ${TARGET_UID}: Source file ${S}[.in] does not exist!")
02299     endif ()
02300     list (APPEND _SOURCES "${S}")
02301   endforeach ()
02302   if (NOT _SOURCES)
02303     message (FATAL_ERROR "Target ${TARGET_UID}: No source files specified!")
02304   endif ()
02305   set (SOURCES "${_SOURCES}")
02306   unset (_SOURCES)
02307   # auto-detect programming language (may be as well UNKNOWN)
02308   string (TOUPPER "${ARGN_LANGUAGE}" ARGN_LANGUAGE)
02309   if (NOT ARGN_LANGUAGE)
02310     basis_get_source_language (ARGN_LANGUAGE ${SOURCES})
02311     if (ARGN_LANGUAGE MATCHES "AMBIGUOUS|UNKNOWN")
02312       message (FATAL_ERROR "Target ${TARGET_UID}: Failed to determine programming"
02313                            " language of modules! Make sure that all modules are"
02314                            " written in the same language and that the used programming"
02315                            " language is supported by BASIS, i.e., either Python (Jython),"
02316                            " Perl, Bash, or MATLAB. Otherwise, try to specify the language"
02317                            " explicitly using the LANGUAGE option.")
02318     endif ()
02319   endif ()
02320   # output directory
02321   if (TEST)
02322     if (DEFINED TESTING_${ARGN_LANGUAGE}_LIBRARY_DIR)
02323       set (OUTPUT_DIRECTORY "${TESTING_${ARGN_LANGUAGE}_LIBRARY_DIR}")
02324     else ()
02325       set (OUTPUT_DIRECTORY "${TESTING_LIBRARY_DIR}")
02326     endif ()
02327   else ()
02328     if (DEFINED BINARY_${ARGN_LANGUAGE}_LIBRARY_DIR)
02329       set (OUTPUT_DIRECTORY "${BINARY_${ARGN_LANGUAGE}_LIBRARY_DIR}")
02330     else ()
02331       set (OUTPUT_DIRECTORY "${BINARY_LIBRARY_DIR}")
02332     endif ()
02333   endif ()
02334   # installation component
02335   if (NOT ARGN_COMPONENT)
02336     set (ARGN_COMPONENT "${BASIS_LIBRARY_COMPONENT}")
02337   endif ()
02338   if (NOT ARGN_COMPONENT)
02339     set (ARGN_COMPONENT "Unspecified")
02340   endif ()
02341   # installation directory
02342   if (TEST)
02343     if (ARGN_DESTINATION)
02344       message (WARNING "Target ${TARGET_UID} is a library used for testing only."
02345                        " Installation to the specified directory will be skipped.")
02346       set (ARGN_DESTINATION)
02347     endif ()
02348   else ()
02349     if (ARGN_DESTINATION)
02350       if (IS_ABSOLUTE "${ARGN_DESTINATION}")
02351         file (RELATIVE_PATH ARGN_DESTINATION "${CMAKE_INSTALL_PREFIX}" "${ARGN_DESTINATION}")
02352       endif ()
02353     else ()
02354       if (DEFINED INSTALL_${ARGN_LANGUAGE}_LIBRARY_DIR)
02355         set (ARGN_DESTINATION "${INSTALL_${ARGN_LANGUAGE}_LIBRARY_DIR}")
02356       else ()
02357         set (ARGN_DESTINATION "${INSTALL_LIBRARY_DIR}")
02358       endif ()
02359     endif ()
02360   endif ()
02361   # common module prefix
02362   if (ARGN_LANGUAGE MATCHES "^([JP]YTHON|PERL|MATLAB|BASH)$")
02363     basis_library_prefix (PREFIX ${ARGN_LANGUAGE})
02364   else ()
02365     set (PREFIX)
02366   endif ()
02367   # script configuration ("compile definitions")
02368   if (EXISTS "${BINARY_CONFIG_DIR}/ScriptConfig.cmake")
02369     set (CONFIG_FILE "${BINARY_CONFIG_DIR}/ScriptConfig.cmake")
02370   else ()
02371     set (CONFIG_FILE)
02372   endif ()
02373   # auto-detect use of BASIS utilities
02374   if (ARGN_LANGUAGE MATCHES "[JP]YTHON")
02375     set (UTILITIES_LANGUAGE "PYTHON")
02376   else ()
02377     set (UTILITIES_LANGUAGE "${ARGN_LANGUAGE}")
02378   endif ()
02379   if (ARGN_USE_BASIS_UTILITIES)
02380     if (NOT BASIS_UTILITIES_ENABLED MATCHES "${UTILITIES_LANGUAGE}")
02381       message (FATAL_ERROR "Target ${TARGET_UID} requires the BASIS utilities for ${UTILITIES_LANGUAGE}"
02382                            " but BASIS was either build without the build of these utilities enabled"
02383                            " or no utilities for this programming language are implemented. Remove the"
02384                            " USE_BASIS_UTILITIES option if no BASIS utilities are used by the modules"
02385                            " of the library or specify the correct programming language if it was not"
02386                            " detected correctly.")
02387     endif ()
02388     set (USES_BASIS_UTILITIES TRUE)
02389   elseif (NOT ARGN_NO_BASIS_UTILITIES AND NOT UTILITIES_LANGUAGE MATCHES "UNKNOWN")
02390     set (USES_BASIS_UTILITIES FALSE)
02391     foreach (M IN LISTS SOURCES)
02392       basis_utilities_check (USES_BASIS_UTILITIES "${M}" ${UTILITIES_LANGUAGE})
02393       if (USES_BASIS_UTILITIES)
02394         break ()
02395       endif ()
02396     endforeach ()
02397   else ()
02398     set (USES_BASIS_UTILITIES FALSE)
02399   endif ()
02400   if (USES_BASIS_UTILITIES)
02401     basis_set_project_property (PROPERTY PROJECT_USES_${UTILITIES_LANGUAGE}_UTILITIES TRUE)
02402     if (BASIS_DEBUG)
02403       message ("** Target ${TARGET_UID} uses the BASIS utilities for ${UTILITIES_LANGUAGE}.")
02404     endif ()
02405   endif ()
02406   # add custom target
02407   add_custom_target (${TARGET_UID} ALL SOURCES ${SOURCES})
02408   _set_target_properties (
02409     ${TARGET_UID}
02410     PROPERTIES
02411       LANGUAGE                  "${ARGN_LANGUAGE}"
02412       BASIS_TYPE                "SCRIPT_LIBRARY"
02413       BASIS_UTILITIES           "${USES_BASIS_UTILITIES}"
02414       SOURCE_DIRECTORY          "${CMAKE_CURRENT_SOURCE_DIR}"
02415       BINARY_DIRECTORY          "${CMAKE_CURRENT_BINARY_DIR}"
02416       LIBRARY_OUTPUT_DIRECTORY  "${OUTPUT_DIRECTORY}"
02417       LIBRARY_INSTALL_DIRECTORY "${ARGN_DESTINATION}"
02418       LIBRARY_COMPONENT         "${BASIS_LIBRARY_COMPONENT}"
02419       PREFIX                    "${PREFIX}"
02420       COMPILE_DEFINITIONS       ""
02421       COMPILE_DEFINITIONS_FILE  "${CONFIG_FILE}"
02422       LINK_DEPENDS              ""
02423       EXPORT                    "${EXPORT}"
02424       COMPILE                   "${BASIS_COMPILE_SCRIPTS}"
02425       TEST                      "${TEST}"
02426   )
02427   # add target to list of targets
02428   basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET_UID}")
02429   message (STATUS "Adding script library ${TARGET_UID}... - done")
02430 endfunction ()
02431 
02432 # ============================================================================
02433 # custom build commands
02434 # ============================================================================
02435 
02436 # ----------------------------------------------------------------------------
02437 ## @brief Finalize custom targets by adding the missing build commands.
02438 #
02439 # This function is called by basis_project_impl() in order to finalize the
02440 # addition of the custom build targets such as, for example, build targets
02441 # for the build of executable scripts, Python packages, MATLAB Compiler
02442 # executables and shared libraries, and MEX-files.
02443 #
02444 # @returns Generates the CMake build scripts and adds custom build commands
02445 #          and corresponding targets for the execution of these scripts.
02446 #
02447 # @sa basis_build_script()
02448 # @sa basis_build_script_library()
02449 # @sa basis_build_mcc_target()
02450 # @sa basis_build_mex_file()
02451 function (basis_finalize_targets)
02452   basis_get_project_property (TARGETS PROPERTY TARGETS)
02453   foreach (TARGET_UID ${TARGETS})
02454     if (NOT TARGET _${TARGET_UID})
02455       get_target_property (BASIS_TYPE ${TARGET_UID} BASIS_TYPE)
02456       if (BASIS_TYPE MATCHES "^EXECUTABLE$|^(SHARED|MODULE)_LIBRARY$")
02457         basis_set_target_install_rpath (${TARGET_UID})
02458       elseif (BASIS_TYPE MATCHES "SCRIPT_LIBRARY")
02459         basis_build_script_library (${TARGET_UID})
02460       elseif (BASIS_TYPE MATCHES "SCRIPT")
02461         basis_build_script (${TARGET_UID})
02462       elseif (BASIS_TYPE MATCHES "MEX")
02463         basis_build_mex_file (${TARGET_UID})
02464       elseif (BASIS_TYPE MATCHES "MCC")
02465         basis_build_mcc_target (${TARGET_UID})
02466       endif ()
02467     endif ()
02468   endforeach ()
02469 endfunction ()
02470 
02471 # ----------------------------------------------------------------------------
02472 ## @brief Set INSTALL_RPATH property of executable or shared library target.
02473 #
02474 # This function sets the @c INSTALL_RPATH property of a specified executable or
02475 # shared library target using the @c LINK_DEPENDS obtained using the
02476 # basis_get_target_link_libraries() function. It determines the installation
02477 # location of each dependency using the basis_get_target_location() function.
02478 #
02479 # @returns Sets the @c INSTALL_RPATH property of the specified target.
02480 #
02481 # @sa basis_get_target_link_libraries()
02482 function (basis_set_target_install_rpath TARGET_NAME)
02483   basis_get_target_uid (TARGET_UID "${TARGET_NAME}")
02484   if (NOT TARGET "${TARGET_UID}")
02485     message (FATAL_ERROR "Unknown target: ${TARGET_UID}")
02486   endif ()
02487   if (BASIS_DEBUG)
02488     message ("** basis_set_target_install_rpath():")
02489     message ("**    TARGET_NAME:   ${TARGET_UID}")
02490   endif ()
02491   if (CMAKE_HOST_APPLE)
02492     set (ORIGIN "@loader_path")
02493   else ()
02494     set (ORIGIN "\$ORIGIN")
02495   endif ()
02496   # always prefer libraries located within the same directory
02497   set (INSTALL_RPATH "${ORIGIN}/.")
02498   # common default RPATH (rarely used)
02499   if (CMAKE_INSTALL_RPATH)
02500     set (INSTALL_RPATH "${INSTALL_RPATH};${CMAKE_INSTALL_RPATH}")
02501   endif ()
02502   # get location of target used to make paths relative to this $ORIGIN
02503   basis_get_target_location (TARGET_LOCATION ${TARGET_UID} POST_INSTALL_PATH)
02504   # directories of external projects belonging to same bundle which
02505   # were added using [basis_]link_directories() command
02506   basis_get_project_property (BUNDLE_LINK_DIRS PROPERTY BUNDLE_LINK_DIRS)
02507   foreach (LINK_DIR ${BUNDLE_LINK_DIRS})
02508     list (FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${LINK_DIR}" IDX)
02509     if (IDX EQUAL -1)
02510       if (BASIS_DEBUG AND BASIS_VERBOSE)
02511         message ("**    BUNDLE_LINK_DIR: ${LINK_DIR}")
02512       endif ()
02513       basis_get_relative_path (RPATH "${TARGET_LOCATION}" "${LINK_DIR}")
02514       list (APPEND INSTALL_RPATH "${ORIGIN}/${RPATH}")
02515     endif ()
02516   endforeach ()
02517   # directories of link libraries
02518   #
02519   # only the libraries of this project and targets imported
02520   # from other projects which are part of the same bundle
02521   basis_get_target_link_libraries (LINK_DEPENDS ${TARGET_UID})
02522   if (BASIS_DEBUG AND BASIS_VERBOSE)
02523     message ("**    LINK_DEPENDS: [${LINK_DEPENDS}]")
02524   endif ()
02525   foreach (LINK_DEPEND ${LINK_DEPENDS})
02526     set (DEPEND_LOCATION)
02527     if (TARGET "${LINK_DEPEND}")
02528       basis_get_target_property (BUNDLED  ${LINK_DEPEND} BUNDLED)
02529       basis_get_target_property (IMPORTED ${LINK_DEPEND} IMPORTED)
02530       if (NOT IMPORTED OR BUNDLED)
02531         basis_get_target_location (DEPEND_LOCATION ${LINK_DEPEND} POST_INSTALL_PATH)
02532         if (BASIS_DEBUG AND BASIS_VERBOSE)
02533           message ("**    LOCATION(${LINK_DEPEND}): ${DEPEND_LOCATION}")
02534         endif ()
02535       endif ()
02536     elseif (IS_ABSOLUTE "${LINK_DEPEND}")
02537       if (IS_DIRECTORY "${LINK_DEPEND}")
02538         set (DEPEND_LOCATION "${LINK_DEPEND}")
02539       else ()
02540         get_filename_component (DEPEND_LOCATION "${LINK_DEPEND}" PATH)
02541       endif ()
02542       list (FIND BUNDLE_LINK_DIRS "${DEPEND_LOCATION}" IDX)
02543       if (IDX EQUAL -1)
02544         set (DEPEND_LOCATION)
02545       endif ()
02546     endif ()
02547     if (DEPEND_LOCATION)
02548       list (FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${DEPEND_LOCATION}" IDX)
02549       if (IDX EQUAL -1)
02550         basis_get_relative_path (RPATH "${TARGET_LOCATION}" "${DEPEND_LOCATION}")
02551         list (APPEND INSTALL_RPATH "${ORIGIN}/${RPATH}")
02552       endif ()
02553     endif ()
02554   endforeach ()
02555   # remove duplicates
02556   if (INSTALL_RPATH)
02557     list (REMOVE_DUPLICATES INSTALL_RPATH)
02558   endif ()
02559   # set INSTALL_RPATH property
02560   string (REPLACE ";" ":" INSTALL_RPATH "${INSTALL_RPATH}")
02561   _set_target_properties (${TARGET_UID} PROPERTIES INSTALL_RPATH "${INSTALL_RPATH}")
02562   if (BASIS_DEBUG)
02563     message ("**    INSTALL_RPATH: [${INSTALL_RPATH}]")
02564   endif ()
02565 endfunction ()
02566 
02567 # ----------------------------------------------------------------------------
02568 ## @brief Add custom command for build of single script.
02569 #
02570 # This function is called by basis_finalize_targets() which in turn is called
02571 # at the end of basis_project_impl(), i.e., the end of the root CMake
02572 # configuration file of the (sub-)project.
02573 #
02574 # @param [in] TARGET_UID Name/UID of custom target added by basis_add_script().
02575 #
02576 # @sa basis_add_script()
02577 function (basis_build_script TARGET_UID)
02578   # does this target exist ?
02579   basis_get_target_uid (TARGET_UID "${TARGET_UID}")
02580   if (NOT TARGET "${TARGET_UID}")
02581     message (FATAL_ERROR "Unknown build target: ${TARGET_UID}")
02582   endif ()
02583   if (BASIS_VERBOSE)
02584     message (STATUS "Adding build command for target ${TARGET_UID}...")
02585   endif ()
02586   # get target properties
02587   basis_get_target_link_libraries (LINK_DEPENDS ${TARGET_UID}) # paths of script modules/packages
02588                                                                # including BASIS utilities if used
02589   set (
02590     PROPERTIES
02591       LANGUAGE                 # programming language of script
02592       BASIS_TYPE               # must match "^SCRIPT_(EXECUTABLE|LIBEXEC|MODULE)$"
02593       SOURCE_DIRECTORY         # CMake source directory
02594       BINARY_DIRECTORY         # CMake binary directory
02595       OUTPUT_DIRECTORY         # output directory for built script
02596       INSTALL_DIRECTORY        # installation directory for built script
02597       COMPONENT                # installation component
02598       OUTPUT_NAME              # name of built script including extension (if any)
02599       PREFIX                   # name prefix
02600       SUFFIX                   # name suffix (e.g., extension for executable script)
02601       COMPILE_DEFINITIONS      # CMake code to set variables used to configure script
02602       COMPILE_DEFINITIONS_FILE # script configuration file
02603       TEST                     # whether this script is used for testing only
02604       EXPORT                   # whether this target shall be exported
02605       COMPILE                  # whether to compile script if applicable
02606       SOURCES                  # path of script source file
02607   )
02608   foreach (PROPERTY ${PROPERTIES})
02609     get_target_property (${PROPERTY} ${TARGET_UID} ${PROPERTY})
02610   endforeach ()
02611   set (EXECUTABLE FALSE)
02612   set (LIBEXEC    FALSE)
02613   set (MODULE     FALSE)
02614   if (BASIS_TYPE MATCHES "^SCRIPT_(EXECUTABLE|LIBEXEC|MODULE)$")
02615     set (${CMAKE_MATCH_1} TRUE)
02616     if (LIBEXEC)
02617       set (EXECUTABLE TRUE)
02618     endif ()
02619   else ()
02620     message (FATAL_ERROR "Target ${TARGET_UID}: Unexpected BASIS_TYPE: ${BASIS_TYPE}")
02621   endif ()
02622   if (NOT BINARY_DIRECTORY)
02623     message (FATAL_ERROR "Target ${TARGET_UID}: Missing BINARY_DIRECTORY property!")
02624   endif ()
02625   if (NOT BINARY_DIRECTORY MATCHES "^${CMAKE_BINARY_DIR}(/|$)")
02626     message (FATAL_ERROR "Target ${TARGET_UID}: BINARY_DIRECTORY must be inside of build tree!")
02627   endif ()
02628   if (INSTALL_DIRECTORY AND NOT COMPONENT)
02629     set (COMPONENT "Unspecified")
02630   endif ()
02631   list (LENGTH SOURCES L)
02632   if (NOT L EQUAL 2)
02633     message (FATAL_ERROR "Target ${TARGET_UID}: Expected two elements in SOURCES list!"
02634                          " Have you accidentally modified this read-only property or"
02635                          " is your (newer) CMake version not compatible with BASIS?")
02636   endif ()
02637   list (GET SOURCES 0 BUILD_DIR) # strange, but CMake stores path to internal build directory here
02638   list (GET SOURCES 1 SOURCE_FILE)
02639   set (BUILD_DIR "${BUILD_DIR}.dir")
02640   # output name
02641   if (NOT OUTPUT_NAME)
02642     basis_get_target_name (OUTPUT_NAME ${TARGET_UID})
02643   endif ()
02644   if (PREFIX)
02645     set (OUTPUT_NAME "${PREFIX}${OUTPUT_NAME}")
02646   endif ()
02647   if (SUFFIX)
02648     set (OUTPUT_NAME "${OUTPUT_NAME}${SUFFIX}")
02649   endif ()
02650   # arguments of build script
02651   set (OUTPUT_FILE "${OUTPUT_DIRECTORY}/${OUTPUT_NAME}")
02652   if (INSTALL_DIRECTORY)
02653     get_filename_component (SOURCE_NAME "${SOURCE_FILE}" NAME)
02654     set (INSTALL_FILE "${BUILD_DIR}/build/${SOURCE_NAME}")
02655     string (REGEX REPLACE "\\.in$" "" INSTALL_FILE "${INSTALL_FILE}")
02656     set (DESTINATION "${INSTALL_DIRECTORY}")
02657     if (NOT IS_ABSOLUTE "${DESTINATION}")
02658       set (DESTINATION "${CMAKE_INSTALL_PREFIX}/${DESTINATION}")
02659     endif ()
02660   else ()
02661     set (INSTALL_FILE)
02662     set (DESTINATION)
02663   endif ()
02664   set (CONFIG_FILE)
02665   if (EXISTS "${BASIS_SCRIPT_CONFIG_FILE}")
02666     list (APPEND CONFIG_FILE "${BASIS_SCRIPT_CONFIG_FILE}")
02667   endif ()
02668   if (COMPILE_DEFINITIONS_FILE)
02669     list (APPEND CONFIG_FILE ${COMPILE_DEFINITIONS_FILE})
02670   endif ()
02671   if (COMPILE_DEFINITIONS)
02672     file (WRITE "${BUILD_DIR}/ScriptConfig.cmake" "# DO NOT edit. Automatically generated by BASIS.\n${COMPILE_DEFINITIONS}\n")
02673     list (APPEND CONFIG_FILE "${BUILD_DIR}/ScriptConfig.cmake")
02674   endif ()
02675   set (CACHE_FILE "${BUILD_DIR}/cache.cmake")
02676   set (OPTIONS)
02677   foreach (FLAG IN ITEMS COMPILE EXECUTABLE)
02678     if (${FLAG})
02679       list (APPEND OPTIONS ${FLAG})
02680     endif ()
02681   endforeach ()
02682   # link dependencies - module search paths
02683   set (BUILD_LINK_DEPENDS)
02684   set (INSTALL_LINK_DEPENDS)
02685   foreach (LINK_DEPEND IN LISTS LINK_DEPENDS)
02686     basis_get_target_uid (UID "${LINK_DEPEND}")
02687     if (TARGET "${UID}")
02688       get_target_property (IMPORTED ${UID} IMPORTED)
02689       get_target_property (BUNDLED  ${UID} BUNDLED)
02690       if (IMPORTED AND NOT BUNDLED)
02691         basis_get_target_location (LOCATION "${UID}" ABSOLUTE)
02692         if (LOCATION)
02693           list (APPEND BUILD_LINK_DEPENDS   "${LOCATION}")
02694           list (APPEND INSTALL_LINK_DEPENDS "${LOCATION}")
02695         else ()
02696           message (WARNING "Could not determine build tree location of file corresponding to target ${UID}")
02697         endif ()
02698       else ()
02699         basis_get_target_location (LOCATION "${UID}" ABSOLUTE)
02700         if (LOCATION)
02701           list (APPEND BUILD_LINK_DEPENDS "${LOCATION}")
02702         else ()
02703           message (WARNING "Could not determine build tree location of file corresponding to target ${UID}")
02704         endif ()
02705         basis_get_target_property (LINK_DEPEND_IS_TEST "${UID}" TEST)
02706         if (NOT LINK_DEPEND_IS_TEST)
02707           basis_get_target_location (LOCATION "${UID}" POST_INSTALL)
02708           if (LOCATION)
02709             list (APPEND INSTALL_LINK_DEPENDS "relative ${LOCATION}")
02710           else ()
02711             message (WARNING "Could not determine installation location of file corresponding to target ${UID}")
02712           endif ()
02713         endif ()
02714       endif ()
02715     else ()
02716       list (APPEND BUILD_LINK_DEPENDS   "${LINK_DEPEND}")
02717       list (APPEND INSTALL_LINK_DEPENDS "${LINK_DEPEND}")
02718     endif ()
02719   endforeach ()
02720   # prepend own module search paths - if dependencies among own modules
02721   #                                   not specified or to ensure that
02722   #                                   these are preferred
02723   if (LANGUAGE MATCHES "JYTHON")
02724     if (BINARY_PYTHON_LIBRARY_DIR)
02725       list (INSERT BUILD_LINK_DEPENDS 0 "${BINARY_PYTHON_LIBRARY_DIR}")
02726     endif ()
02727     if (INSTALL_PYTHON_LIBRARY_DIR)
02728       list (INSERT INSTALL_LINK_DEPENDS 0 "relative ${CMAKE_INSTALL_PREFIX}/${INSTALL_PYTHON_LIBRARY_DIR}")
02729     endif ()
02730   endif ()
02731   if (BINARY_${LANGUAGE}_LIBRARY_DIR)
02732     list (INSERT BUILD_LINK_DEPENDS 0 "${BINARY_${LANGUAGE}_LIBRARY_DIR}")
02733   endif ()
02734   if (INSTALL_${LANGUAGE}_LIBRARY_DIR)
02735     list (INSERT INSTALL_LINK_DEPENDS 0 "relative ${CMAKE_INSTALL_PREFIX}/${INSTALL_${LANGUAGE}_LIBRARY_DIR}")
02736   endif ()
02737   list (INSERT BUILD_LINK_DEPENDS   0 "${BINARY_LIBRARY_DIR}")
02738   list (INSERT INSTALL_LINK_DEPENDS 0 "relative ${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBRARY_DIR}")
02739   if (TEST)
02740     list (INSERT BUILD_LINK_DEPENDS 0 "${TESTING_LIBRARY_DIR}")
02741   endif ()
02742   if (BUILD_LINK_DEPENDS)
02743     list (REMOVE_DUPLICATES BUILD_LINK_DEPENDS)
02744   endif ()
02745   if (INSTALL_LINK_DEPENDS)
02746     list (REMOVE_DUPLICATES INSTALL_LINK_DEPENDS)
02747   endif ()
02748   # remove default site-packages directories
02749   if (LANGUAGE MATCHES "[JP]YTHON|PERL")
02750     list (REMOVE_ITEM BUILD_LINK_DEPENDS   "${${LANGUAGE}_SITELIB}")
02751     list (REMOVE_ITEM INSTALL_LINK_DEPENDS "${${LANGUAGE}_SITELIB}")
02752   endif ()
02753   # configure build script
02754   set (BUILD_SCRIPT "${BUILD_DIR}/build.cmake")
02755   configure_file ("${BASIS_MODULE_PATH}/configure_script.cmake.in" "${BUILD_SCRIPT}" @ONLY)
02756   # list of all output files
02757   set (OUTPUT_FILES "${OUTPUT_FILE}")
02758   if (INSTALL_FILE)
02759     list (APPEND OUTPUT_FILES "${INSTALL_FILE}")
02760   endif ()
02761   if (MODULE AND COMPILE)
02762     basis_get_compiled_file (OUTPUT_CFILE  "${OUTPUT_FILE}"  ${LANGUAGE})
02763     basis_get_compiled_file (INSTALL_CFILE "${INSTALL_FILE}" ${LANGUAGE})
02764     if (OUTPUT_CFILE)
02765       list (APPEND OUTPUT_FILES "${OUTPUT_CFILE}")
02766     endif ()
02767     if (INSTALL_CFILE)
02768       list (APPEND OUTPUT_FILES "${INSTALL_CFILE}")
02769     endif ()
02770     if (LANGUAGE MATCHES "PYTHON")
02771       basis_compile_python_modules_for_jython (RV)
02772       if (RV)
02773         basis_get_compiled_jython_file_of_python_module (JYTHON_OUTPUT_CFILE "${OUTPUT_FILE}")
02774         basis_get_compiled_file (JYTHON_INSTALL_CFILE "${INSTALL_FILE}" JYTHON)
02775         if (JYTHON_OUTPUT_CFILE)
02776           list (APPEND OUTPUT_FILES "${JYTHON_OUTPUT_CFILE}")
02777         endif ()
02778         if (JYTHON_INSTALL_CFILE)
02779           list (APPEND OUTPUT_FILES "${JYTHON_INSTALL_CFILE}")
02780         endif ()
02781       endif ()
02782     endif ()
02783   endif ()
02784   # add build command for script
02785   if (OUTPUT_CFILE)
02786     file (RELATIVE_PATH REL "${CMAKE_BINARY_DIR}" "${OUTPUT_CFILE}")
02787   else ()
02788     file (RELATIVE_PATH REL "${CMAKE_BINARY_DIR}" "${OUTPUT_FILE}")
02789   endif ()
02790   if (LANGUAGE MATCHES "UNKNOWN")
02791     set (COMMENT "Building script ${REL}...")
02792   elseif (MODULE)
02793     set (COMMENT "Building ${LANGUAGE} module ${REL}...")
02794   else ()
02795     set (COMMENT "Building ${LANGUAGE} executable ${REL}...")
02796   endif ()
02797   add_custom_command (
02798     OUTPUT          ${OUTPUT_FILES}
02799     COMMAND         "${CMAKE_COMMAND}" -P "${BUILD_SCRIPT}"
02800     MAIN_DEPENDENCY "${SOURCE_FILE}"
02801     DEPENDS         "${BUILD_SCRIPT}" "${BASIS_MODULE_PATH}/CommonTools.cmake" # basis_configure_script() definition
02802                     "${BUILD_DIR}/cache.cmake" ${CONFIG_FILE}
02803     COMMENT         "${COMMENT}"
02804     VERBATIM
02805   )
02806   # add custom target
02807   add_custom_target (_${TARGET_UID} DEPENDS ${OUTPUT_FILES})
02808   foreach (T IN LISTS LINK_DEPENDS)
02809     if (TARGET ${T})
02810       add_dependencies (_${TARGET_UID} ${T})
02811     endif ()
02812   endforeach ()
02813   if (TARGET __${TARGET_UID}) # re-glob source files
02814     add_dependencies (_${TARGET_UID} __${TARGET_UID})
02815   endif ()
02816   add_dependencies (${TARGET_UID} _${TARGET_UID})
02817   # cleanup on "make clean" - including compiled files regardless of COMPILE flag
02818   set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${OUTPUT_FILES})
02819   foreach (OUTPUT_FILE IN LISTS OUTPUT_FILES)
02820     basis_get_compiled_file (CFILE "${OUTPUT_FILE}" ${LANGUAGE})
02821     if (CFILE)
02822       list (FIND OUTPUT_FILES "${CFILE}" IDX)
02823       if (IDX EQUAL -1)
02824         set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CFILE}")
02825       endif ()
02826     endif ()
02827   endforeach ()
02828   # export target
02829   if (EXPORT)
02830     if (TEST)
02831       basis_set_project_property (APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}")
02832     else ()
02833       basis_set_project_property (APPEND PROPERTY CUSTOM_EXPORT_TARGETS "${TARGET_UID}")
02834     endif ()
02835   endif ()
02836   # install script
02837   if (INSTALL_DIRECTORY)
02838     if (INSTALL_CFILE)
02839       if (MODULE AND LANGUAGE MATCHES "PYTHON")
02840         basis_compile_python_modules_for_jython (RV)
02841         if (RV)
02842           basis_get_compiled_script (INSTALL_JYTHON_CFILE "${INSTALL_FILE}" JYTHON)
02843           basis_sanitize_for_regex (LIBRE  "${INSTALL_PYTHON_LIBRARY_DIR}")
02844           basis_sanitize_for_regex (SITERE "${INSTALL_PYTHON_SITE_DIR}")
02845           if (INSTALL_CFILE MATCHES "^${LIBRE}/" AND INSTALL_JYTHON_LIBRARY_DIR)
02846             string (REGEX REPLACE "^${LIBRE}/" "${INSTALL_JYTHON_LIBRARY_DIR}/" INSTALL_DIRECTORY_JYTHON "${INSTALL_DIRECTORY}")
02847           elseif (INSTALL_CFILE MATCHES "^${SITERE}/" AND INSTALL_JYTHON_SITE_DIR)
02848             string (REGEX REPLACE "^${SITERE}/" "${INSTALL_JYTHON_SITE_DIR}/" INSTALL_DIRECTORY_JYTHON "${INSTALL_DIRECTORY}")
02849           else ()
02850             set (INSTALL_DIRECTORY_JYTHON "${INSTALL_DIRECTORY}")
02851           endif ()
02852           install (
02853             FILES       "${INSTALL_JYTHON_CFILE}"
02854             DESTINATION "${INSTALL_DIRECTORY_JYTHON}"
02855             COMPONENT   "${COMPONENT}"
02856           )
02857         endif ()
02858       endif ()
02859       set (INSTALL_FILE "${INSTALL_CFILE}")
02860     elseif (NOT INSTALL_FILE)
02861       set (INSTALL_FILE "${OUTPUT_FILE}")
02862     endif ()
02863     if (MODULE)
02864       set (INSTALLTYPE FILES)
02865     else ()
02866       set (INSTALLTYPE PROGRAMS)
02867     endif ()
02868     install (
02869       ${INSTALLTYPE} "${INSTALL_FILE}"
02870       DESTINATION    "${INSTALL_DIRECTORY}"
02871       COMPONENT      "${COMPONENT}"
02872       RENAME         "${OUTPUT_NAME}"
02873     )
02874   endif ()
02875   # done
02876   if (BASIS_VERBOSE)
02877     message (STATUS "Adding build command for target ${TARGET_UID}... - done")
02878   endif ()
02879 endfunction ()
02880 
02881 # ----------------------------------------------------------------------------
02882 ## @brief Add custom command for build of script library.
02883 #
02884 # This function is called by basis_finalize_targets() which in turn is called
02885 # at the end of basis_project_impl(), i.e., the end of the root CMake
02886 # configuration file of the (sub-)project.
02887 #
02888 # @param [in] TARGET_UID Name/UID of custom target added by basis_add_script_library().
02889 #
02890 # @sa basis_add_script_library()
02891 function (basis_build_script_library TARGET_UID)
02892   # does this target exist ?
02893   basis_get_target_uid (TARGET_UID "${TARGET_UID}")
02894   if (NOT TARGET "${TARGET_UID}")
02895     message (FATAL_ERROR "Unknown target: ${TARGET_UID}")
02896   endif ()
02897   if (BASIS_VERBOSE)
02898     message (STATUS "Adding build command for target ${TARGET_UID}...")
02899   endif ()
02900   # get target properties
02901   basis_get_target_link_libraries (LINK_DEPENDS ${TARGET_UID}) # paths of script modules/packages
02902                                                                # including BASIS utilities if used
02903   set (
02904     PROPERTIES
02905       LANGUAGE                   # programming language of modules
02906       BASIS_TYPE                 # must be "SCRIPT_LIBRARY"
02907       BASIS_UTILITIES            # whether this target requires the BASIS utilities
02908       SOURCE_DIRECTORY           # CMake source directory
02909       BINARY_DIRECTORY           # CMake binary directory
02910       LIBRARY_OUTPUT_DIRECTORY   # output directory for built modules
02911       LIBRARY_INSTALL_DIRECTORY  # installation directory for built modules
02912       LIBRARY_COMPONENT          # installation component
02913       PREFIX                     # common prefix for modules
02914       COMPILE_DEFINITIONS        # CMake code to set variables used to configure modules
02915       COMPILE_DEFINITIONS_FILE   # script configuration file
02916       LINK_DEPENDS               # paths of script modules/packages used by the modules of this library
02917       EXPORT                     # whether to export this target
02918       COMPILE                    # whether to compile the modules/library if applicable
02919       SOURCES                    # source files of module scripts
02920   )
02921   foreach (PROPERTY ${PROPERTIES})
02922     get_target_property (${PROPERTY} ${TARGET_UID} ${PROPERTY})
02923   endforeach ()
02924   if (NOT BASIS_TYPE MATCHES "^SCRIPT_LIBRARY$")
02925     message (FATAL_ERROR "Target ${TARGET_UID}: Unexpected BASIS_TYPE: ${BASIS_TYPE}")
02926   endif ()
02927   if (NOT SOURCE_DIRECTORY)
02928     message (FATAL_ERROR "Missing SOURCE_DIRECTORY property!")
02929   endif ()
02930   if (NOT LIBRARY_OUTPUT_DIRECTORY)
02931     message (FATAL_ERROR "Missing LIBRARY_OUTPUT_DIRECTORY property!")
02932   endif ()
02933   if (NOT IS_ABSOLUTE "${LIBRARY_OUTPUT_DIRECTORY}")
02934     set (LIBRARY_OUTPUT_DIRECTORY "${BASIS_PROJECT_BINARY_DIR}/${LIBRARY_OUTPUT_DIRECTORY}")
02935   endif ()
02936   if (NOT LIBRARY_OUTPUT_DIRECTORY MATCHES "^${CMAKE_BINARY_DIR}")
02937     message (FATAL_ERROR "Output directory LIBRARY_OUTPUT_DIRECTORY is outside the build tree!")
02938   endif ()
02939   if (NOT LIBRARY_COMPONENT)
02940     set (LIBRARY_COMPONENT "Unspecified")
02941   endif ()
02942   list (GET SOURCES 0 BUILD_DIR) # strange, but CMake stores path to internal build directory here
02943   list (REMOVE_AT SOURCES 0)
02944   set (BUILD_DIR "${BUILD_DIR}.dir")
02945   if (NOT SOURCES)
02946     message (FATAL_ERROR "Target ${TARGET_UID}: Empty SOURCES list!"
02947                          " Have you accidentally modified this read-only property or"
02948                          " is your (newer) CMake version not compatible with BASIS?")
02949   endif ()
02950   # common arguments of build script
02951   set (CONFIG_FILE)
02952   if (EXISTS "${BASIS_SCRIPT_CONFIG_FILE}")
02953     list (APPEND CONFIG_FILE "${BASIS_SCRIPT_CONFIG_FILE}")
02954   endif ()
02955   if (COMPILE_DEFINITIONS_FILE)
02956     list (APPEND CONFIG_FILE ${COMPILE_DEFINITIONS_FILE})
02957   endif ()
02958   if (COMPILE_DEFINITIONS)
02959     file (WRITE "${BUILD_DIR}/ScriptConfig.cmake" "# DO NOT edit. Automatically generated by BASIS.\n${COMPILE_DEFINITIONS}\n")
02960     list (APPEND CONFIG_FILE "${BUILD_DIR}/ScriptConfig.cmake")
02961   endif ()
02962   set (CACHE_FILE "${BUILD_DIR}/cache.cmake")
02963   set (OPTIONS) # no additional options
02964   if (COMPILE)
02965     list (APPEND OPTIONS COMPILE)
02966   endif ()
02967   # add build command for each module
02968   set (OUTPUT_FILES)                                  # list of all output files
02969   set (FILES_TO_INSTALL)                              # list of output files for installation
02970   set (BINARY_INSTALL_DIRECTORY "${BUILD_DIR}/build") # common base directory for files to install 
02971   foreach (SOURCE_FILE IN LISTS SOURCES)
02972     file (RELATIVE_PATH S "${SOURCE_DIRECTORY}" "${SOURCE_FILE}")
02973     string (REGEX REPLACE "\\.in$" "" S "${S}")
02974     basis_get_source_target_name (BUILD_SCRIPT_NAME "build_${S}")
02975     # arguments of build script
02976     if (PREFIX)
02977       set (S "${PREFIX}${S}")
02978     endif ()
02979     set (OUTPUT_FILE    "${LIBRARY_OUTPUT_DIRECTORY}/${S}")
02980     if (LIBRARY_INSTALL_DIRECTORY)
02981       set (INSTALL_FILE "${BINARY_INSTALL_DIRECTORY}/${S}")
02982       set (DESTINATION  "${LIBRARY_INSTALL_DIRECTORY}/${S}")
02983       if (NOT IS_ABSOLUTE "${DESTINATION}")
02984         set (DESTINATION "${CMAKE_INSTALL_PREFIX}/${DESTINATION}")
02985       endif ()
02986       get_filename_component (DESTINATION "${DESTINATION}" PATH)
02987     else ()
02988       set (INSTALL_FILE)
02989       set (DESTINATION)
02990     endif ()
02991     # configure build script
02992     set (BUILD_SCRIPT "${BUILD_DIR}/${BUILD_SCRIPT_NAME}.cmake")
02993     configure_file ("${BASIS_MODULE_PATH}/configure_script.cmake.in" "${BUILD_SCRIPT}" @ONLY)
02994     # output files of this command
02995     set (_OUTPUT_FILES "${OUTPUT_FILE}")
02996     if (INSTALL_FILE)
02997       list (APPEND _OUTPUT_FILES "${INSTALL_FILE}")
02998     endif ()
02999     if (COMPILE)
03000       basis_get_compiled_file (OUTPUT_CFILE  "${OUTPUT_FILE}"  ${LANGUAGE})
03001       basis_get_compiled_file (INSTALL_CFILE "${INSTALL_FILE}" ${LANGUAGE})
03002       if (OUTPUT_CFILE)
03003         list (APPEND _OUTPUT_FILES "${OUTPUT_CFILE}")
03004       endif ()
03005       if (INSTALL_CFILE)
03006         list (APPEND _OUTPUT_FILES "${INSTALL_CFILE}")
03007       endif ()
03008       if (LANGUAGE MATCHES "PYTHON")
03009         basis_compile_python_modules_for_jython (RV)
03010         if (RV)
03011           basis_get_compiled_jython_file_of_python_module (JYTHON_OUTPUT_CFILE "${OUTPUT_FILE}")
03012           basis_get_compiled_file (JYTHON_INSTALL_CFILE "${INSTALL_FILE}" JYTHON)
03013           if (JYTHON_OUTPUT_CFILE)
03014             list (APPEND _OUTPUT_FILES "${JYTHON_OUTPUT_CFILE}")
03015           endif ()
03016           if (JYTHON_INSTALL_CFILE)
03017             list (APPEND _OUTPUT_FILES "${JYTHON_INSTALL_CFILE}")
03018           endif ()
03019         endif ()
03020       endif ()
03021     endif ()
03022     if (INSTALL_CFILE)
03023       list (APPEND FILES_TO_INSTALL "${INSTALL_CFILE}")
03024     elseif (INSTALL_FILE)
03025       list (APPEND FILES_TO_INSTALL "${INSTALL_FILE}")
03026     endif ()
03027     # add build command
03028     if (OUTPUT_CFILE)
03029       file (RELATIVE_PATH REL "${CMAKE_BINARY_DIR}" "${OUTPUT_CFILE}")
03030     else ()
03031       file (RELATIVE_PATH REL "${CMAKE_BINARY_DIR}" "${OUTPUT_FILE}")
03032     endif ()
03033     set (COMMENT "Building ${LANGUAGE} module ${REL}...")
03034     add_custom_command (
03035       OUTPUT          ${_OUTPUT_FILES}
03036       COMMAND         "${CMAKE_COMMAND}" -P "${BUILD_SCRIPT}"
03037       MAIN_DEPENDENCY "${SOURCE_FILE}"
03038       DEPENDS         "${BUILD_SCRIPT}" "${BASIS_MODULE_PATH}/CommonTools.cmake" # basis_configure_script() definition
03039                       "${BUILD_DIR}/cache.cmake" ${CONFIG_FILE}
03040       COMMENT         "${COMMENT}"
03041       VERBATIM
03042     )
03043     # add output files of command to list of all output files
03044     list (APPEND OUTPUT_FILES ${_OUTPUT_FILES})
03045   endforeach ()
03046   # add custom target to build modules
03047   add_custom_target (_${TARGET_UID} DEPENDS ${OUTPUT_FILES})
03048   foreach (T IN LISTS LINK_DEPENDS)
03049     if (TARGET ${T})
03050       add_dependencies (_${TARGET_UID} ${T})
03051     endif ()
03052   endforeach ()
03053   if (TARGET __${TARGET_UID}) # re-glob source files
03054     add_dependencies (_${TARGET_UID} __${TARGET_UID})
03055   endif ()
03056   add_dependencies (${TARGET_UID} _${TARGET_UID})
03057   # cleanup on "make clean" - including compiled files regardless of COMPILE flag
03058   set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${OUTPUT_FILES})
03059   foreach (OUTPUT_FILE IN LISTS OUTPUT_FILES)
03060     basis_get_compiled_file (CFILE "${OUTPUT_FILE}" ${LANGUAGE})
03061     if (CFILE)
03062       list (FIND OUTPUT_FILES "${CFILE}" IDX)
03063       if (IDX EQUAL -1)
03064         set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CFILE}")
03065       endif ()
03066     endif ()
03067   endforeach ()
03068   # export target
03069   if (EXPORT)
03070     if (TEST)
03071       basis_set_project_property (APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}")
03072     else ()
03073       basis_set_project_property (APPEND PROPERTY CUSTOM_EXPORT_TARGETS "${TARGET_UID}")
03074     endif ()
03075   endif ()
03076   # add installation rule
03077   foreach (INSTALL_FILE IN LISTS FILES_TO_INSTALL)
03078     get_filename_component (D "${INSTALL_FILE}" PATH)
03079     file (RELATIVE_PATH D "${BINARY_INSTALL_DIRECTORY}" "${D}")
03080     install (
03081       FILES       "${INSTALL_FILE}"
03082       DESTINATION "${LIBRARY_INSTALL_DIRECTORY}/${D}"
03083       COMPONENT   "${LIBRARY_COMPONENT}"
03084     )
03085     if (LANGUAGE MATCHES "PYTHON" AND INSTALL_FILE MATCHES "\\.pyc$")
03086       basis_compile_python_modules_for_jython (RV)
03087       if (RV)
03088         basis_sanitize_for_regex (LIBRE  "${INSTALL_PYTHON_LIBRARY_DIR}")
03089         basis_sanitize_for_regex (SITERE "${INSTALL_PYTHON_SITE_DIR}")
03090         if (LIBRARY_INSTALL_DIRECTORY MATCHES "^${LIBRE}/*$")
03091           set (JYTHON_INSTALL_DIRECTORY "${INSTALL_JYTHON_LIBRARY_DIR}")
03092         elseif (LIBRARY_INSTALL_DIRECTORY MATCHES "^${SITERE}/*$")
03093           set (JYTHON_INSTALL_DIRECTORY "${INSTALL_JYTHON_SITE_DIR}")
03094         else ()
03095           set (JYTHON_INSTALL_DIRECTORY "${LIBRARY_INSTALL_DIRECTORY}")
03096         endif ()
03097         string (REGEX REPLACE "c$" "" SOURCE_FILE "${INSTALL_FILE}")
03098         basis_get_compiled_file (INSTALL_JYTHON_CFILE "${SOURCE_FILE}" JYTHON)
03099         install (
03100           FILES       "${INSTALL_JYTHON_CFILE}"
03101           DESTINATION "${JYTHON_INSTALL_DIRECTORY}/${D}"
03102           COMPONENT   "${LIBRARY_COMPONENT}"
03103         )
03104       endif ()
03105     endif ()
03106   endforeach ()
03107   # done
03108   if (BASIS_VERBOSE)
03109     message (STATUS "Adding build command for target ${TARGET_UID}... - done")
03110   endif ()
03111 endfunction ()
03112 
03113 # ----------------------------------------------------------------------------
03114 # @brief Add target to build/install __init__.py files.
03115 function (basis_add_init_py_target)
03116   # constants
03117   set (BUILD_DIR "${PROJECT_BINARY_DIR}/CMakeFiles/_initpy.dir")
03118   basis_sanitize_for_regex (BINARY_PYTHON_LIBRARY_DIR_RE  "${BINARY_PYTHON_LIBRARY_DIR}")
03119   basis_sanitize_for_regex (TESTING_PYTHON_LIBRARY_DIR_RE "${TESTING_PYTHON_LIBRARY_DIR}")
03120   basis_sanitize_for_regex (INSTALL_PYTHON_LIBRARY_DIR_RE "${INSTALL_PYTHON_LIBRARY_DIR}")
03121   basis_sanitize_for_regex (BINARY_JYTHON_LIBRARY_DIR_RE  "${BINARY_JYTHON_LIBRARY_DIR}")
03122   basis_sanitize_for_regex (TESTING_JYTHON_LIBRARY_DIR_RE "${TESTING_JYTHON_LIBRARY_DIR}")
03123   basis_sanitize_for_regex (INSTALL_JYTHON_LIBRARY_DIR_RE "${INSTALL_JYTHON_LIBRARY_DIR}")
03124   # collect directories requiring a __init__.py file
03125   set (DEPENDENTS)          # targets which generate Python/Jython modules and depend on _initpy
03126   set (PYTHON_DIRS)         # Python library directories requiring a __init__.py file
03127   set (JYTHON_DIRS)         # Jython library directories requiring a __init__.py file
03128   set (EXCLUDE)             # exclude these directories
03129   set (INSTALL_EXCLUDE)     # exclude these directories upon installation
03130   set (COMPONENTS)          # installation components
03131   basis_get_project_property (TARGETS PROPERTY TARGETS)
03132   foreach (TARGET_UID IN LISTS TARGETS)
03133     get_target_property (BASIS_TYPE ${TARGET_UID} BASIS_TYPE)
03134     get_target_property (LANGUAGE   ${TARGET_UID} LANGUAGE)
03135     if (BASIS_TYPE MATCHES "MODULE|LIBRARY" AND LANGUAGE MATCHES "^[JP]YTHON$")
03136       # get path of built Python modules
03137       basis_get_target_location (LOCATION         ${TARGET_UID} ABSOLUTE)
03138       basis_get_target_location (INSTALL_LOCATION ${TARGET_UID} POST_INSTALL_RELATIVE)
03139       if (BASIS_TYPE MATCHES "^SCRIPT_LIBRARY$")
03140         get_target_property (PREFIX           ${TARGET_UID} PREFIX)
03141         get_target_property (SOURCES          ${TARGET_UID} SOURCES)
03142         get_target_property (SOURCE_DIRECTORY ${TARGET_UID} SOURCE_DIRECTORY)
03143         string (REGEX REPLACE "/+$" "" PREFIX "${PREFIX}")
03144         if (PREFIX)
03145           set (LOCATION         "${LOCATION}/${PREFIX}")
03146           set (INSTALL_LOCATION "${INSTALL_LOCATION}/${PREFIX}")
03147         endif ()
03148         list (REMOVE_AT SOURCES 0) # strange, but this is a CMakeFiles/ subdirectory
03149         foreach (SOURCE IN LISTS SOURCES)
03150           file (RELATIVE_PATH SOURCE "${SOURCE_DIRECTORY}" "${SOURCE}")
03151           list (APPEND _LOCATION         "${LOCATION}/${SOURCE}")
03152           list (APPEND _INSTALL_LOCATION "${INSTALL_LOCATION}/${SOURCE}")
03153         endforeach ()
03154         set (LOCATION         "${_LOCATION}")
03155         set (INSTALL_LOCATION "${_INSTALL_LOCATION}")
03156       endif ()
03157       # get component (used by installation rule)
03158       get_target_property (COMPONENT ${TARGET_UID} "LIBRARY_COMPONENT")
03159       list (FIND COMPONENTS "${COMPONENT}" IDX)
03160       if (IDX EQUAL -1)
03161         list (APPEND COMPONENTS "${COMPONENT}")
03162         set (INSTALL_${LANGUAGE}_DIRS_${COMPONENT}) # list of directories for which to install
03163                                                     # __init__.py for this component
03164       endif ()
03165       # directories for which to build a __init__.py file
03166       foreach (L IN LISTS LOCATION)
03167         basis_get_filename_component (DIR "${L}" PATH)
03168         if (L MATCHES "/__init__.py$")
03169           list (APPEND EXCLUDE "${DIR}")
03170         else ()
03171           list (APPEND DEPENDENTS ${TARGET_UID}) # depends on _initpy
03172           if (BINARY_${LANGUAGE}_LIBRARY_DIR_RE AND DIR MATCHES "^${BINARY_${LANGUAGE}_LIBRARY_DIR_RE}/.+")
03173             while (NOT "${DIR}" MATCHES "^${BINARY_${LANGUAGE}_LIBRARY_DIR_RE}$")
03174               list (APPEND ${LANGUAGE}_DIRS "${DIR}")
03175               get_filename_component (DIR "${DIR}" PATH)
03176             endwhile ()
03177           elseif (TESTING_${LANGUAGE}_LIBRARY_DIR_RE AND DIR MATCHES "^${TESTING_${LANGUAGE}_LIBRARY_DIR_RE}/.+")
03178             while (NOT "${DIR}" MATCHES "^${TESTING_${LANGUAGE}_LIBRARY_DIR_RE}$")
03179               list (APPEND ${LANGUAGE}_DIRS "${DIR}")
03180               get_filename_component (DIR "${DIR}" PATH)
03181             endwhile ()
03182           endif ()
03183         endif ()
03184       endforeach ()
03185       # directories for which to install a __init__.py file
03186       foreach (L IN LISTS INSTALL_LOCATION)
03187         basis_get_filename_component (DIR "${L}" PATH)
03188         if (L MATCHES "/__init__.py$")
03189           list (APPEND INSTALL_EXCLUDE "${DIR}")
03190         else ()
03191           list (APPEND DEPENDENTS ${TARGET_UID}) # depends on _initpy
03192           if (INSTALL_${LANGUAGE}_LIBRARY_DIR_RE AND DIR MATCHES "^${INSTALL_${LANGUAGE}_LIBRARY_DIR_RE}/.+")
03193             while (NOT "${DIR}" MATCHES "^${INSTALL_${LANGUAGE}_LIBRARY_DIR_RE}$")
03194               list (APPEND INSTALL_${LANGUAGE}_DIRS_${COMPONENT} "${DIR}")
03195               if (BASIS_COMPILE_SCRIPTS AND LANGUAGE MATCHES "PYTHON")
03196                 basis_compile_python_modules_for_jython (RV)
03197                 if (RV)
03198                   if (INSTALL_JYTHON_LIBRARY_DIR)
03199                     file (RELATIVE_PATH REL "${CMAKE_INSTALL_PREFIX}/${INSTALL_PYTHON_LIBRARY_DIR}" "${CMAKE_INSTALL_PREFIX}/${DIR}")
03200                   else ()
03201                     set (REL)
03202                   endif ()
03203                   if (NOT REL MATCHES "^$|^\\.\\./")
03204                     list (APPEND INSTALL_JYTHON_DIRS_${COMPONENT} "${INSTALL_JYTHON_LIBRARY_DIR}/${REL}")
03205                   endif ()
03206                 endif ()
03207               endif ()
03208               get_filename_component (DIR "${DIR}" PATH)
03209             endwhile ()
03210           endif ()
03211         endif ()
03212       endforeach ()
03213     endif ()
03214   endforeach ()
03215   if (DEPENDENTS)
03216     list (REMOVE_DUPLICATES DEPENDENTS)
03217   endif ()
03218   # return if nothing to do
03219   if (NOT PYTHON_DIRS AND NOT JYTHON_DIRS)
03220     return ()
03221   endif ()
03222   if (PYTHON_DIRS)
03223     list (REMOVE_DUPLICATES PYTHON_DIRS)
03224   endif ()
03225   if (JYTHON_DIRS)
03226     list (REMOVE_DUPLICATES JYTHON_DIRS)
03227   endif ()
03228   if (EXCLUDE)
03229     list (REMOVE_DUPLICATES EXCLUDE)
03230   endif ()
03231   if (INSTALL_EXCLUDE)
03232     list (REMOVE_DUPLICATES INSTALL_EXCLUDE)
03233   endif ()
03234   # generate build script
03235   set (PYTHON_COMPILED_FILES "${CFILE}")
03236   set (JYTHON_COMPILED_FILES "${CFILE}")
03237   set (C "configure_file (\"${BASIS_PYTHON_TEMPLATES_DIR}/__init__.py.in\" \"${BUILD_DIR}/__init__.py\" @ONLY)\n")
03238   foreach (LANGUAGE IN ITEMS PYTHON JYTHON) # Python *must* come first. See JYTHON_COMPILED_FILES list.
03239     set (${LANGUAGE}_OUTPUT_FILES)
03240     set (${LANGUAGE}_INSTALL_FILE "${BUILD_DIR}/__init__.py")
03241     set (C "${C}\nset (${LANGUAGE}_EXECUTABLE \"${${LANGUAGE}_EXECUTABLE}\")\n\n")
03242     foreach (DIR IN LISTS ${LANGUAGE}_DIRS)
03243       list (FIND EXCLUDE "${DIR}" IDX)
03244       if (IDX EQUAL -1)
03245         set (C "${C}configure_file (\"${BASIS_PYTHON_TEMPLATES_DIR}/__init__.py.in\" \"${DIR}/__init__.py\" @ONLY)\n")
03246         list (APPEND ${LANGUAGE}_OUTPUT_FILES "${DIR}/__init__.py")
03247       endif ()
03248     endforeach ()
03249     if (BASIS_COMPILE_SCRIPTS AND ${LANGUAGE}_EXECUTABLE)
03250       set (C "${C}\n")
03251       string (TOLOWER "${LANGUAGE}" language)
03252       basis_get_compiled_file (CFILE "${BUILD_DIR}/${language}/__init__.py" ${LANGUAGE})
03253       set (C "${C}file (MAKE_DIRECTORY \"${BUILD_DIR}/${language}\")\n")
03254       set (C "${C}execute_process (COMMAND \"${${LANGUAGE}_EXECUTABLE}\" -c \"import py_compile; py_compile.compile('${BUILD_DIR}/__init__.py', '${CFILE}')\")\n")
03255       set (${LANGUAGE}_INSTALL_FILE "${CFILE}")
03256       set (C "${C}\n")
03257       foreach (SFILE IN LISTS ${LANGUAGE}_OUTPUT_FILES)
03258         basis_get_compiled_file (CFILE "${SFILE}" ${LANGUAGE})
03259         set (C "${C}execute_process (COMMAND \"${${LANGUAGE}_EXECUTABLE}\" -c \"import py_compile; py_compile.compile('${SFILE}', '${CFILE}')\")\n")
03260         list (APPEND ${LANGUAGE}_COMPILED_FILES "${CFILE}")
03261         if (LANGUAGE MATCHES "PYTHON")
03262           basis_compile_python_modules_for_jython (RV)
03263           if (RV)
03264             if (BINARY_PYTHON_LIBRARY_DIR AND BINARY_JYTHON_LIBRARY_DIR)
03265               file (RELATIVE_PATH REL "${BINARY_PYTHON_LIBRARY_DIR}" "${SFILE}")
03266             else ()
03267               set (REL)
03268             endif ()
03269             if (NOT REL MATCHES "^$|^\\.\\./")
03270               basis_get_compiled_file (CFILE "${BINARY_JYTHON_LIBRARY_DIR}/${REL}" JYTHON)
03271             else ()
03272               basis_get_compiled_file (CFILE "${SFILE}" JYTHON)
03273             endif ()
03274             get_filename_component (CDIR "${CFILE}" PATH)
03275             set (C "${C}file (MAKE_DIRECTORY \"${CDIR}\")\n")
03276             set (C "${C}execute_process (COMMAND \"${JYTHON_EXECUTABLE}\" -c \"import py_compile; py_compile.compile('${SFILE}', '${CFILE}')\")\n")
03277             list (APPEND JYTHON_COMPILED_FILES "${CFILE}")
03278           endif ()
03279         endif ()
03280       endforeach ()
03281       list (APPEND ${LANGUAGE}_OUTPUT_FILES ${${LANGUAGE}_COMPILED_FILES})
03282     endif ()
03283   endforeach ()
03284   # write/update build script
03285   set (BUILD_SCRIPT "${BUILD_DIR}/build.cmake")
03286   if (EXISTS "${BUILD_SCRIPT}")
03287     file (WRITE "${BUILD_SCRIPT}.tmp" "${C}")
03288     execute_process (
03289       COMMAND "${CMAKE_COMMAND}" -E copy_if_different
03290           "${BUILD_SCRIPT}.tmp" "${BUILD_SCRIPT}"
03291     )
03292     file (REMOVE "${BUILD_SCRIPT}.tmp")
03293   else ()
03294     file (WRITE "${BUILD_SCRIPT}" "${C}")
03295   endif ()
03296   # add custom build command
03297   add_custom_command (
03298     OUTPUT          "${BUILD_DIR}/__init__.py" ${PYTHON_OUTPUT_FILES} ${JYTHON_OUTPUT_FILES}
03299     COMMAND         "${CMAKE_COMMAND}" -P "${BUILD_SCRIPT}"
03300     MAIN_DEPENDENCY "${BASIS_PYTHON_TEMPLATES_DIR}/__init__.py.in"
03301     COMMENT         "Building PYTHON modules */__init__.py..."
03302   )
03303   # add custom target which triggers execution of build script
03304   add_custom_target (_initpy ALL DEPENDS "${BUILD_DIR}/__init__.py" ${PYTHON_OUTPUT_FILES} ${JYTHON_OUTPUT_FILES})
03305   if (BASIS_DEBUG)
03306     message ("** basis_add_init_py_target():")
03307   endif ()
03308   foreach (DEPENDENT IN LISTS DEPENDENTS)
03309     if (BASIS_DEBUG)
03310       message ("**    Adding dependency on _initpy target to ${DEPENDENT}")
03311     endif ()
03312     add_dependencies (${DEPENDENT} _initpy)
03313   endforeach ()
03314   # cleanup on "make clean" - including compiled modules regardless of COMPILE flag
03315   set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${BUILD_DIR}/__init__.py" ${PYTHON_OUTPUT_FILES} ${JYTHON_OUTPUT_FILES})
03316   # add install rules
03317   foreach (LANGUAGE IN ITEMS PYTHON JYTHON)
03318     foreach (COMPONENT IN LISTS COMPONENTS)
03319       if (INSTALL_${LANGUAGE}_DIRS_${COMPONENT})
03320         list (REMOVE_DUPLICATES INSTALL_${LANGUAGE}_DIRS_${COMPONENT})
03321       endif ()
03322       foreach (DIR IN LISTS INSTALL_${LANGUAGE}_DIRS_${COMPONENT})
03323         list (FIND INSTALL_EXCLUDE "${DIR}" IDX)
03324         if (IDX EQUAL -1)
03325           install (
03326             FILES       "${${LANGUAGE}_INSTALL_FILE}"
03327             DESTINATION "${DIR}"
03328             COMPONENT   "${COMPONENT}"
03329           )
03330         endif ()
03331       endforeach ()
03332     endforeach ()
03333   endforeach ()
03334 endfunction ()
03335 
03336 
03337 ## @}
03338 # end of Doxygen group