00001 ##############################################################################
00002 # @file TargetTools.cmake
00003 # @brief Functions and macros to add executable and library targets.
00004 #
00005 # Copyright (c) 2011, 2012 University of Pennsylvania. All rights reserved.<br />
00006 # See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file.
00007 #
00008 # Contact: SBIA Group <sbia-software at uphs.upenn.edu>
00009 #
00010 # @ingroup CMakeTools
00011 ##############################################################################
00012
00013 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_REGEX}")
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:
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 (NOT DIRS)
00251 message (WARNING "basis_include_directories(): No directories given to add!")
00252 endif ()
00253
00254 # append directories to "global" list of include directories
00255 basis_get_project_property (INCLUDE_DIRS PROPERTY PROJECT_INCLUDE_DIRS)
00256 if (BEFORE)
00257 list (INSERT INCLUDE_DIRS 0 ${DIRS})
00258 else ()
00259 list (APPEND INCLUDE_DIRS ${DIRS})
00260 endif ()
00261 if (INCLUDE_DIRS)
00262 list (REMOVE_DUPLICATES INCLUDE_DIRS)
00263 endif ()
00264 if (BASIS_DEBUG)
00265 message ("** basis_include_directories():")
00266 if (BEFORE)
00267 message ("** Add before: ${DIRS}")
00268 else ()
00269 message ("** Add after: ${DIRS}")
00270 endif ()
00271 if (BASIS_VERBOSE)
00272 message ("** Directories: ${INCLUDE_DIRS}")
00273 endif ()
00274 endif ()
00275 basis_set_project_property (PROPERTY PROJECT_INCLUDE_DIRS ${INCLUDE_DIRS})
00276 endfunction ()
00277
00278 # ----------------------------------------------------------------------------
00279 ## @brief Add directories to search path for libraries.
00280 #
00281 # Overwrites CMake's
00282 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:link_directories">
00283 # link_directories()</a> command. This is required because the
00284 # basis_link_directories() function is not used by other projects in their
00285 # package use files. Therefore, this macro is an alias for
00286 # basis_link_directories().
00287 #
00288 # @param [in] ARGN List of arguments for basis_link_directories().
00289 #
00290 # @returns Adds the given paths to the search path for libraries.
00291 #
00292 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:link_directories
00293 macro (link_directories)
00294 basis_link_directories (${ARGN})
00295 endmacro ()
00296
00297 # ----------------------------------------------------------------------------
00298 ## @brief Add directories to search path for libraries.
00299 #
00300 # This function replaces CMake's
00301 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:link_directories">
00302 # link_directories()</a> command. Even though this function yet only invokes
00303 # CMake's internal command, it should be used in BASIS projects to enable the
00304 # extension of this command's functionality as part of BASIS if required.
00305 #
00306 # @param [in] ARGN List of arguments for
00307 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:link_directories">
00308 # link_directories()</a>.
00309 #
00310 # @returns Adds the given paths to the search path for libraries.
00311 #
00312 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:link_directories
00313 #
00314 # @ingroup CMakeAPI
00315 function (basis_link_directories)
00316 # CMake's link_directories() command
00317 _link_directories (${ARGN})
00318 endfunction ()
00319
00320 # ============================================================================
00321 # dependencies
00322 # ============================================================================
00323
00324 # ----------------------------------------------------------------------------
00325 ## @brief Add dependencies to build target.
00326 #
00327 # This function replaces CMake's
00328 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_dependencies">
00329 # add_dependencies()</a> command and extends its functionality.
00330 # In particular, it maps the given target names to the corresponding target UIDs.
00331 #
00332 # @param [in] ARGN Arguments for
00333 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_dependencies">
00334 # add_dependencies()</a>.
00335 #
00336 # @returns Adds the given dependencies of the specified build target.
00337 #
00338 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_dependencies
00339 #
00340 # @ingroup CMakeAPI
00341 function (basis_add_dependencies)
00342 set (ARGS)
00343 foreach (ARG ${ARGN})
00344 basis_get_target_uid (UID "${ARG}")
00345 if (TARGET "${UID}")
00346 list (APPEND ARGS "${UID}")
00347 else ()
00348 list (APPEND ARGS "${ARG}")
00349 endif ()
00350 endforeach ()
00351 add_dependencies (${ARGS})
00352 endfunction ()
00353
00354 # ----------------------------------------------------------------------------
00355 ## @brief Add link dependencies to build target.
00356 #
00357 # This function replaces CMake's
00358 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:target_link_libraries">
00359 # target_link_libraries()</a> command.
00360 #
00361 # The main reason for replacing this function is to treat libraries such as
00362 # MEX-files which are supposed to be compiled into a MATLAB executable added
00363 # by basis_add_executable() special. In this case, these libraries are added
00364 # to the LINK_DEPENDS property of the given MATLAB Compiler target.
00365 #
00366 # Another reason is the mapping of build target names to fully-qualified
00367 # build target names as used by BASIS (see basis_get_target_uid()).
00368 #
00369 # Example:
00370 # @code
00371 # basis_add_library (MyMEXFunc MEX myfunc.c)
00372 # basis_add_executable (MyMATLABApp main.m)
00373 # basis_target_link_libraries (MyMATLABApp MyMEXFunc OtherMEXFunc.mexa64)
00374 # @endcode
00375 #
00376 # @param [in] TARGET_NAME Name of the target.
00377 # @param [in] ARGN Link libraries.
00378 #
00379 # @returns Adds link dependencies to the specified build target.
00380 # For custom targets, the given libraries are added to the
00381 # @c DEPENDS property of these target, in particular.
00382 #
00383 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:target_link_libraries
00384 #
00385 # @ingroup CMakeAPI
00386 function (basis_target_link_libraries TARGET_NAME)
00387 basis_get_target_uid (TARGET_UID "${TARGET_NAME}")
00388
00389 if (NOT TARGET "${TARGET_UID}")
00390 message (FATAL_ERROR "basis_target_link_libraries(): Unknown target ${TARGET_UID}.")
00391 endif ()
00392
00393 # get type of named target
00394 get_target_property (BASIS_TYPE ${TARGET_UID} "BASIS_TYPE")
00395
00396 # substitute non-fully qualified target names
00397 set (ARGS)
00398 foreach (ARG ${ARGN})
00399 basis_get_target_uid (UID "${ARG}")
00400 if (TARGET "${UID}")
00401 list (APPEND ARGS "${UID}")
00402 else ()
00403 list (APPEND ARGS "${ARG}")
00404 endif ()
00405 endforeach ()
00406
00407 # MATLAB Compiler or MEX target
00408 if (BASIS_TYPE MATCHES "MCC|MEX")
00409 get_target_property (DEPENDS ${TARGET_UID} "LINK_DEPENDS")
00410
00411 if (NOT DEPENDS)
00412 set (DEPENDS)
00413 endif ()
00414 list (APPEND DEPENDS ${ARGS})
00415
00416 # pull implicit dependencies (e.g., ITK uses this)
00417 # note that MCC does itself a dependency check
00418 if (NOT BASIS_TYPE MATCHES "MCC")
00419 set (DEPENDENCY_ADDED 1)
00420 while (DEPENDENCY_ADDED)
00421 set (DEPENDENCY_ADDED 0)
00422 foreach (LIB ${DEPENDS})
00423 foreach (LIB_DEPEND ${${LIB}_LIB_DEPENDS})
00424 if (NOT LIB_DEPEND MATCHES "^general$")
00425 string (REGEX REPLACE "^-l" "" LIB_DEPEND "${LIB_DEPEND}")
00426 list (FIND DEPENDS ${LIB_DEPEND} IDX)
00427 if (IDX EQUAL -1)
00428 list (APPEND DEPENDS ${LIB_DEPEND})
00429 set (DEPENDENCY_ADDED 1)
00430 endif ()
00431 endif ()
00432 endforeach ()
00433 endforeach ()
00434 endwhile ()
00435 endif ()
00436
00437 _set_target_properties (${TARGET_UID} PROPERTIES LINK_DEPENDS "${DEPENDS}")
00438 # other
00439 else ()
00440 target_link_libraries (${TARGET_UID} ${ARGS})
00441 endif ()
00442 endfunction ()
00443
00444 # ============================================================================
00445 # add targets
00446 # ============================================================================
00447
00448 # ----------------------------------------------------------------------------
00449 ## @brief Add executable target.
00450 #
00451 # This is the main function to add an executable target to the build system,
00452 # where an executable can be a binary file or a script written in a scripting
00453 # language. In general we refer to any output file which is part of the software
00454 # (i.e., excluding configuration files) and which can be executed
00455 # (e.g., a binary file in the ELF format) or interpreted (e.g., a BASH script)
00456 # directly, as executable file. Natively, CMake supports only executables build
00457 # from C/C++ source code files. This function extends CMake's capabilities
00458 # by adding custom build commands for non-natively supported programming
00459 # languages and further standardizes the build of executable targets.
00460 # For example, by default, it is not necessary to specify installation rules
00461 # separately as these are added by this function already (see below).
00462 #
00463 # @par Programming languages
00464 # Besides adding usual executable targets build by the set <tt>C/CXX</tt>
00465 # language compiler, this function inspects the list of source files given and
00466 # detects whether this list contains sources which need to be build using a
00467 # different compiler. In particular, it supports the following languages:
00468 # @n
00469 # <table border="0">
00470 # <tr>
00471 # @tp @b CXX @endtp
00472 # <td>The default behavior, adding an executable target build from C/C++
00473 # source code. The target is added via CMake's add_executable() command.</td>
00474 # </tr>
00475 # <tr>
00476 # @tp <b>PYTHON</b>|<b>PERL</b>|<b>BASH</b> @endtp
00477 # <td>Executables written in one of the named scripting languages are built by
00478 # configuring and/or copying the script files to the build tree and
00479 # installation tree, respectively. During the build step, certain strings
00480 # of the form \@VARIABLE\@ are substituted by the values set during the
00481 # configure step. How these CMake variables are set is specified by a
00482 # so-called script configuration file, which itself is a CMake script.</td>
00483 # </tr>
00484 # <tr>
00485 # @tp @b MATLAB @endtp
00486 # <td>Standalone application build from MATLAB sources using the
00487 # MATLAB Compiler (mcc). This language option is used when the list
00488 # of source files contains one or more *.m files. A custom target is
00489 # added which depends on custom command(s) that build the executable.</td>
00490 # @n@n
00491 # Attention: The *.m file with the entry point/main function of the
00492 # executable has to be given before any other *.m file.
00493 # </tr>
00494 # </table>
00495 #
00496 # @par Helper functions
00497 # If the programming language of the input source files is not specified
00498 # explicitly by providing the @p LANGUAGE argument, the extensions of the
00499 # source files are inspected using basis_get_source_language(). Once the
00500 # programming language is known, this function invokes the proper subcommand.
00501 # In particular, it calls basis_add_executable_target() for C++ sources (.cxx),
00502 # basis_add_mcc_target() for MATLAB scripts (.m), and basis_add_script() for all
00503 # other source files.
00504 #
00505 # @note DO NOT use the mentioned subcommands directly. Always use
00506 # basis_add_library() to add a library target to your project. Only refer
00507 # to the documentation of the subcommands to learn about the available
00508 # options of the particular subcommand.
00509 #
00510 # @par Output directories
00511 # The built executable file is output to the @c BINARY_RUNTIME_DIR or
00512 # @c BINARY_LIBEXEC_DIR if the @p LIBEXEC option is given.
00513 # If this function is used within the @c PROJECT_TESTING_DIR, however,
00514 # the built executable is output to the @c TESTING_RUNTIME_DIR or
00515 # @c TESTING_LIBEXEC_DIR instead.
00516 #
00517 # @par Installation
00518 # An install command for the added executable target is added by this function
00519 # as well. The executable will be installed as part of the component @p COMPONENT
00520 # in the directory @c INSTALL_RUNTIME_DIR or @c INSTALL_LIBEXEC_DIR if the option
00521 # @p LIBEXEC is given. Executable targets are exported such that they can be
00522 # imported by other CMake-aware projects by including the CMake configuration file
00523 # of this package (<Package>Config.cmake file). No installation rules are
00524 # added, however, if this function is used within the @c PROJECT_TESTING_DIR.
00525 # Test executables are further only exported as part of the build tree.
00526 #
00527 # @note If this function is used within the @c PROJECT_TESTING_DIR, the built
00528 # executable is output to the @c TESTING_RUNTIME_DIR or
00529 # @c TESTING_LIBEXEC_DIR instead. Moreover, no installation rules are added.
00530 # Test executables are further only exported as part of the build tree.
00531 #
00532 # @param [in] TARGET_NAME Name of the target. If a source file is given
00533 # as first argument, the build target name is derived
00534 # from the name of this source file.
00535 # @param [in] ARGN This argument list is parsed and the following
00536 # arguments are extracted, all other arguments are passed
00537 # on to add_executable() or the respective custom
00538 # commands used to build the executable.
00539 # @par
00540 # <table border="0">
00541 # <tr>
00542 # @tp @b COMPONENT name @endtp
00543 # <td>Name of the component. Default: @c BASIS_RUNTIME_COMPONENT.</td>
00544 # </tr>
00545 # <tr>
00546 # @tp @b DESTINATION dir @endtp
00547 # <td>Installation directory relative to @c INSTALL_PREFIX.
00548 # If "none" (the case is ignored) is given as argument,
00549 # no installation rules are added for this executable target.
00550 # Default: @c INSTALL_RUNTIME_DIR or @c INSTALL_LIBEXEC_DIR
00551 # (if @p LIBEXEC is given).</td>
00552 # </tr>
00553 # <tr>
00554 # @tp @b LANGUAGE lang @endtp
00555 # <td>Source code language. By default determined from the extensions of
00556 # the given source files.</td>
00557 # </tr>
00558 # <tr>
00559 # @tp @b LIBEXEC @endtp
00560 # <td>Specifies that the built executable is an auxiliary executable
00561 # which is only called by other executables.</td>
00562 # </tr>
00563 # <tr>
00564 # @tp @b NO_BASIS_UTILITIES @endtp
00565 # <td>Do not add the BASIS C++ utilities as link dependency.</td>
00566 # </tr>
00567 # <tr>
00568 # @tp @b NO_EXPORT @endtp
00569 # <td>Do not export the target.</td>
00570 # </tr>
00571 # <tr>
00572 # @tp @b WITH_PATH , @b WITH_EXT @endtp
00573 # <td>See documentation of basis_add_script().</td>
00574 # </tr>
00575 # <tr>
00576 # @tp @b CONFIG , @b CONFIG_FILE @endtp
00577 # <td>See documentation of basis_add_script().</td>
00578 # </tr>
00579 # </table>
00580 #
00581 # @returns Adds an executable build target. In case of an executable which is
00582 # not build from C++ source files, the function basis_add_custom_finalize()
00583 # has to be invoked to finalize the addition of the custom build target.
00584 # This is done automatically by the basis_project_impl() macro.
00585 #
00586 # @sa basis_add_executable_target()
00587 # @sa basis_add_script()
00588 # @sa basis_add_mcc_target()
00589 #
00590 # @ingroup CMakeAPI
00591 function (basis_add_executable TARGET_NAME)
00592 # --------------------------------------------------------------------------
00593 # determine language
00594 CMAKE_PARSE_ARGUMENTS (
00595 ARGN
00596 "TEST" # discard deprecated TEST option
00597 "LANGUAGE"
00598 ""
00599 ${ARGN}
00600 )
00601
00602 if (NOT ARGN_LANGUAGE)
00603
00604 CMAKE_PARSE_ARGUMENTS (
00605 TMP
00606 "LIBEXEC;MODULE;WITH_PATH;WITH_EXT;NO_BASIS_UTILITIES;NO_EXPORT"
00607 "BINARY_DIRECTORY;DESTINATION;COMPONENT;CONFIG;CONFIG_FILE"
00608 ""
00609 ${ARGN_UNPARSED_ARGUMENTS}
00610 )
00611
00612 if (NOT TMP_UNPARSED_ARGUMENTS)
00613 set (TMP_UNPARSED_ARGUMENTS "${TARGET_NAME}")
00614 endif ()
00615
00616 basis_get_source_language (ARGN_LANGUAGE "${TMP_UNPARSED_ARGUMENTS}")
00617 if (ARGN_LANGUAGE MATCHES "AMBIGUOUS|UNKNOWN")
00618 message ("basis_add_executable(${TARGET_NAME}): Given source code files: ${TMP_UNPARSED_ARGUMENTS}")
00619 if (ARGN_LANGUAGE MATCHES "AMBIGUOUS")
00620 message (FATAL_ERROR "basis_add_executable(${TARGET_NAME}): Ambiguous source code files! Try to set LANGUAGE manually and make sure that no unknown option was given.")
00621 elseif (ARGN_LANGUAGE MATCHES "UNKNOWN")
00622 message (FATAL_ERROR "basis_add_executable(${TARGET_NAME}): Unknown source code language! Try to set LANGUAGE manually and make sure that no unknown option was given.")
00623 endif ()
00624 endif ()
00625 endif ()
00626 string (TOUPPER "${ARGN_LANGUAGE}" ARGN_LANGUAGE)
00627
00628 # --------------------------------------------------------------------------
00629 # C++
00630 if (ARGN_LANGUAGE MATCHES "CXX")
00631
00632 basis_add_executable_target (${TARGET_NAME} ${ARGN_UNPARSED_ARGUMENTS})
00633
00634 # --------------------------------------------------------------------------
00635 # MATLAB
00636 elseif (ARGN_LANGUAGE MATCHES "MATLAB")
00637
00638 basis_add_mcc_target (${TARGET_NAME} ${ARGN_UNPARSED_ARGUMENTS} TYPE EXECUTABLE)
00639
00640 # --------------------------------------------------------------------------
00641 # scripting language
00642 else ()
00643 CMAKE_PARSE_ARGUMENTS (ARGN "MODULE" "" "" ${ARGN_UNPARSED_ARGUMENTS})
00644 if (ARGN_MODULE)
00645 message (FATAL_ERROR "basis_add_executable(${TARGET_UID}): A MODULE cannot be an executable! Use basis_add_library() instead.")
00646 endif ()
00647 basis_add_script (${TARGET_NAME} ${ARGN_UNPARSED_ARGUMENTS})
00648 endif ()
00649 endfunction ()
00650
00651 # ----------------------------------------------------------------------------
00652 ## @brief Add library target.
00653 #
00654 # This is the main function to add a library target to the build system, where
00655 # a library can be a binary archive, shared library, a MEX-file or a module
00656 # written in a scripting language. In general we refer to any output file which
00657 # is part of the software (i.e., excluding configuration files), but cannot be
00658 # executed (e.g., a binary file in the ELF format) or interpreted
00659 # (e.g., a BASH script) directly, as library file. Natively, CMake supports only
00660 # libraries build from C/C++ source code files. This function extends CMake's
00661 # capabilities by adding custom build commands for non-natively supported
00662 # programming languages and further standardizes the build of library targets.
00663 # For example, by default, it is not necessary to specify installation rules
00664 # separately as these are added by this function already (see below).
00665 #
00666 # @par Programming languages
00667 # Besides adding usual library targets built from C/C++ source code files,
00668 # this function can also add custom build targets for libraries implemented
00669 # in other programming languages. It therefore tries to detect the programming
00670 # language of the given source code files and delegates the addition of the
00671 # build target to the proper helper functions. It in particular supports the
00672 # following languages:
00673 # @n
00674 # <table border="0">
00675 # <tr>
00676 # @tp @b CXX @endtp
00677 # <td>Source files written in C/C++ are by default built into either
00678 # @p STATIC, @p SHARED, or @p MODULE libraries. If the @p MEX option
00679 # is given, however, a MEX-file (a shared library) is build using
00680 # the MEX script instead of using the default C++ compiler directly.</td>
00681 # </tr>
00682 # <tr>
00683 # @tp <b>PYTHON</b>|<b>PERL</b>|<b>BASH</b> @endtp
00684 # <td>Modules written in one of the named scripting languages are built similar
00685 # to executable scripts except that the file name extension is preserved
00686 # and no executable file permission is set on Unix. These modules are
00687 # intended for import/inclusion in other modules or executables written
00688 # in the particular scripting language only.</td>
00689 # </tr>
00690 # <tr>
00691 # @tp @b MATLAB @endtp
00692 # <td>Shared libraries built from MATLAB sources using the MATLAB Compiler (mcc).
00693 # This language option is used when the list of source files contains one or
00694 # more *.m files. A custom target is added which depends on custom command(s)
00695 # that build the library.</td>
00696 # </tr>
00697 # </table>
00698 #
00699 # @par Helper functions
00700 # If the programming language of the input source files is not specified
00701 # explicitly by providing the @p LANGUAGE argument, the extensions of the
00702 # source files are inspected using basis_get_source_language(). Once the
00703 # programming language is known, this function invokes the proper subcommand.
00704 # In particular, it calls basis_add_library_target() for C++ sources (.cxx)
00705 # if the target is not a MEX-file target, basis_add_mex_target() for C++ sources
00706 # if the @p MEX option is given, basis_add_mcc_target() for MATLAB scripts (.m),
00707 # and basis_add_script() for all other source files.
00708 #
00709 # @note DO NOT use the mentioned subcommands directly. Always use
00710 # basis_add_library() to add a library target to your project. Only refer
00711 # to the documentation of the subcommands to learn about the available
00712 # options of the particular subcommand.
00713 #
00714 # @par Output directories
00715 # The built libraries are output to the @c BINARY_RUNTIME_DIR, @c BINARY_LIBRARY_DIR,
00716 # and/or @c BINARY_ARCHIVE_DIR. Python modules are output to subdirectories in
00717 # the @c BINARY_PYTHON_LIBRARY_DIR. Perl modules are output to subdirectories in
00718 # the @c BINARY_PERL_LIBRARY_DIR. If this command is used within the
00719 # @c PROJECT_TESTING_DIR, however, the files are output to the
00720 # @c TESTING_RUNTIME_DIR, @c TESTING_LIBRARY_DIR, @c TESTING_ARCHIVE_DIR,
00721 # @c TESTING_PYTHON_LIBRARY_DIR, or @c TESTING_PERL_LIBRARY_DIR instead.
00722 #
00723 # @par Installation
00724 # An install command for the added library target is added by this function
00725 # as well. Runtime libraries are installed as part of the @p RUNTIME_COMPONENT
00726 # to the @p RUNTIME_DESTINATION. Library components are installed as part of
00727 # the @p LIBRARY_COMPONENT to the @p LIBRARY_DESTINATION. Library targets are
00728 # exported such that they can be imported by other CMake-aware projects by
00729 # including the CMake configuration file of this package
00730 # (<Package>Config.cmake file). If this function is used within the
00731 # @c PROJECT_TESTING_DIR, however, no installation rules are added.
00732 # Test library targets are further only exported as part of the build tree.
00733 #
00734 # @par Example
00735 # @code
00736 # basis_add_library (MyLib1 STATIC mylib.cxx)
00737 # basis_add_library (MyLib2 STATIC mylib.cxx COMPONENT dev)
00738 #
00739 # basis_add_library (
00740 # MyLib3 SHARED mylib.cxx
00741 # RUNTIME_COMPONENT bin
00742 # LIBRARY_COMPONENT dev
00743 # )
00744 #
00745 # basis_add_library (MyMex MEX mymex.cxx)
00746 # basis_add_library (PythonModule MyModule.py.in)
00747 # basis_add_library (ShellModule MODULE MyModule.sh.in)
00748 # @endcode
00749 #
00750 # @param [in] TARGET_NAME Name of the target. If a source file is given
00751 # as first argument, the build target name is derived
00752 # from the name of this source file.
00753 # @param [in] ARGN This argument list is parsed and the following
00754 # arguments are extracted:
00755 # @par
00756 # <table border="0">
00757 # <tr>
00758 # @tp @b LANGUAGE lang @endtp
00759 # <td>Source code language. By default determined from the extensions of
00760 # the given source code files.</td>
00761 # </tr>
00762 # <tr>
00763 # @tp <b>STATIC</b>|<b>SHARED</b>|<b>MODULE</b>|<b>MEX</b> @endtp
00764 # <td>Type of the library.</td>
00765 # </tr>
00766 # <tr>
00767 # @tp @b COMPONENT name @endtp
00768 # <td>Name of the component. Default: @c BASIS_LIBRARY_COMPONENT.</td>
00769 # </tr>
00770 # <tr>
00771 # @tp @b RUNTIME_COMPONENT name @endtp
00772 # <td>Name of runtime component. Default: @c COMPONENT if specified or
00773 # @c BASIS_RUNTIME_COMPONENT, otherwise.</td>
00774 # </tr>
00775 # <tr>
00776 # @tp @b LIBRARY_COMPONENT name @endtp
00777 # <td>Name of library component. Default: @c COMPONENT if specified or
00778 # @c BASIS_LIBRARY_COMPONENT, otherwise.</td>
00779 # </tr>
00780 # <tr>
00781 # @tp @b NO_EXPORT @endtp
00782 # <td>Do not export build target.</td>
00783 # </tr>
00784 # </table>
00785 #
00786 # @returns Adds a library build target. In case of a library not written in C++
00787 # or MEX-file targets, basis_add_custom_finalize() has to be invoked
00788 # to finalize the addition of the build target(s). This is done
00789 # automatically by the basis_project_impl() macro.
00790 #
00791 # @sa basis_add_library_target()
00792 # @sa basis_add_script()
00793 # @sa basis_add_mex_target()
00794 # @sa basis_add_mcc_target()
00795 #
00796 # @ingroup CMakeAPI
00797 function (basis_add_library TARGET_NAME)
00798 # --------------------------------------------------------------------------
00799 # determine language
00800 CMAKE_PARSE_ARGUMENTS (
00801 ARGN
00802 "TEST" # discard deprecated TEST option
00803 "LANGUAGE"
00804 ""
00805 ${ARGN}
00806 )
00807
00808 if (NOT ARGN_LANGUAGE)
00809
00810 CMAKE_PARSE_ARGUMENTS (
00811 TMP
00812 "STATIC;SHARED;MODULE;MEX;WITH_PATH;NO_EXPORT"
00813 "BINARY_DIRECTORY;DESTINATION;RUNTIME_DESTINATION;LIBRARY_DESTINATION;COMPONENT;RUNTIME_COMPONENT;LIBRARY_COMPONENT;CONFIG;CONFIG_SCRIPT;MFILE"
00814 ""
00815 ${ARGN_UNPARSED_ARGUMENTS}
00816 )
00817
00818 if (NOT TMP_UNPARSED_ARGUMENTS)
00819 set (TMP_UNPARSED_ARGUMENTS "${TARGET_NAME}")
00820 endif ()
00821
00822 basis_get_source_language (ARGN_LANGUAGE "${TMP_UNPARSED_ARGUMENTS}")
00823 if (ARGN_LANGUAGE MATCHES "AMBIGUOUS|UNKNOWN")
00824 message ("basis_add_library(${TARGET_NAME}): Given source code files: ${TMP_UNPARSED_ARGUMENTS}")
00825 if (ARGN_LANGUAGE MATCHES "AMBIGUOUS")
00826 message (FATAL_ERROR "basis_add_library(${TARGET_NAME}): Ambiguous source code files! Try to set LANGUAGE manually and make sure that no unknown option was given.")
00827 elseif (ARGN_LANGUAGE MATCHES "UNKNOWN")
00828 message (FATAL_ERROR "basis_add_library(${TARGET_NAME}): Unknown source code language! Try to set LANGUAGE manually and make sure that no unknown option was given.")
00829 endif ()
00830 endif ()
00831 endif ()
00832 string (TOUPPER "${ARGN_LANGUAGE}" ARGN_LANGUAGE)
00833
00834 # --------------------------------------------------------------------------
00835 # C++
00836 if (ARGN_LANGUAGE MATCHES "CXX")
00837
00838 CMAKE_PARSE_ARGUMENTS (
00839 ARGN
00840 "MEX"
00841 ""
00842 ""
00843 ${ARGN_UNPARSED_ARGUMENTS}
00844 )
00845
00846 # MEX-file
00847 if (ARGN_MEX)
00848
00849 CMAKE_PARSE_ARGUMENTS (
00850 ARGN
00851 ""
00852 "DESTINATION;RUNTIME_DESTINATION;LIBRARY_DESTINATION;COMPONENT;RUNTIME_COMPONENT;LIBRARY_COMPONENT"
00853 ""
00854 ${ARGN_UNPARSED_ARGUMENTS}
00855 )
00856
00857 set (OPTS)
00858 if (ARGN_CXX_DESTINATION)
00859 list (APPEND OPTS "DESTINATION" "${ARGN_DESTINATION}")
00860 elseif (ARGN_RUNTIME_DESTINATION)
00861 list (APPEND OPTS "DESTINATION" "${ARGN_RUNTIME_DESTINATION}")
00862 endif ()
00863 if (ARGN_COMPONENT)
00864 list (APPEND OPTS "COMPONENT" "${ARGN_COMPONENT}")
00865 elseif (ARGN_RUNTIME_COMPONENT)
00866 list (APPEND OPTS "COMPONENT" "${ARGN_RUNTIME_COMPONENT}")
00867 endif ()
00868
00869 basis_add_mex_target (${TARGET_NAME} ${ARGN_UNPARSED_ARGUMENTS} ${OPTS})
00870
00871 # library
00872 else ()
00873
00874 basis_add_library_target (${TARGET_NAME} ${ARGN_UNPARSED_ARGUMENTS})
00875
00876 endif ()
00877
00878 # --------------------------------------------------------------------------
00879 # MATLAB
00880 elseif (ARGN_LANGUAGE MATCHES "MATLAB")
00881
00882 CMAKE_PARSE_ARGUMENTS (
00883 ARGN
00884 "STATIC;SHARED;MODULE;MEX"
00885 ""
00886 ""
00887 ${ARGN_UNPARSED_ARGUMENTS}
00888 )
00889
00890 if (ARGN_STATIC OR ARGN_MODULE OR ARGN_MEX)
00891 message (FATAL_ERROR "basis_add_library(${TARGET_UID}): Invalid library type! Only shared libraries can be built by the MATLAB Compiler.")
00892 endif ()
00893
00894 basis_add_mcc_target (${TARGET_NAME} ${ARGN_UNPARSED_ARGUMENTS} TYPE LIBRARY)
00895
00896 # --------------------------------------------------------------------------
00897 # scripting language
00898 else ()
00899
00900 CMAKE_PARSE_ARGUMENTS (
00901 ARGN
00902 "STATIC;SHARED;MODULE;MEX"
00903 ""
00904 ""
00905 ${ARGN_UNPARSED_ARGUMENTS}
00906 )
00907
00908 if (ARGN_STATIC OR ARGN_SHARED OR ARGN_MEX)
00909 message (FATAL_ERROR "basis_add_library(${TARGET_UID}): Invalid library type! Only modules can be built from scripts.")
00910 endif ()
00911
00912 basis_add_script (${TARGET_NAME} ${ARGN_UNPARSED_ARGUMENTS} MODULE)
00913 endif ()
00914 endfunction ()
00915
00916 # ============================================================================
00917 # internal helpers
00918 # ============================================================================
00919
00920 # ----------------------------------------------------------------------------
00921 ## @brief Add executable target.
00922 #
00923 # This BASIS function overwrites CMake's
00924 # <a href="http:
00925 # add_executable()</a> command in order to store information of imported targets
00926 # which is in particular used to generate the source code of the ExecutableTargetInfo
00927 # modules which are part of the BASIS utilities.
00928 #
00929 # @note Use basis_add_executable() instead where possible!
00930 #
00931 # @param [in] TARGET Name of the target.
00932 # @param [in] ARGN Further arguments of CMake's add_executable().
00933 #
00934 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_executable
00935 function (add_executable TARGET)
00936 if (ARGC EQUAL 2 AND ARGV1 MATCHES "^IMPORTED$")
00937 _add_executable (${TARGET} IMPORTED)
00938 basis_add_imported_target ("${TARGET}" EXECUTABLE)
00939 else ()
00940 _add_executable (${TARGET} ${ARGN})
00941 basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET}")
00942 endif ()
00943 endfunction ()
00944
00945 # ----------------------------------------------------------------------------
00946 ## @brief Add library target.
00947 #
00948 # This BASIS function overwrites CMake's
00949 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_library">
00950 # add_library()</a> command in order to store information of imported targets.
00951 #
00952 # @note Use basis_add_library() instead where possible!
00953 #
00954 # @param [in] TARGET Name of the target.
00955 # @param [in] ARGN Further arguments of CMake's add_library().
00956 #
00957 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_library
00958 function (add_library TARGET)
00959 if (ARGC EQUAL 3 AND ARGV2 MATCHES "^IMPORTED$")
00960 _add_library (${TARGET} "${ARGV1}" IMPORTED)
00961 basis_add_imported_target ("${TARGET}" "${ARGV1}")
00962 else ()
00963 _add_library (${TARGET} ${ARGN})
00964 basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET}")
00965 endif ()
00966 endfunction ()
00967
00968 # ----------------------------------------------------------------------------
00969 ## @brief Adds an executable target built from C++ source code.
00970 #
00971 # This function adds an executable target for the build of an executable from
00972 # C++ source code files. Refer to the documentation of basis_add_executable()
00973 # for a description of general options for adding an executable target.
00974 #
00975 # By default, the BASIS C++ utilities library is added as link dependency of
00976 # the executable target. If none of the BASIS C++ utilities are used by the
00977 # executable, the option NO_BASIS_UTILITIES can be given. To enable this option
00978 # by default, set the variable @c BASIS_NO_BASIS_UTILITIES to TRUE before the
00979 # basis_add_executable() commands, i.e., best in the Settings.cmake file located
00980 # in the @c PROJECT_CONFIG_DIR. Note, however, that the utilities library is a
00981 # static library and thus the linker would simply not include any of the BASIS
00982 # utilities object code in the final binary executable file if not used.
00983 #
00984 # @note This function should not be used directly. Instead, it is called
00985 # by basis_add_executable() if the (detected) programming language
00986 # of the given source code files is @c CXX (i.e., C/C++).
00987 #
00988 # @param [in] TARGET_NAME Name of the target. If a source file is given
00989 # as first argument, the build target name is derived
00990 # from the name of this source file.
00991 # @param [in] ARGN This argument list is parsed and the following
00992 # arguments are extracted, all other arguments are
00993 # considered to be source code files and simply passed
00994 # on to CMake's add_executable() command.
00995 # @par
00996 # <table border="0">
00997 # <tr>
00998 # @tp @b DESTINATION dir @endtp
00999 # <td>Installation directory relative to @c INSTALL_PREFIX.
01000 # If "none" (the case is ignored) is given as argument,
01001 # no installation rules are added for this executable target.
01002 # Default: @c INSTALL_RUNTIME_DIR or @c INSTALL_LIBEXEC_DIR
01003 # (if @p LIBEXEC is given).</td>
01004 # </tr>
01005 # <tr>
01006 # @tp @b COMPONENT name @endtp
01007 # <td>Name of the component. Default: @c BASIS_RUNTIME_COMPONENT.</td>
01008 # </tr>
01009 # <tr>
01010 # @tp @b LIBEXEC @endtp
01011 # <td>Specifies that the built executable is an auxiliary executable
01012 # which is only called by other executable.</td>
01013 # </tr>
01014 # <tr>
01015 # @tp @b NO_BASIS_UTILITIES @endtp
01016 # <td>Do not add the BASIS C++ utilities as link dependency.</td>
01017 # </tr>
01018 # <tr>
01019 # @tp @b NO_EXPORT @endtp
01020 # <td>Do not export the target.</td>
01021 # </tr>
01022 # </table>
01023 #
01024 # @returns Adds an executable build target built from C++ sources.
01025 #
01026 # @sa basis_add_executable()
01027 # @sa basis_install()
01028 function (basis_add_executable_target TARGET_NAME)
01029 # parse arguments
01030 CMAKE_PARSE_ARGUMENTS (
01031 ARGN
01032 "LIBEXEC;TEST;BASIS_UTILITIES;NO_BASIS_UTILITIES;NO_EXPORT"
01033 "DESTINATION;COMPONENT"
01034 ""
01035 ${ARGN}
01036 )
01037
01038 basis_sanitize_for_regex (R "${PROJECT_TESTING_DIR}")
01039 if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${R}")
01040 set (ARGN_TEST TRUE)
01041 else ()
01042 if (ARGN_TEST)
01043 message (FATAL_ERROR "Executable ${TARGET_NAME} cannot have TEST property!"
01044 "If it is a test executable, put it in ${PROJECT_TESTING_DIR}.")
01045 endif ()
01046 set (ARGN_TEST FALSE)
01047 endif ()
01048
01049 set (SOURCES ${ARGN_UNPARSED_ARGUMENTS})
01050
01051 get_filename_component (S "${TARGET_NAME}" ABSOLUTE)
01052 if (NOT SOURCES OR EXISTS "${S}" OR EXISTS "${S}.in")
01053 list (APPEND SOURCES "${TARGET_NAME}")
01054 basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE)
01055 endif ()
01056
01057 # check target name
01058 basis_check_target_name (${TARGET_NAME})
01059 basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
01060
01061 # whether or not to link to BASIS utilities
01062 set (NO_BASIS_UTILITIES "${BASIS_NO_BASIS_UTILITIES}")
01063 if (ARGN_NO_BASIS_UTILITIES)
01064 set (NO_BASIS_UTILITIES TRUE)
01065 endif ()
01066 if (ARGN_BASIS_UTILITIES)
01067 set (NO_BASIS_UTILITIES FALSE)
01068 endif ()
01069
01070 # component
01071 if (NOT ARGN_COMPONENT)
01072 set (ARGN_COMPONENT "${BASIS_RUNTIME_COMPONENT}")
01073 endif ()
01074
01075 # installation directory
01076 if (NOT ARGN_DESTINATION)
01077 if (ARGN_LIBEXEC)
01078 set (ARGN_DESTINATION "${INSTALL_LIBEXEC_DIR}")
01079 else ()
01080 set (ARGN_DESTINATION "${INSTALL_RUNTIME_DIR}")
01081 endif ()
01082 endif ()
01083
01084 if (BASIS_VERBOSE)
01085 message (STATUS "Adding executable ${TARGET_UID}...")
01086 endif ()
01087
01088 # add standard auxiliary library
01089 if (NOT NO_BASIS_UTILITIES)
01090 if (NOT BASIS_UTILITIES_ENABLED MATCHES "CXX")
01091 message (FATAL_ERROR "Target ${TARGET_UID} makes use of the BASIS C++ utilities"
01092 " but BASIS was build without C++ utilities enabled."
01093 " Either specify the option NO_BASIS_UTILITIES or rebuild"
01094 " BASIS with C++ utilities enabled.")
01095 endif ()
01096 set (BASIS_UTILITIES_TARGET "basis")
01097 if (BASIS_USE_FULLY_QUALIFIED_UIDS)
01098 set (BASIS_UTILITIES_TARGET "${BASIS_PROJECT_NAMESPACE_CMAKE}.${BASIS_UTILITIES_TARGET}")
01099 endif ()
01100 if (NOT TARGET ${BASIS_UTILITIES_TARGET} AND BASIS_UTILITIES_SOURCES)
01101 add_library (${BASIS_UTILITIES_TARGET} STATIC ${BASIS_UTILITIES_SOURCES})
01102 string (REGEX REPLACE "^.*\\." "" OUTPUT_NAME "${BASIS_UTILITIES_TARGET}")
01103
01104 # define dependency on non-project specific utilities as the order in
01105 # which static libraries are listed on the command-line for the linker
01106 # matters; this will tell CMake to get the order right
01107 target_link_libraries (${BASIS_UTILITIES_TARGET} ${BASIS_UTILITIES_LIBRARY})
01108
01109 _set_target_properties (
01110 ${BASIS_UTILITIES_TARGET}
01111 PROPERTIES
01112 BASIS_TYPE "STATIC_LIBRARY"
01113 OUTPUT_NAME "${OUTPUT_NAME}"
01114 # make sure that this library is always output to the 'lib' directory
01115 # even if only test executables use it; see CMakeLists.txt in 'test'
01116 # subdirectory, which (re-)sets the CMAKE_*_OUTPUT_DIRECTORY variables.
01117 ARCHIVE_OUTPUT_DIRECTORY "${BASIS_BINARY_ARCHIVE_DIR}"
01118 )
01119
01120 install (
01121 TARGETS ${BASIS_UTILITIES_TARGET}
01122 EXPORT ${BASIS_PROJECT_NAME}
01123 ARCHIVE
01124 DESTINATION "${BASIS_INSTALL_ARCHIVE_DIR}"
01125 COMPONENT "${BASIS_LIBRARY_COMPONENT}"
01126 )
01127
01128 if (BASIS_DEBUG)
01129 message ("** Added BASIS utilities library ${BASIS_UTILITIES_TARGET}")
01130 endif ()
01131 endif ()
01132 endif ()
01133
01134 # configure .in source files
01135 basis_configure_sources (SOURCES ${SOURCES})
01136
01137 # add executable target
01138 add_executable (${TARGET_UID} ${SOURCES})
01139
01140 basis_make_target_uid (HEADERS_TARGET headers)
01141 if (TARGET "${HEADERS_TARGET}")
01142 add_dependencies (${TARGET_UID} ${HEADERS_TARGET})
01143 endif ()
01144
01145 # target properties
01146 _set_target_properties (
01147 ${TARGET_UID}
01148 PROPERTIES
01149 BASIS_TYPE "EXECUTABLE"
01150 OUTPUT_NAME "${TARGET_NAME}"
01151 )
01152
01153 if (ARGN_LIBEXEC)
01154 _set_target_properties (
01155 ${TARGET_UID}
01156 PROPERTIES
01157 LIBEXEC 1
01158 COMPILE_DEFINITIONS "LIBEXEC"
01159 )
01160 else ()
01161 _set_target_properties (${TARGET_UID} PROPERTIES LIBEXEC 0)
01162 endif ()
01163 if (ARGN_TEST)
01164 _set_target_properties (${TARGET_UID} PROPERTIES TEST 1)
01165 else ()
01166 _set_target_properties (${TARGET_UID} PROPERTIES TEST 0)
01167 endif ()
01168
01169 # output directory
01170 if (ARGN_TEST)
01171 if (ARGN_LIBEXEC)
01172 _set_target_properties (
01173 ${TARGET_UID}
01174 PROPERTIES
01175 RUNTIME_OUTPUT_DIRECTORY "${TESTING_LIBEXEC_DIR}"
01176 )
01177 else ()
01178 _set_target_properties (
01179 ${TARGET_UID}
01180 PROPERTIES
01181 RUNTIME_OUTPUT_DIRECTORY "${TESTING_RUNTIME_DIR}"
01182 )
01183 endif ()
01184 elseif (ARGN_LIBEXEC)
01185 _set_target_properties (
01186 ${TARGET_UID}
01187 PROPERTIES
01188 RUNTIME_OUTPUT_DIRECTORY "${BINARY_LIBEXEC_DIR}"
01189 )
01190 else ()
01191 _set_target_properties (
01192 ${TARGET_UID}
01193 PROPERTIES
01194 LIBEXEC 0
01195 RUNTIME_OUTPUT_DIRECTORY "${BINARY_RUNTIME_DIR}"
01196 )
01197 endif ()
01198
01199 # add default link dependencies
01200 if (NOT ARGN_NO_BASIS_UTILITIES)
01201 # non-project specific utilities build as part of BASIS
01202 basis_target_link_libraries (${TARGET_UID} ${BASIS_UTILITIES_LIBRARY})
01203 # project specific utilities build as part of this project
01204 basis_target_link_libraries (${TARGET_UID} ${BASIS_UTILITIES_TARGET})
01205 endif ()
01206
01207 # install executable and/or export target
01208 if (ARGN_TEST)
01209
01210 # TODO install (selected?) tests
01211
01212 if (NOT ARGN_NO_EXPORT)
01213 basis_set_project_property (APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}")
01214 endif ()
01215
01216 else ()
01217
01218 if (ARGN_NO_EXPORT)
01219 set (EXPORT_OPT)
01220 else ()
01221 set (EXPORT_OPT "EXPORT" "${PROJECT_NAME}")
01222 basis_set_project_property (APPEND PROPERTY EXPORT_TARGETS "${TARGET_UID}")
01223 endif ()
01224
01225 install (
01226 TARGETS ${TARGET_UID} ${EXPORT_OPT}
01227 DESTINATION "${ARGN_DESTINATION}"
01228 COMPONENT "${ARGN_COMPONENT}"
01229 )
01230
01231 _set_target_properties (
01232 ${TARGET_UID}
01233 PROPERTIES
01234 RUNTIME_INSTALL_DIRECTORY "${ARGN_DESTINATION}"
01235 )
01236 endif ()
01237
01238 if (BASIS_VERBOSE)
01239 message (STATUS "Adding executable ${TARGET_UID}... - done")
01240 endif ()
01241 endfunction ()
01242
01243 # ----------------------------------------------------------------------------
01244 ## @brief Add build target for library built from C++ source code.
01245 #
01246 # This function adds a library target which builds a library from C++ source
01247 # code files. Refer to the documentation of basis_add_library() for a
01248 # description of the general options for adding a library target.
01249 #
01250 # @note This function should not be used directly. Instead, it is called
01251 # by basis_add_library() if the (detected) programming language
01252 # of the given source code files is @c CXX (i.e., C/C++) and the
01253 # option @c MEX is not given.
01254 #
01255 # @param [in] TARGET_NAME Name of the target. If a source file is given
01256 # as first argument, the build target name is derived
01257 # from the name of this source file.
01258 # @param [in] ARGN This argument list is parsed and the following
01259 # arguments are extracted. All other arguments are
01260 # considered to be source code files and simply
01261 # passed on to CMake's add_library() command.
01262 # @par
01263 # <table border="0">
01264 # <tr>
01265 # @tp <b>STATIC</b>|<b>SHARED</b>|<b>MODULE</b> @endtp
01266 # <td>Type of the library.</td>
01267 # </tr>
01268 # <tr>
01269 # @tp @b DESTINATION dir @endtp
01270 # <td>Installation directory for runtime and library component
01271 # relative to @c INSTALL_PREFIX. See @p RUNTIME_DESTINATION
01272 # and @p LIBRARY_DESTINATION.</td>
01273 # </tr>
01274 # <tr>
01275 # @tp @b RUNTIME_DESTINATION dir @endtp
01276 # <td>Installation directory of the runtime component relative to
01277 # @c INSTALL_PREFIX. If "none" (case ignored) is given as argument,
01278 # no installation rule for the runtime library is not added.
01279 # Default: @c INSTALL_LIBRARY_DIR on Unix or @c INSTALL_RUNTIME_DIR
01280 # on Windows.</td>
01281 # </tr>
01282 # <tr>
01283 # @tp @b LIBRARY_DESTINATION dir @endtp
01284 # <td>Installation directory of the library component relative to
01285 # @c INSTALL_PREFIX. If "none" (case ignored) is given as argument,
01286 # no installation rule for the library component is added.
01287 # Default: @c INSTALL_ARCHIVE_DIR.</td>
01288 # </tr>
01289 # <tr>
01290 # @tp @b COMPONENT name @endtp
01291 # <td>Name of the component. Default: @c BASIS_LIBRARY_COMPONENT.</td>
01292 # </tr>
01293 # <tr>
01294 # @tp @b RUNTIME_COMPONENT name @endtp
01295 # <td>Name of runtime component. Default: @c COMPONENT if specified or
01296 # @c BASIS_RUNTIME_COMPONENT, otherwise.</td>
01297 # </tr>
01298 # <tr>
01299 # @tp @b LIBRARY_COMPONENT name @endtp
01300 # <td>Name of library component. Default: @c COMPONENT if specified or
01301 # @c BASIS_LIBRARY_COMPONENT, otherwise.</td>
01302 # </tr>
01303 # <tr>
01304 # @tp @b NO_EXPORT @endtp
01305 # <td>Do not export build target.</td>
01306 # </tr>
01307 # </table>
01308 #
01309 # @returns Adds a library build target.
01310 function (basis_add_library_target TARGET_NAME)
01311 # parse arguments
01312 CMAKE_PARSE_ARGUMENTS (
01313 ARGN
01314 "STATIC;SHARED;MODULE;NO_EXPORT"
01315 "DESTINATION;RUNTIME_DESTINATION;LIBRARY_DESTINATION;COMPONENT;RUNTIME_COMPONENT;LIBRARY_COMPONENT"
01316 ""
01317 ${ARGN}
01318 )
01319
01320 basis_sanitize_for_regex (R "${PROJECT_TESTING_DIR}")
01321 if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${R}")
01322 set (ARGN_TEST TRUE)
01323 else ()
01324 set (ARGN_TEST FALSE)
01325 endif ()
01326
01327 set (SOURCES ${ARGN_UNPARSED_ARGUMENTS})
01328
01329 get_filename_component (S "${TARGET_NAME}" ABSOLUTE)
01330 if (NOT SOURCES OR EXISTS "${S}")
01331 list (APPEND SOURCES "${TARGET_NAME}")
01332 basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE)
01333 endif ()
01334
01335 # check target name
01336 basis_check_target_name (${TARGET_NAME})
01337 basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
01338
01339 # library type
01340 if (NOT ARGN_SHARED AND NOT ARGN_STATIC AND NOT ARGN_MODULE)
01341 if (BUILD_SHARED_LIBS)
01342 set (ARGN_SHARED 1)
01343 else ()
01344 set (ARGN_STATIC 1)
01345 endif ()
01346 endif ()
01347
01348 # installation directories
01349 if (ARGN_DESTINATION)
01350 if (NOT ARGN_STATIC AND NOT ARGN_RUNTIME_DESTINATION)
01351 set (ARGN_RUNTIME_DESTINATION "${ARGN_DESTINATION}")
01352 endif ()
01353 if (NOT ARGN_LIBRARY_DESTINATION)
01354 set (ARGN_LIBRARY_DESTINATION "${ARGN_DESTINATION}")
01355 endif ()
01356 endif ()
01357 if (NOT ARGN_RUNTIME_DESTINATION)
01358 set (ARGN_RUNTIME_DESTINATION "${INSTALL_RUNTIME_DIR}")
01359 endif ()
01360 if (NOT ARGN_LIBRARY_DESTINATION)
01361 set (ARGN_LIBRARY_DESTINATION "${INSTALL_LIBRARY_DIR}")
01362 endif ()
01363
01364 if (ARGN_STATIC OR ARGN_RUNTIME_DESTINATION MATCHES "^none$|^None$|^NONE$")
01365 set (ARGN_RUNTIME_DESTINATION)
01366 endif ()
01367 if (ARGN_NO_EXPORT OR ARGN_LIBRARY_DESTINATION MATCHES "^none$|^None$|^NONE$")
01368 set (ARGN_LIBRARY_DESTINATION)
01369 endif ()
01370
01371 # component
01372 if (ARGN_COMPONENT)
01373 if (NOT ARGN_RUNTIME_COMPONENT)
01374 set (ARGN_RUNTIME_COMPONENT "${ARGN_COMPONENT}")
01375 endif ()
01376 if (NOT ARGN_LIBRARY_COMPONENT)
01377 set (ARGN_LIBRARY_COMPONENT "${ARGN_COMPONENT}")
01378 endif ()
01379 endif ()
01380 if (NOT ARGN_RUNTIME_COMPONENT)
01381 set (ARGN_RUNTIME_COMPONENT "${BASIS_RUNTIME_COMPONENT}")
01382 endif ()
01383 if (NOT ARGN_LIBRARY_COMPONENT)
01384 set (ARGN_LIBRARY_COMPONENT "${BASIS_LIBRARY_COMPONENT}")
01385 endif ()
01386
01387 # status message
01388 if (ARGN_STATIC)
01389 if (BASIS_VERBOSE)
01390 message (STATUS "Adding static library ${TARGET_UID}...")
01391 endif ()
01392 if (TYPE)
01393 message (FATAL_ERROR "More than one library type specified for target ${TARGET_UID}.")
01394 endif ()
01395 set (TYPE "STATIC")
01396 endif ()
01397 if (ARGN_SHARED)
01398 if (BASIS_VERBOSE)
01399 message (STATUS "Adding shared library ${TARGET_UID}...")
01400 endif ()
01401 if (TYPE)
01402 message (FATAL_ERROR "More than one library type specified for target ${TARGET_UID}.")
01403 endif ()
01404 set (TYPE "SHARED")
01405 endif ()
01406 if (ARGN_MODULE)
01407 if (BASIS_VERBOSE)
01408 message (STATUS "Adding module ${TARGET_UID}...")
01409 endif ()
01410 if (TYPE)
01411 message (FATAL_ERROR "More than one library type specified for target ${TARGET_UID}.")
01412 endif ()
01413 set (TYPE "MODULE")
01414 endif ()
01415
01416 # configure .in source files
01417 basis_configure_sources (SOURCES ${SOURCES})
01418
01419 # add library target
01420 add_library (${TARGET_UID} ${TYPE} ${SOURCES})
01421
01422 basis_make_target_uid (HEADERS_TARGET headers)
01423 if (TARGET ${HEADERS_TARGET})
01424 add_dependencies (${TARGET_UID} ${HEADERS_TARGET})
01425 endif ()
01426
01427 _set_target_properties (
01428 ${TARGET_UID}
01429 PROPERTIES
01430 BASIS_TYPE "${TYPE}_LIBRARY"
01431 OUTPUT_NAME "${TARGET_NAME}"
01432 )
01433
01434 # output directory
01435 if (ARGN_TEST)
01436 _set_target_properties (
01437 ${TARGET_UID}
01438 PROPERTIES
01439 RUNTIME_OUTPUT_DIRECTORY "${TESTING_RUNTIME_DIR}"
01440 LIBRARY_OUTPUT_DIRECTORY "${TESTING_LIBRARY_DIR}"
01441 ARCHIVE_OUTPUT_DIRECTORY "${TESTING_ARCHIVE_DIR}"
01442 )
01443 else ()
01444 _set_target_properties (
01445 ${TARGET_UID}
01446 PROPERTIES
01447 RUNTIME_OUTPUT_DIRECTORY "${BINARY_RUNTIME_DIR}"
01448 LIBRARY_OUTPUT_DIRECTORY "${BINARY_LIBRARY_DIR}"
01449 ARCHIVE_OUTPUT_DIRECTORY "${BINARY_ARCHIVE_DIR}"
01450 )
01451 endif ()
01452
01453 # target version information
01454 #
01455 # Note: On UNIX-based systems this only creates annoying files with the
01456 # version string as suffix.
01457 # Attention: MEX-files may NEVER have a suffix after the MEX extension!
01458 # Otherwise, the MATLAB Compiler when using the symbolic link
01459 # without this suffix will create code that fails on runtime
01460 # with an .auth file missing error.
01461 #
01462 # Thus, do NOT set VERSION and SOVERSION properties.
01463
01464 # install library
01465 if (ARGN_TEST)
01466 # TODO At the moment, no tests are installed. Once there is a way to
01467 # install selected tests, the shared libraries they depend on
01468 # need to be installed as well.
01469
01470 if (NOT ARGN_NO_EXPORT)
01471 basis_set_project_property (APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}")
01472 endif ()
01473 else ()
01474 if (ARGN_NO_EXPORT)
01475 set (EXPORT_OPT)
01476 else ()
01477 set (EXPORT_OPT "EXPORT" "${PROJECT_NAME}")
01478 basis_set_project_property (APPEND PROPERTY EXPORT_TARGETS "${TARGET_UID}")
01479 endif ()
01480
01481 if (ARGN_RUNTIME_DESTINATION)
01482 install (
01483 TARGETS ${TARGET_UID} ${EXPORT_OPT}
01484 RUNTIME
01485 DESTINATION "${ARGN_RUNTIME_DESTINATION}"
01486 COMPONENT "${ARGN_RUNTIME_COMPONENT}"
01487 )
01488 endif ()
01489
01490 if (ARGN_LIBRARY_DESTINATION)
01491 install (
01492 TARGETS ${TARGET_UID} ${EXPORT_OPT}
01493 LIBRARY
01494 DESTINATION "${ARGN_LIBRARY_DESTINATION}"
01495 COMPONENT "${ARGN_LIBRARY_COMPONENT}"
01496 ARCHIVE
01497 DESTINATION "${ARGN_LIBRARY_DESTINATION}"
01498 COMPONENT "${ARGN_LIBRARY_COMPONENT}"
01499 )
01500 endif ()
01501 endif ()
01502
01503 # done
01504 if (BASIS_VERBOSE)
01505 if (ARGN_STATIC)
01506 message (STATUS "Adding static library ${TARGET_UID}... - done")
01507 elseif (ARGN_SHARED)
01508 message (STATUS "Adding shared library ${TARGET_UID}... - done")
01509 elseif (ARGN_MODULE)
01510 message (STATUS "Adding module ${TARGET_UID}... - done")
01511 endif ()
01512 endif ()
01513 endfunction ()
01514
01515 # ----------------------------------------------------------------------------
01516 ## @brief Add script target.
01517 #
01518 # If the script name ends in ".in", the ".in" suffix is removed from the
01519 # output name. Further, the extension of the script such as .sh or .py is
01520 # removed from the output filename of executable scripts. On Unix, a shebang
01521 # directive is added to executable scripts at the top of the script files
01522 # instead if such directive is not given yet. In order to enable the convenient
01523 # execution of Python and Perl scripts on Windows as well, some Batch code
01524 # is added at the top and bottom of executable Python and Perl scripts which
01525 # calls the Python or Perl interpreter with the script file and the given
01526 # script arguments as command-line arguments. The file name extension of
01527 # such modified scripts is by default set to <tt>.cmd</tt>, the common
01528 # extension for Windows NT Command Scripts. Scripts in other languages are
01529 # not specifically modified. In case of script modules, the script file name
01530 # extension is preserved in any case. When the @c WITH_EXT option is given,
01531 # executable scripts are not modified as described and their file name
01532 # extension is preserved.
01533 #
01534 # Example:
01535 # @code
01536 # basis_add_script (MyShellScript.sh.in)
01537 # basis_add_script (Script Script1.sh)
01538 # @endcode
01539 #
01540 # Certain CMake variables within the script are replaced during the configure step.
01541 # See @ref ScriptTargets for details.
01542 #
01543 # Note that this function only configures the script file if it ends in the ".in"
01544 # suffix and adds a custom target which stores all information required to setup
01545 # the actual custom build command as properties. The custom build command itself
01546 # is added by basis_add_script_finalize(), which is supposed to be called once at
01547 # the end of the root CMakeLists.txt file. This way properties such as the
01548 # @c OUTPUT_NAME can still be modified after adding the script target.
01549 #
01550 # @note If this function is used within the @c PROJECT_TESTING_DIR, the built
01551 # executable is output to the @c BINARY_TESTING_DIR directory tree instead.
01552 # Moreover, no installation rules are added. Test executables are further
01553 # not exported, regardless of whether NO_EXPORT is given or not.
01554 #
01555 # @note This function should not be used directly. Instead, the functions
01556 # basis_add_executable() and basis_add_library() should be used which in
01557 # turn make use of this function if the (detected) programming language
01558 # is a (supported) scripting language.
01559 #
01560 # @param [in] TARGET_NAME Name of the target. If the target is build from a
01561 # single source file, the file path of this source file
01562 # can be given as first argument. The build target name
01563 # is then derived from the name of the source file.
01564 # @param [in] ARGN This argument list is parsed and the following
01565 # arguments are extracted:
01566 # @par
01567 # <table border="0">
01568 # <tr>
01569 # @tp @b COMPONENT name @endtp
01570 # <td>Name of the component. Default: @c BASIS_RUNTIME_COMPONENT for
01571 # executable scripts or @c BASIS_LIBRARY_COMPONENT for modules.</td>
01572 # </tr>
01573 # <tr>
01574 # @tp @b CONFIG config @endtp
01575 # <td>Additional script configuration given directly as string argument.
01576 # This string is included in the CMake build script before configuring
01577 # the script file after the script configuration files have been included.</td>
01578 # </tr>
01579 # <tr>
01580 # @tp @b CONFIG_FILE file @endtp
01581 # <td>Additional script configuration file. This file is included after
01582 # the default script configuration file of BASIS and after the default
01583 # script configuration file which is located in @c PROJECT_BINARY_DIR,
01584 # but before the script configuration code given by @p CONFIG.</td>
01585 # </tr>
01586 # <tr>
01587 # @tp @b DESTINATION dir @endtp
01588 # <td>The installation directory relative to @c INSTALL_PREFIX.
01589 # Default: @c INSTALL_RUNTIME_DIR or @c INSTALL_LIBEXEC_DIR if
01590 # the @p LIBEXEC option is given or @c INSTALL_LIBRARY_DIR
01591 # if the @p MODULE option is given.</td>
01592 # </tr>
01593 # <tr>
01594 # @tp @b LIBEXEC @endtp
01595 # <td>Specifies that the built executable is an auxiliary executable
01596 # which is only called by other executable.</td>
01597 # </tr>
01598 # <tr>
01599 # @tp @b MODULE @endtp
01600 # <td>Specifies that the script is a module file which is included by
01601 # other scripts. Implies @p LIBEXEC regarding installation directory and
01602 # preserves file name extension on all platforms. It can be used,
01603 # for example, for Python modules that are to be imported only by other
01604 # Python scripts.
01605 #
01606 # Note that this option can also be used for arbitrary text files
01607 # which are used as input to a program, not only actual modules written
01608 # in a scripting language.</td>
01609 # </tr>
01610 # <tr>
01611 # @tp @b WITH_PATH @endtp
01612 # <td>Preserve relative path of module. Required for example for
01613 # Python and Perl packages where the directory hierarchy is important.</td>
01614 # </tr>
01615 # <tr>
01616 # @tp @b WITH_EXT @endtp
01617 # <td>Specify that the existing filename extension should be kept also
01618 # in case of an executable script. No shebang directive is added to
01619 # the top of the script automatically if this option is given.
01620 # On Windows, on the other side, this prevents the addition of Batch
01621 # code to execute the script and no <tt>.cmd</tt> file name extension
01622 # is used for executable scripts build with this option.</td>
01623 # </tr>
01624 # <tr>
01625 # @tp @b NO_EXPORT @endtp
01626 # <td>Do not export build target.</td>
01627 # </tr>
01628 # <tr>
01629 # @tp @b COMPILE | @b NOCOMPILE @endtp
01630 # <td>Enable/disable compilation of script if supported by scripting
01631 # language as well as BASIS. In particular, Python modules can be
01632 # compiled. If a script could be compiled by BASIS, only the
01633 # compiled file is installed. Default: @c BASIS_COMPILE_SCRIPTS</td>
01634 # </tr>
01635 # </table>
01636 #
01637 # @returns Adds custom build target @p TARGET_NAME. In order to add the
01638 # custom target that actually builds the script file,
01639 # basis_add_script_finalize() has to be invoked.
01640 #
01641 # @sa basis_add_executable()
01642 # @sa basis_add_library()
01643 # @sa basis_add_script_finalize()
01644 # @sa basis_add_custom_finalize()
01645 function (basis_add_script TARGET_NAME)
01646 # parse arguments
01647 CMAKE_PARSE_ARGUMENTS (
01648 ARGN
01649 "LIBEXEC;TEST;MODULE;WITH_PATH;WITH_EXT;NO_EXPORT;COMPILE;NOCOMPILE"
01650 "BINARY_DIRECTORY;CONFIG;CONFIG_FILE;COMPONENT;DESTINATION"
01651 ""
01652 ${ARGN}
01653 )
01654
01655 basis_sanitize_for_regex (R "${PROJECT_TESTING_DIR}")
01656 if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${R}")
01657 set (ARGN_TEST TRUE)
01658 else ()
01659 if (ARGN_TEST)
01660 message (FATAL_ERROR "Executable ${TARGET_NAME} cannot have TEST property!"
01661 "If it is a test executable, put it in ${PROJECT_TESTING_DIR}.")
01662 endif ()
01663 set (ARGN_TEST FALSE)
01664 endif ()
01665
01666 if (ARGN_COMPILE)
01667 set (COMPILE TRUE)
01668 elseif (ARGN_NOCOMPILE)
01669 set (COMPILE FALSE)
01670 else ()
01671 set (COMPILE "${BASIS_COMPILE_SCRIPTS}")
01672 endif ()
01673
01674 if (ARGN_TEST)
01675 set (ARGN_NO_EXPORT TRUE)
01676 endif ()
01677 if (NOT ARGN_NO_EXPORT)
01678 set (ARGN_NO_EXPORT FALSE)
01679 endif ()
01680
01681 if (NOT ARGN_COMPONENT)
01682 if (ARGN_MODULE)
01683 set (ARGN_COMPONENT "${BASIS_LIBRARY_COMPONENT}")
01684 else ()
01685 set (ARGN_COMPONENT "${BASIS_RUNTIME_COMPONENT}")
01686 endif ()
01687 endif ()
01688 if (NOT ARGN_COMPONENT)
01689 set (ARGN_COMPONENT "Unspecified")
01690 endif ()
01691
01692 # get script file and script name
01693 list (LENGTH ARGN_UNPARSED_ARGUMENTS LEN)
01694 if (LEN EQUAL 0)
01695 set (ARGN_SCRIPT)
01696 elseif (LEN EQUAL 1)
01697 list (GET ARGN_UNPARSED_ARGUMENTS 0 ARGN_SCRIPT)
01698 else ()
01699 message (FATAL_ERROR "basis_add_script(${TARGET_UID}): Too many arguments! Only one script can be built by a script target.")
01700 endif ()
01701 if (NOT ARGN_SCRIPT)
01702 set (ARGN_SCRIPT "${TARGET_NAME}")
01703 set (TARGET_NAME) # set below from ARGN_SCRIPT
01704 endif ()
01705 get_filename_component (ARGN_SCRIPT "${ARGN_SCRIPT}" ABSOLUTE)
01706 if (NOT EXISTS "${ARGN_SCRIPT}")
01707 set (ARGN_SCRIPT "${ARGN_SCRIPT}.in")
01708 endif ()
01709 if (NOT EXISTS "${ARGN_SCRIPT}")
01710 string (REGEX REPLACE "\\.in$" "" ARGN_SCRIPT "${ARGN_SCRIPT}")
01711 message (FATAL_ERROR "basis_add_script(): Missing script file ${ARGN_SCRIPT}[.in]!")
01712 endif ()
01713 get_filename_component (SCRIPT_NAME "${ARGN_SCRIPT}" NAME)
01714 string (REGEX REPLACE "\\.in$" "" SCRIPT_NAME "${SCRIPT_NAME}")
01715 get_filename_component (SCRIPT_NAME_WE "${SCRIPT_NAME}" NAME_WE)
01716 get_filename_component (SCRIPT_EXT "${SCRIPT_NAME}" EXT)
01717
01718 # determine path part which is optionally prepended to the binary directory
01719 if (ARGN_WITH_PATH)
01720 get_filename_component (SCRIPT_PATH "${ARGN_SCRIPT}" PATH)
01721 if (IS_ABSOLUTE "${SCRIPT_PATH}")
01722 if (SCRIPT_PATH MATCHES "^${PROJECT_SOURCE_DIR}")
01723 basis_get_relative_path (SCRIPT_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${SCRIPT_PATH}")
01724 else ()
01725 set (SCRIPT_PATH)
01726 endif ()
01727 endif ()
01728 endif ()
01729
01730 # get script language
01731 basis_get_source_language (SCRIPT_LANGUAGE "${ARGN_SCRIPT}")
01732
01733 # set output name and target name (if not set yet)
01734 set (OUTPUT_PREFIX "")
01735 set (OUTPUT_NAME "")
01736 set (OUTPUT_SUFFIX "")
01737 if (TARGET_NAME)
01738 set (OUTPUT_NAME "${TARGET_NAME}")
01739 else ()
01740 set (OUTPUT_NAME "${SCRIPT_NAME_WE}")
01741 if (ARGN_MODULE)
01742 basis_get_source_target_name (TARGET_NAME "${SCRIPT_NAME}" NAME)
01743 else ()
01744 basis_get_source_target_name (TARGET_NAME "${SCRIPT_NAME}" NAME_WE)
01745 endif ()
01746 endif ()
01747 # use output name extension for modules,
01748 # for executables also on Windows, and if WITH_EXT option is given
01749 if (ARGN_MODULE OR ARGN_WITH_EXT)
01750 set (OUTPUT_SUFFIX "${SCRIPT_EXT}")
01751 elseif (WIN32)
01752 if (SCRIPT_LANGUAGE MATCHES "PYTHON|PERL")
01753 set (OUTPUT_SUFFIX ".cmd")
01754 else ()
01755 set (OUTPUT_SUFFIX "${SCRIPT_EXT}")
01756 endif ()
01757 endif ()
01758 # SUFFIX and PREFIX used by CMake only for libraries
01759 if (NOT ARGN_MODULE)
01760 set (OUTPUT_NAME "${OUTPUT_PREFIX}${OUTPUT_NAME}${OUTPUT_SUFFIX}")
01761 set (OUTPUT_PREFIX "")
01762 set (OUTPUT_SUFFIX "")
01763 endif ()
01764 # check target name
01765 basis_check_target_name ("${TARGET_NAME}")
01766 basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
01767
01768 if (BASIS_VERBOSE)
01769 if (ARGN_MODULE)
01770 message (STATUS "Adding module script ${TARGET_UID}...")
01771 else ()
01772 message (STATUS "Adding executable script ${TARGET_UID}...")
01773 endif ()
01774 endif ()
01775
01776 if (ARGN_MODULE AND ARGN_LIBEXEC)
01777 message (FATAL_ERROR "basis_add_script(${TARGET_UID}): Script cannot be MODULE and LIBEXEC at the same time!")
01778 endif ()
01779
01780 # directory for build system files
01781 set (BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TARGET_UID}.dir")
01782
01783 # dump CMake variables for "build" of script
01784 basis_dump_variables ("${BUILD_DIR}/variables.cmake")
01785
01786 # "parse" script to check if BASIS utilities are used and hence required
01787 file (READ "${ARGN_SCRIPT}" SCRIPT)
01788 if (SCRIPT MATCHES "@BASIS_([A-Z]+)_UTILITIES@")
01789 if (BASIS_DEBUG)
01790 message ("** Target ${TARGET_UID} uses BASIS ${CMAKE_MATCH_1} utilities.")
01791 endif ()
01792 basis_set_project_property (PROPERTY PROJECT_USES_${CMAKE_MATCH_1}_UTILITIES TRUE)
01793 endif ()
01794 set (SCRIPT)
01795
01796 # binary directory
01797 if (ARGN_BINARY_DIRECTORY)
01798 set (BINARY_DIRECTORY "${ARGN_BINARY_DIRECTORY}")
01799 else ()
01800 set (BINARY_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
01801 endif ()
01802
01803 # output directory
01804 if (ARGN_TEST)
01805 if (ARGN_MODULE)
01806 if (SCRIPT_LANGUAGE MATCHES "PYTHON")
01807 set (OUTPUT_DIRECTORY "${TESTING_PYTHON_LIBRARY_DIR}/sbia/${PROJECT_NAME_LOWER}")
01808 elseif (SCRIPT_LANGUAGE MATCHES "PERL")
01809 set (OUTPUT_DIRECTORY "${TESTING_PERL_LIBRARY_DIR}/SBIA/${PROJECT_NAME}")
01810 else ()
01811 set (OUTPUT_DIRECTORY "${TESTING_LIBRARY_DIR}")
01812 endif ()
01813 elseif (ARGN_LIBEXEC)
01814 set (OUTPUT_DIRECTORY "${TESTING_LIBEXEC_DIR}")
01815 else ()
01816 set (OUTPUT_DIRECTORY "${TESTING_RUNTIME_DIR}")
01817 endif ()
01818 elseif (ARGN_MODULE)
01819 if (SCRIPT_LANGUAGE MATCHES "PYTHON")
01820 set (OUTPUT_DIRECTORY "${BINARY_PYTHON_LIBRARY_DIR}/sbia/${PROJECT_NAME_LOWER}")
01821 elseif (SCRIPT_LANGUAGE MATCHES "PERL")
01822 set (OUTPUT_DIRECTORY "${BINARY_PERL_LIBRARY_DIR}/SBIA/${PROJECT_NAME}")
01823 else ()
01824 set (OUTPUT_DIRECTORY "${BINARY_LIBRARY_DIR}")
01825 endif ()
01826 elseif (ARGN_LIBEXEC)
01827 set (OUTPUT_DIRECTORY "${BINARY_LIBEXEC_DIR}")
01828 else ()
01829 set (OUTPUT_DIRECTORY "${BINARY_RUNTIME_DIR}")
01830 endif ()
01831 if (SCRIPT_PATH AND ARGN_WITH_PATH)
01832 set (OUTPUT_DIRECTORY "${OUTPUT_DIRECTORY}/${SCRIPT_PATH}")
01833 endif ()
01834
01835 # installation directory
01836 if (ARGN_DESTINATION)
01837 if (IS_ABSOLUTE "${ARGN_DESTINATION}")
01838 file (RELATIVE_PATH ARGN_DESTINATION "${INSTALL_PREFIX}" "${ARGN_DESTINATION}")
01839 endif ()
01840 else ()
01841 if (ARGN_TEST)
01842 set (ARGN_DESTINATION)
01843 elseif (ARGN_MODULE)
01844 if (SCRIPT_LANGUAGE MATCHES "^PYTHON$")
01845 set (ARGN_DESTINATION "${INSTALL_PYTHON_LIBRARY_DIR}/sbia/${PROJECT_NAME_LOWER}")
01846 elseif (SCRIPT_LANGUAGE MATCHES "^PERL$")
01847 set (ARGN_DESTINATION "${INSTALL_PERL_LIBRARY_DIR}/SBIA/${PROJECT_NAME}")
01848 else ()
01849 set (ARGN_DESTINATION "${INSTALL_LIBRARY_DIR}")
01850 endif ()
01851 elseif (ARGN_LIBEXEC)
01852 set (ARGN_DESTINATION "${INSTALL_LIBEXEC_DIR}")
01853 else ()
01854 set (ARGN_DESTINATION "${INSTALL_RUNTIME_DIR}")
01855 endif ()
01856 if (ARGN_DESTINATION AND SCRIPT_PATH AND ARGN_WITH_PATH)
01857 set (ARGN_DESTINATION "${ARGN_DESTINATION}/${SCRIPT_PATH}")
01858 endif ()
01859 endif ()
01860
01861 # script configuration (only if script file name ends in ".in")
01862 set (INSTALL_DIR "${ARGN_DESTINATION}")
01863
01864 if (ARGN_SCRIPT MATCHES "\\.in$")
01865 # reference to BASIS doxygen page documenting the script configuration
01866 if (PROJECT_NAME MATCHES "^BASIS$")
01867 set (BuildOfScriptTargetsPageRef "@ref BuildOfScriptTargets")
01868 else ()
01869 set (BuildOfScriptTargetsPageRef "Build of Script Targets")
01870 endif ()
01871 # Configure script configuration files using configure_file()
01872 # to have CMake create build rules to update the configured
01873 # file if the script configuration was modified.
01874 # The configured files are included by the build script that is
01875 # generated by basis_add_script_finalize().
01876 configure_file ("${BASIS_SCRIPT_CONFIG_FILE}" "${BINARY_CONFIG_DIR}/BasisScriptConfig.cmake" @ONLY)
01877 if (EXISTS "${PROJECT_CONFIG_DIR}/ScriptConfig.cmake.in")
01878 configure_file ("${PROJECT_CONFIG_DIR}/ScriptConfig.cmake.in" "${BINARY_CONFIG_DIR}/ScriptConfig.cmake" @ONLY)
01879 endif ()
01880 if (ARGN_CONFIG_FILE)
01881 if (NOT EXISTS "${ARGN_CONFIG_FILE}")
01882 message (FATAL_ERROR "Script configuration file \"${ARGN_CONFIG_FILE}\" does not exist. It is required to build the script ${TARGET_UID}.")
01883 endif ()
01884 configure_file ("${ARGN_CONFIG_FILE}" "${BUILD_DIR}/ScriptConfig.cmake" @ONLY)
01885 endif ()
01886 # configure script configuration given as string
01887 if (ARGN_CONFIG)
01888 string (CONFIGURE ARGN_CONFIG "${ARGN_CONFIG}" @ONLY)
01889 endif ()
01890 elseif (ARGN_CONFIG OR ARGN_CONFIG_FILE)
01891 message (WARNING "Provided script configuration for ${TARGET_UID} but the script file "
01892 "is missing a .in suffix. Will ignore script configuration and just "
01893 "copy the script file as is without configuring it.")
01894 set (ARGN_CONFIG)
01895 set (ARGN_CONFIG_FILE)
01896 endif ()
01897
01898 # add custom target
01899 add_custom_target (${TARGET_UID} ALL SOURCES ${ARGN_SCRIPT})
01900
01901 # set target properties required by basis_add_script_finalize ()
01902 if (ARGN_MODULE)
01903 set (TYPE "MODULE_SCRIPT")
01904 else ()
01905 set (TYPE "EXECUTABLE_SCRIPT")
01906 endif ()
01907
01908 _set_target_properties (
01909 ${TARGET_UID}
01910 PROPERTIES
01911 BASIS_TYPE "${TYPE}"
01912 BASIS_LANGUAGE "${SCRIPT_LANGUAGE}"
01913 SOURCE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
01914 BINARY_DIRECTORY "${BINARY_DIRECTORY}"
01915 RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIRECTORY}"
01916 LIBRARY_OUTPUT_DIRECTORY "${OUTPUT_DIRECTORY}"
01917 RUNTIME_INSTALL_DIRECTORY "${ARGN_DESTINATION}"
01918 LIBRARY_INSTALL_DIRECTORY "${ARGN_DESTINATION}"
01919 OUTPUT_NAME "${OUTPUT_NAME}"
01920 PREFIX "${OUTPUT_PREFIX}"
01921 SUFFIX "${OUTPUT_SUFFIX}"
01922 COMPILE_DEFINITIONS "${ARGN_CONFIG}"
01923 LINK_DEPENDS "${ARGN_CONFIG_FILE}"
01924 RUNTIME_COMPONENT "${ARGN_COMPONENT}"
01925 LIBRARY_COMPONENT "${ARGN_COMPONENT}"
01926 NO_EXPORT "${ARGN_NO_EXPORT}"
01927 COMPILE "${COMPILE}"
01928 WITH_EXT "${ARGN_WITH_EXT}"
01929 )
01930
01931 if (ARGN_TEST)
01932 _set_target_properties (${TARGET_UID} PROPERTIES TEST 1)
01933 else ()
01934 _set_target_properties (${TARGET_UID} PROPERTIES TEST 0)
01935 endif ()
01936
01937 if (ARGN_LIBEXEC)
01938 _set_target_properties (${TARGET_UID} PROPERTIES LIBEXEC 1)
01939 else ()
01940 _set_target_properties (${TARGET_UID} PROPERTIES LIBEXEC 0)
01941 endif ()
01942
01943 # add target to list of targets
01944 basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET_UID}")
01945
01946 if (BASIS_VERBOSE)
01947 if (ARGN_MODULE)
01948 message (STATUS "Adding module script ${TARGET_UID}... - done")
01949 else ()
01950 message (STATUS "Adding executable script ${TARGET_UID}... - done")
01951 endif ()
01952 endif ()
01953 endfunction ()
01954
01955 # ----------------------------------------------------------------------------
01956 ## @brief Finalize addition of script.
01957 #
01958 # This function uses the properties of the custom script target added by
01959 # basis_add_script() to create the custom build command and adds this build
01960 # command as dependency of this added target.
01961 #
01962 # @param [in] TARGET_UID "Global" target name. If this function is used
01963 # within the same project as basis_add_script(),
01964 # the "local" target name may be given alternatively.
01965 #
01966 # @returns Adds custom target(s) to actually build the script target
01967 # @p TARGET_UID added by basis_add_script().
01968 #
01969 # @sa basis_add_script()
01970 # @sa basis_add_custom_finalize()
01971 function (basis_add_script_finalize TARGET_UID)
01972 # if used within (sub-)project itself, allow user to specify "local" target name
01973 basis_get_target_uid (TARGET_UID "${TARGET_UID}")
01974
01975 # already finalized before ?
01976 if (TARGET "_${TARGET_UID}")
01977 return ()
01978 endif ()
01979
01980 # does this target exist ?
01981 if (NOT TARGET "${TARGET_UID}")
01982 message (FATAL_ERROR "Unknown target ${TARGET_UID}.")
01983 return ()
01984 endif ()
01985
01986 if (BASIS_VERBOSE)
01987 message (STATUS "Adding build command for script ${TARGET_UID}...")
01988 endif ()
01989
01990 # get target properties
01991 basis_get_target_name (TARGET_NAME ${TARGET_UID})
01992
01993 set (
01994 PROPERTIES
01995 "BASIS_TYPE"
01996 "BASIS_LANGUAGE"
01997 "SOURCE_DIRECTORY"
01998 "BINARY_DIRECTORY"
01999 "RUNTIME_OUTPUT_DIRECTORY"
02000 "RUNTIME_INSTALL_DIRECTORY"
02001 "LIBRARY_OUTPUT_DIRECTORY"
02002 "LIBRARY_INSTALL_DIRECTORY"
02003 "PREFIX"
02004 "OUTPUT_NAME"
02005 "SUFFIX"
02006 "VERSION"
02007 "SOVERSION"
02008 "SOURCES"
02009 "COMPILE_DEFINITIONS"
02010 "LINK_DEPENDS"
02011 "RUNTIME_COMPONENT"
02012 "LIBRARY_COMPONENT"
02013 "LIBEXEC"
02014 "TEST"
02015 "NO_EXPORT"
02016 "COMPILE"
02017 "WITH_EXT"
02018 )
02019
02020 foreach (PROPERTY ${PROPERTIES})
02021 get_target_property (${PROPERTY} ${TARGET_UID} ${PROPERTY})
02022 endforeach ()
02023
02024 # check target type
02025 if (NOT BASIS_TYPE MATCHES "^EXECUTABLE_SCRIPT$|^MODULE_SCRIPT$")
02026 message (FATAL_ERROR "Target ${TARGET_UID} has invalid BASIS_TYPE: ${BASIS_TYPE}")
02027 endif ()
02028
02029 if (BASIS_TYPE MATCHES "^MODULE_SCRIPT$")
02030 set (MODULE 1)
02031 else ()
02032 set (MODULE 0)
02033 endif ()
02034
02035 # build directory (note that CMake returns basename of build directory as first element of SOURCES list)
02036 list (GET SOURCES 0 BUILD_DIR)
02037 set (BUILD_DIR "${BUILD_DIR}.dir")
02038
02039 # binary directory
02040 if (NOT BINARY_DIRECTORY)
02041 message (FATAL_ERROR "basis_add_script_finalize(${TARGET_UID}): BINARY_DIRECTORY property not set!")
02042 endif ()
02043 if (NOT BINARY_DIRECTORY MATCHES "^${PROJECT_BINARY_DIR}")
02044 message (FATAL_ERROR "basis_add_script_finalize(${TARGET_UID}): BINARY_DIRECTORY must be inside of build tree!")
02045 endif ()
02046
02047 # extract script file from SOURCES
02048 list (GET SOURCES 1 SCRIPT_FILE)
02049
02050 # get script name without ".in"
02051 get_filename_component (SCRIPT_NAME "${SCRIPT_FILE}" NAME)
02052 string (REGEX REPLACE "\\.in$" "" SCRIPT_NAME "${SCRIPT_NAME}")
02053
02054 # output name
02055 if (NOT OUTPUT_NAME)
02056 set (OUTPUT_NAME "${TARGET_NAME}")
02057 endif ()
02058 if (PREFIX)
02059 set (OUTPUT_NAME "${PREFIX}${OUTPUT_NAME}")
02060 endif ()
02061 if (SUFFIX)
02062 set (OUTPUT_NAME "${OUTPUT_NAME}${SUFFIX}")
02063 endif ()
02064
02065 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02066 # create build script
02067 #
02068 # Note: If the script is configured, this is done twice, once for the build tree
02069 # and once for the installation. The build tree version of the configured
02070 # script is written to the runtime output directory in the build tree.
02071 # The version configured for the installation, is written to the binary
02072 # directory that corresponds to the source directory of the script.
02073 # If a documentation is generated automatically from the sources, the
02074 # latter, i.e., the script which will be installed is used as input file.
02075 set (BUILD_SCRIPT "${BUILD_DIR}/build.cmake")
02076 # configured script file for build tree
02077 if (MODULE)
02078 set (CONFIGURED_FILE "${LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT_NAME}")
02079 else ()
02080 set (CONFIGURED_FILE "${RUNTIME_OUTPUT_DIRECTORY}/${OUTPUT_NAME}")
02081 endif ()
02082 # final output script file for build tree
02083 set (OUTPUT_FILE "${CONFIGURED_FILE}")
02084 # configured script file for install tree
02085 set (CONFIGURED_INSTALL_FILE "${CONFIGURED_FILE}")
02086 # final output script file for install tree
02087 set (INSTALL_FILE "${CONFIGURED_INSTALL_FILE}")
02088 set (INSTALL_NAME "${OUTPUT_NAME}")
02089 # output files of build command
02090 set (OUTPUT_FILES "${OUTPUT_FILE}")
02091 # files this script and its build depends on
02092 set (DEPENDS ${LINK_DEPENDS} "${BUILD_SCRIPT}")
02093
02094 set (C "# DO NOT edit. This file was automatically generated by BASIS.\n")
02095
02096 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02097 # look for required interpreter executable
02098 if (BASIS_LANGUAGE MATCHES "PYTHON")
02099 find_package (PythonInterp QUIET)
02100 if (NOT PYTHONINTERP_FOUND)
02101 message (FATAL_ERROR "Python interpreter not found. It is required to"
02102 " execute the script file target ${TARGET_UID}.")
02103 endif ()
02104 elseif (BASIS_LANGUAGE MATCHES "PERL")
02105 find_package (Perl QUIET)
02106 if (NOT PERL_FOUND)
02107 message (FATAL_ERROR "Perl interpreter not found. It is required to"
02108 " execute the script file target ${TARGET_UID}.")
02109 endif ()
02110 elseif (BASIS_LANGUAGE MATCHES "BASH")
02111 find_package (BASH QUIET)
02112 if (NOT BASH_FOUND)
02113 message (FATAL_ERROR "BASH interpreter not found. It is required to"
02114 " execute the script file target ${TARGET_UID}.")
02115 endif ()
02116 endif ()
02117
02118 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02119 # common variables and functions used by build scripts
02120 set (C "${C}\n")
02121 set (C "${C}# set script attributes\n")
02122 set (C "${C}set (LANGUAGE \"${BASIS_LANGUAGE}\")\n")
02123 set (C "${C}set (NAME \"${OUTPUT_NAME}\")\n")
02124 set (C "${C}string (TOUPPER \"\${NAME}\" NAME_UPPER)\n")
02125 set (C "${C}string (TOLOWER \"\${NAME}\" NAME_LOWER)\n")
02126 set (C "${C}get_filename_component (NAMESPACE \"\${NAME}\" NAME_WE)\n")
02127 set (C "${C}string (REGEX REPLACE \"[^a-zA-Z0-9]\" \"_\" NAMESPACE \"\${NAMESPACE}\")\n")
02128 set (C "${C}string (TOUPPER \"\${NAMESPACE}\" NAMESPACE_UPPER)\n")
02129 set (C "${C}string (TOLOWER \"\${NAMESPACE}\" NAMESPACE_LOWER)\n")
02130 set (C "${C}\n")
02131 set (C "${C}# function used by build script to generate script for this platform\n")
02132 set (C "${C}function (basis_configure_script SCRIPT_FILE CONFIGURED_FILE MODE)\n")
02133 set (C "${C} file (READ \"\${SCRIPT_FILE}\" SCRIPT)\n")
02134 set (C "${C} if (NOT MODE MATCHES \"COPYONLY\")\n")
02135 set (C "${C} string (CONFIGURE \"\${SCRIPT}\" SCRIPT \${MODE})\n")
02136 set (C "${C} string (CONFIGURE \"\${SCRIPT}\" SCRIPT \${MODE})\n")
02137 set (C "${C} endif ()\n")
02138 if (NOT MODULE AND NOT WITH_EXT)
02139 set (C "${C} if (WIN32)\n")
02140 set (C "${C} if (LANGUAGE MATCHES \"PYTHON\")\n")
02141 set (C "${C} set (SCRIPT \"@setlocal enableextensions & ${PYTHON_EXECUTABLE} -x %~f0 %* & goto :EOF\\n\${SCRIPT}\")\n")
02142 set (C "${C} elseif (LANGUAGE MATCHES \"PERL\")\n")
02143 set (C "${C} set (SCRIPT \"@goto = \\\"START_OF_BATCH\\\" ;\\n@goto = ();\\n\\n\${SCRIPT}\")\n")
02144 set (C "${C} set (SCRIPT \"\${SCRIPT}\\n\\n__END__\\n\\n:\\\"START_OF_BATCH\\\"\\n@${PERL_EXECUTABLE} -w -S %~f0 %*\")\n")
02145 set (C "${C} endif ()\n")
02146 set (C "${C} elseif (NOT SCRIPT MATCHES \"^#!\")\n")
02147 set (C "${C} if (LANGUAGE MATCHES \"PYTHON\")\n")
02148 set (C "${C} set (SCRIPT \"#! ${PYTHON_EXECUTABLE}\\n\${SCRIPT}\")\n")
02149 set (C "${C} elseif (LANGUAGE MATCHES \"PERL\")\n")
02150 set (C "${C} set (SCRIPT \"#! ${PERL_EXECUTABLE} -w\\n\${SCRIPT}\")\n")
02151 set (C "${C} elseif (LANGUAGE MATCHES \"BASH\")\n")
02152 set (C "${C} set (SCRIPT \"#! ${BASH_EXECUTABLE}\\n\${SCRIPT}\")\n")
02153 set (C "${C} endif ()\n")
02154 set (C "${C} endif ()\n")
02155 endif ()
02156 set (C "${C} file (WRITE \"\${CONFIGURED_FILE}\" \"\${SCRIPT}\")\n")
02157 set (C "${C}endfunction ()\n")
02158
02159 if (SCRIPT_FILE MATCHES "\\.in$")
02160 # make (configured) script configuration files a dependency
02161 list (APPEND DEPENDS "${BUILD_DIR}/variables.cmake")
02162 if (EXISTS "${BINARY_CONFIG_DIR}/BasisScriptConfig.cmake")
02163 list (APPEND DEPENDS "${BINARY_CONFIG_DIR}/BasisScriptConfig.cmake")
02164 endif ()
02165 if (EXISTS "${BINARY_CONFIG_DIR}/ScriptConfig.cmake")
02166 list (APPEND DEPENDS "${BINARY_CONFIG_DIR}/ScriptConfig.cmake")
02167 endif ()
02168 if (EXISTS "${BUILD_DIR}/ScriptConfig.cmake")
02169 list (APPEND DEPENDS "${BUILD_DIR}/ScriptConfig.cmake")
02170 endif ()
02171
02172 # additional output files
02173 if (RUNTIME_INSTALL_DIRECTORY)
02174 set (CONFIGURED_INSTALL_FILE "${BINARY_DIRECTORY}/${SCRIPT_NAME}")
02175 set (INSTALL_FILE "${CONFIGURED_INSTALL_FILE}")
02176 list (APPEND OUTPUT_FILES "${CONFIGURED_INSTALL_FILE}")
02177 endif ()
02178 if (MODULE AND COMPILE AND BASIS_LANGUAGE MATCHES "PYTHON")
02179 # Python modules get optionally compiled
02180 get_filename_component (MODULE_PATH "${CONFIGURED_FILE}" PATH)
02181 get_filename_component (MODULE_NAME "${CONFIGURED_FILE}" NAME_WE)
02182 set (OUTPUT_FILE "${MODULE_PATH}/${MODULE_NAME}.pyc")
02183 list (APPEND OUTPUT_FILES "${OUTPUT_FILE}")
02184 # and the compiled module installed
02185 if (RUNTIME_INSTALL_DIRECTORY)
02186 get_filename_component (MODULE_PATH "${CONFIGURED_INSTALL_FILE}" PATH)
02187 get_filename_component (MODULE_NAME "${CONFIGURED_INSTALL_FILE}" NAME_WE)
02188 set (INSTALL_FILE "${MODULE_PATH}/${MODULE_NAME}.pyc")
02189 list (APPEND OUTPUT_FILES "${INSTALL_FILE}")
02190 endif ()
02191 endif ()
02192
02193 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02194 # common code for build of build tree and install tree version
02195
02196 # tools for use in script configuration
02197 set (C "${C}\n")
02198 set (C "${C}# definitions of utility functions\n")
02199 set (C "${C}include (\"${BASIS_MODULE_PATH}/CommonTools.cmake\")\n")
02200 set (C "${C}\n")
02201 set (C "${C}function (basis_set_script_path VAR PATH)\n")
02202 set (C "${C} if (ARGC GREATER 3)\n")
02203 set (C "${C} message (FATAL_ERROR \"Too many arguments given for function basis_set_script_path()\")\n")
02204 set (C "${C} endif ()\n")
02205 set (C "${C} if (ARGC EQUAL 3 AND BUILD_INSTALL_SCRIPT)\n")
02206 set (C "${C} set (PREFIX \"${INSTALL_PREFIX}\")\n")
02207 set (C "${C} set (PATH \"\${ARGV2}\")\n")
02208 set (C "${C} else ()\n")
02209 set (C "${C} set (PREFIX \"${PROJECT_SOURCE_DIR}\")\n")
02210 set (C "${C} endif ()\n")
02211 set (C "${C} if (NOT IS_ABSOLUTE \"\${PATH}\")\n")
02212 set (C "${C} set (PATH \"\${PREFIX}/\${PATH}\")\n")
02213 set (C "${C} endif ()\n")
02214 set (C "${C} basis_get_relative_path (PATH \"\${DIR}\" \"\${PATH}\")\n")
02215 set (C "${C} if (NOT PATH)\n")
02216 set (C "${C} set (PATH \".\")\n")
02217 set (C "${C} endif ()\n")
02218 set (C "${C} string (REGEX REPLACE \"/$\" \"\" PATH \"\${PATH}\")\n")
02219 set (C "${C} set (\${VAR} \"\${PATH}\" PARENT_SCOPE)\n")
02220 set (C "${C}endfunction ()\n")
02221
02222 # variables dumped by basis_add_script()
02223 set (C "${C}\n")
02224 set (C "${C}# dumped CMake variables\n")
02225 set (C "${C}include (\"\${CMAKE_CURRENT_LIST_DIR}/variables.cmake\")\n")
02226
02227 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02228 # build script for build tree
02229
02230 # script configuration code
02231 set (C "${C}\n")
02232 set (C "${C}# build script for use in build tree\n")
02233 set (C "${C}set (BUILD_INSTALL_SCRIPT 0)\n")
02234 if (MODULE)
02235 set (C "${C}set (DIR \"${LIBRARY_OUTPUT_DIRECTORY}\")\n")
02236 else ()
02237 set (C "${C}set (DIR \"${RUNTIME_OUTPUT_DIRECTORY}\")\n")
02238 endif ()
02239 set (C "${C}set (FILE \"\${DIR}/\${NAME}\")\n")
02240 set (C "${C}\n")
02241 set (C "${C}include (\"${BINARY_CONFIG_DIR}/BasisScriptConfig.cmake\")\n")
02242 set (C "${C}include (\"${BINARY_CONFIG_DIR}/ScriptConfig.cmake\" OPTIONAL)\n")
02243 set (C "${C}include (\"${BUILD_DIR}/ScriptConfig.cmake\" OPTIONAL)\n")
02244 set (C "${C}\n")
02245 if (COMPILE_DEFINITIONS)
02246 set (C "${C}${COMPILE_DEFINITIONS}\n")
02247 endif ()
02248 # configure script for build tree
02249 set (C "${C}basis_configure_script (\"${SCRIPT_FILE}\" \"${CONFIGURED_FILE}\" @ONLY)\n")
02250 if (MODULE)
02251 # compile module if applicable
02252 if (COMPILE AND BASIS_LANGUAGE MATCHES "PYTHON")
02253 set (C "${C}execute_process (COMMAND \"${PYTHON_EXECUTABLE}\" -c \"import py_compile;py_compile.compile('${CONFIGURED_FILE}')\")\n")
02254 get_filename_component (MODULE_PATH "${CONFIGURED_FILE}" PATH)
02255 get_filename_component (MODULE_NAME "${CONFIGURED_FILE}" NAME_WE)
02256 set (OUTPUT_FILE "${MODULE_PATH}/${MODULE_NAME}.pyc")
02257 list (APPEND OUTPUT_FILES "${OUTPUT_FILE}")
02258 endif ()
02259 else ()
02260 # or set executable bit on Unix
02261 set (C "${C}\n")
02262 set (C "${C}if (UNIX)\n")
02263 set (C "${C} execute_process (COMMAND /bin/chmod +x \"${CONFIGURED_FILE}\")\n")
02264 set (C "${C}endif ()\n")
02265 endif ()
02266
02267 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02268 # build script for installation tree (optional)
02269
02270 if (MODULE)
02271 set (INSTALL_DIR "${LIBRARY_INSTALL_DIRECTORY}")
02272 else ()
02273 set (INSTALL_DIR "${RUNTIME_INSTALL_DIRECTORY}")
02274 endif ()
02275
02276 if (INSTALL_DIR)
02277 # script configuration code
02278 set (C "${C}\n")
02279 set (C "${C}# build script for use in installation tree\n")
02280 set (C "${C}set (BUILD_INSTALL_SCRIPT 1)\n")
02281 set (C "${C}set (DIR \"${INSTALL_PREFIX}/${INSTALL_DIR}\")\n")
02282 set (C "${C}set (FILE \"\${DIR}/\${NAME}\")\n")
02283 set (C "${C}\n")
02284 set (C "${C}include (\"${BINARY_CONFIG_DIR}/BasisScriptConfig.cmake\")\n")
02285 set (C "${C}include (\"${BINARY_CONFIG_DIR}/ScriptConfig.cmake\" OPTIONAL)\n")
02286 set (C "${C}include (\"${BUILD_DIR}/ScriptConfig.cmake\" OPTIONAL)\n")
02287 set (C "${C}\n")
02288 if (COMPILE_DEFINITIONS)
02289 set (C "${C}${COMPILE_DEFINITIONS}\n")
02290 endif ()
02291 # configure script for installation tree
02292 set (C "${C}basis_configure_script (\"${SCRIPT_FILE}\" \"${CONFIGURED_INSTALL_FILE}\" @ONLY)\n")
02293 # compile module if applicable
02294 if (MODULE AND COMPILE AND BASIS_LANGUAGE MATCHES "PYTHON")
02295 set (C "${C}execute_process (COMMAND \"${PYTHON_EXECUTABLE}\" -c \"import py_compile;py_compile.compile('${CONFIGURED_INSTALL_FILE}')\")\n")
02296 get_filename_component (MODULE_PATH "${CONFIGURED_INSTALL_FILE}" PATH)
02297 get_filename_component (MODULE_NAME "${CONFIGURED_INSTALL_FILE}" NAME_WE)
02298 set (INSTALL_FILE "${MODULE_PATH}/${MODULE_NAME}.pyc")
02299 string (REGEX REPLACE "\\.py$" ".pyc" INSTALL_NAME "${INSTALL_NAME}")
02300 list (APPEND OUTPUT_FILES "${INSTALL_FILE}")
02301 endif ()
02302 endif ()
02303
02304 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02305 # otherwise, just copy script file
02306 else ()
02307
02308 set (C "${C}\nbasis_configure_script (\"${SCRIPT_FILE}\" \"${CONFIGURED_FILE}\" COPYONLY)\n")
02309 # compile module if applicable
02310 if (MODULE)
02311 if (COMPILE AND BASIS_LANGUAGE MATCHES "PYTHON")
02312 set (C "${C}execute_process (COMMAND \"${PYTHON_EXECUTABLE}\" -c \"import py_compile;py_compile.compile('${CONFIGURED_FILE}')\")\n")
02313 get_filename_component (MODULE_PATH "${CONFIGURED_FILE}" PATH)
02314 get_filename_component (MODULE_NAME "${CONFIGURED_FILE}" NAME_WE)
02315 set (OUTPUT_FILE "${MODULE_PATH}/${MODULE_NAME}.pyc")
02316 list (APPEND OUTPUT_FILES "${OUTPUT_FILE}")
02317 set (INSTALL_FILE "${OUTPUT_FILE}")
02318 string (REGEX REPLACE "\\.py$" ".pyc" INSTALL_NAME "${INSTALL_NAME}")
02319 endif ()
02320 # or set executable bit on Unix
02321 else ()
02322 set (C "${C}\n")
02323 set (C "${C}if (UNIX)\n")
02324 set (C "${C} execute_process (COMMAND /bin/chmod +x \"${CONFIGURED_FILE}\")\n")
02325 set (C "${C}endif ()\n")
02326 endif ()
02327
02328 endif ()
02329
02330 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02331 # setup build commands
02332
02333 # write/update build script
02334 if (EXISTS "${BUILD_SCRIPT}")
02335 file (WRITE "${BUILD_SCRIPT}.tmp" "${C}")
02336 execute_process (
02337 COMMAND "${CMAKE_COMMAND}" -E copy_if_different
02338 "${BUILD_SCRIPT}.tmp" "${BUILD_SCRIPT}"
02339 )
02340 file (REMOVE "${BUILD_SCRIPT}.tmp")
02341 else ()
02342 file (WRITE "${BUILD_SCRIPT}" "${C}")
02343 endif ()
02344
02345 # add custom target to execute build script
02346 file (RELATIVE_PATH REL "${CMAKE_BINARY_DIR}" "${OUTPUT_FILE}")
02347
02348 add_custom_command (
02349 OUTPUT ${OUTPUT_FILES}
02350 MAIN_DEPENDENCY "${SCRIPT_FILE}"
02351 DEPENDS ${DEPENDS}
02352 COMMAND "${CMAKE_COMMAND}" -P "${BUILD_SCRIPT}"
02353 COMMENT "Building script ${REL}..."
02354 )
02355
02356 if (TARGET "_${TARGET_UID}")
02357 message (FATAL_ERROR "There is another target named _${TARGET_UID}. "
02358 "BASIS uses target names starting with an underscore "
02359 "for custom targets which are required to build script files. "
02360 "Do not use leading underscores in target names.")
02361 endif ()
02362
02363 # add custom target which triggers execution of build script
02364 add_custom_target (_${TARGET_UID} DEPENDS ${OUTPUT_FILES})
02365 add_dependencies (${TARGET_UID} _${TARGET_UID})
02366
02367 # Provide target to build all scripts. In particular, scripts need to be build
02368 # before the doc target which thus depends on this target.
02369 if (NOT TARGET scripts)
02370 add_custom_target (scripts)
02371 endif ()
02372 add_dependencies (scripts _${TARGET_UID})
02373
02374 # cleanup on "make clean"
02375 set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${OUTPUT_FILES})
02376
02377 # install script
02378 if (NOT ARGN_NO_EXPORT)
02379 if (TEST)
02380 basis_set_project_property (APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}")
02381 else ()
02382 basis_set_project_property (APPEND PROPERTY CUSTOM_EXPORT_TARGETS "${TARGET_UID}")
02383 endif ()
02384 endif ()
02385
02386 if (MODULE)
02387 if (LIBRARY_INSTALL_DIRECTORY)
02388 install (
02389 FILES "${INSTALL_FILE}"
02390 RENAME "${INSTALL_NAME}"
02391 DESTINATION "${LIBRARY_INSTALL_DIRECTORY}"
02392 COMPONENT "${LIBRARY_COMPONENT}"
02393 )
02394 endif ()
02395 else ()
02396 if (RUNTIME_INSTALL_DIRECTORY)
02397 install (
02398 PROGRAMS "${INSTALL_FILE}"
02399 RENAME "${INSTALL_NAME}"
02400 DESTINATION "${RUNTIME_INSTALL_DIRECTORY}"
02401 COMPONENT "${RUNTIME_COMPONENT}"
02402 )
02403 endif ()
02404 endif ()
02405
02406 if (BASIS_VERBOSE)
02407 message (STATUS "Adding build command for script ${TARGET_UID}... - done")
02408 endif ()
02409 endfunction ()
02410
02411 # ----------------------------------------------------------------------------
02412 # @brief Add target to build/install __init__.py files.
02413 function (basis_add_init_py_target)
02414 # constants
02415 set (BUILD_DIR "${PROJECT_BINARY_DIR}/CMakeFiles/_initpy.dir")
02416 basis_sanitize_for_regex (BINARY_PYTHON_LIBRARY_DIR_REGEX "${BINARY_PYTHON_LIBRARY_DIR}")
02417 basis_sanitize_for_regex (TESTING_PYTHON_LIBRARY_DIR_REGEX "${TESTING_PYTHON_LIBRARY_DIR}")
02418 basis_sanitize_for_regex (INSTALL_PYTHON_LIBRARY_DIR_REGEX "${INSTALL_PYTHON_LIBRARY_DIR}")
02419 # collect build tree directories requiring a __init__.py file
02420 set (DIRS) # directories for which to generate a __init__.py file
02421 set (EXCLUDE) # exclude these directories
02422 set (INSTALL_EXCLUDE) # exclude these directories on installation
02423 set (COMPONENTS) # installation components
02424 basis_get_project_property (TARGETS PROPERTY TARGETS)
02425 foreach (TARGET_UID ${TARGETS})
02426 get_target_property (BASIS_TYPE ${TARGET_UID} "BASIS_TYPE")
02427 get_target_property (BASIS_LANGUAGE ${TARGET_UID} "BASIS_LANGUAGE")
02428 if (BASIS_TYPE MATCHES "^MODULE_SCRIPT$" AND BASIS_LANGUAGE MATCHES "PYTHON")
02429 # get absolute path of built Python module
02430 basis_get_target_location (LOCATION ${TARGET_UID} ABSOLUTE)
02431 basis_get_target_location (INSTALL_LOCATION ${TARGET_UID} POST_INSTALL_RELATIVE)
02432 # get component (used by installation rule)
02433 get_target_property (COMPONENT ${TARGET_UID} "LIBRARY_COMPONENT")
02434 list (FIND COMPONENTS "${COMPONENT}" IDX)
02435 if (IDX EQUAL -1)
02436 list (APPEND COMPONENTS "${COMPONENT}")
02437 set (INSTALL_DIRS_${COMPONENT}) # list of directories for which to install
02438 # __init__.py for this component
02439 endif ()
02440 # directories for which to build a __init__.py file
02441 basis_get_filename_component (DIR "${LOCATION}" PATH)
02442 if (LOCATION MATCHES "/__init__.py$")
02443 list (APPEND EXCLUDE "${DIR}")
02444 else ()
02445 if (DIR MATCHES "^${BINARY_PYTHON_LIBRARY_DIR_REGEX}/.+")
02446 while (NOT "${DIR}" MATCHES "^${BINARY_PYTHON_LIBRARY_DIR_REGEX}$")
02447 list (APPEND DIRS "${DIR}")
02448 get_filename_component (DIR "${DIR}" PATH)
02449 endwhile ()
02450 elseif (DIR MATCHES "^${TESTING_PYTHON_LIBRARY_DIR_REGEX}/.+")
02451 while (NOT "${DIR}" MATCHES "^${TESTING_PYTHON_LIBRARY_DIR_REGEX}$")
02452 list (APPEND DIRS "${DIR}")
02453 get_filename_component (DIR "${DIR}" PATH)
02454 endwhile ()
02455 endif ()
02456 endif ()
02457 # directories for which to install a __init__.py file
02458 basis_get_filename_component (DIR "${INSTALL_LOCATION}" PATH)
02459 if (INSTALL_LOCATION MATCHES "/__init__.py$")
02460 list (APPEND INSTALL_EXCLUDE "${DIR}")
02461 else ()
02462 if (DIR MATCHES "^${INSTALL_PYTHON_LIBRARY_DIR_REGEX}/.+")
02463 while (NOT "${DIR}" MATCHES "^${INSTALL_PYTHON_LIBRARY_DIR_REGEX}$")
02464 list (APPEND INSTALL_DIRS_${COMPONENT} "${DIR}")
02465 get_filename_component (DIR "${DIR}" PATH)
02466 endwhile ()
02467 endif ()
02468 endif ()
02469 endif ()
02470 endforeach ()
02471 # return if no Python module is being build
02472 if (NOT DIRS)
02473 return ()
02474 endif ()
02475 list (REMOVE_DUPLICATES DIRS)
02476 if (EXCLUDE)
02477 list (REMOVE_DUPLICATES EXCLUDE)
02478 endif ()
02479 if (INSTALL_EXCLUDE)
02480 list (REMOVE_DUPLICATES INSTALL_EXCLUDE)
02481 endif ()
02482 # generate build script
02483 set (C)
02484 set (OUTPUT_FILES)
02485 foreach (DIR IN LISTS DIRS)
02486 list (FIND EXCLUDE "${DIR}" IDX)
02487 if (IDX EQUAL -1)
02488 set (C "${C}configure_file (\"${BASIS_PYTHON_TEMPLATES_DIR}/__init__.py.in\" \"${DIR}/__init__.py\" @ONLY)\n")
02489 list (APPEND OUTPUT_FILES "${DIR}/__init__.py")
02490 if (BASIS_COMPILE_SCRIPTS)
02491 set (C "${C}execute_process (COMMAND \"${PYTHON_EXECUTABLE}\" -c \"import py_compile;py_compile.compile('${DIR}/__init__.py')\")\n")
02492 list (APPEND OUTPUT_FILES "${DIR}/__init__.pyc")
02493 endif ()
02494 endif ()
02495 endforeach ()
02496 set (C "${C}configure_file (\"${BASIS_PYTHON_TEMPLATES_DIR}/__init__.py.in\" \"${BUILD_DIR}/__init__.py\" @ONLY)\n")
02497 list (APPEND OUTPUT_FILES "${BUILD_DIR}/__init__.py")
02498 if (BASIS_COMPILE_SCRIPTS)
02499 set (C "${C}execute_process (COMMAND \"${PYTHON_EXECUTABLE}\" -c \"import py_compile;py_compile.compile('${BUILD_DIR}/__init__.py')\")\n")
02500 list (APPEND OUTPUT_FILES "${BUILD_DIR}/__init__.pyc")
02501 endif ()
02502 # write/update build script
02503 set (BUILD_SCRIPT "${BUILD_DIR}/build.cmake")
02504 if (EXISTS "${BUILD_SCRIPT}")
02505 file (WRITE "${BUILD_SCRIPT}.tmp" "${C}")
02506 execute_process (
02507 COMMAND "${CMAKE_COMMAND}" -E copy_if_different
02508 "${BUILD_SCRIPT}.tmp" "${BUILD_SCRIPT}"
02509 )
02510 file (REMOVE "${BUILD_SCRIPT}.tmp")
02511 else ()
02512 file (WRITE "${BUILD_SCRIPT}" "${C}")
02513 endif ()
02514 # add custom build command
02515 add_custom_command (
02516 OUTPUT ${OUTPUT_FILES}
02517 COMMAND "${CMAKE_COMMAND}" -P "${BUILD_SCRIPT}"
02518 COMMENT "Building __init__.py modules..."
02519 )
02520 # add custom target which triggers execution of build script
02521 add_custom_target (_initpy ALL DEPENDS ${OUTPUT_FILES})
02522 if (TARGET scripts)
02523 add_dependencies (scripts _initpy)
02524 endif ()
02525 # cleanup on "make clean"
02526 set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${OUTPUT_FILES})
02527 # add install rules
02528 if (BASIS_COMPILE_SCRIPTS)
02529 set (INSTALL_INIT_FILE "${BUILD_DIR}/__init__.pyc")
02530 else ()
02531 set (INSTALL_INIT_FILE "${BUILD_DIR}/__init__.py")
02532 endif ()
02533 foreach (COMPONENT IN LISTS COMPONENTS)
02534 if (INSTALL_DIRS_${COMPONENT})
02535 list (REMOVE_DUPLICATES INSTALL_DIRS_${COMPONENT})
02536 endif ()
02537 foreach (DIR IN LISTS INSTALL_DIRS_${COMPONENT})
02538 list (FIND INSTALL_EXCLUDE "${DIR}" IDX)
02539 if (IDX EQUAL -1)
02540 install (
02541 FILES "${INSTALL_INIT_FILE}"
02542 DESTINATION "${DIR}"
02543 COMPONENT "${COMPONENT}"
02544 )
02545 endif ()
02546 endforeach ()
02547 endforeach ()
02548 endfunction ()
02549
02550 # ----------------------------------------------------------------------------
02551 ## @brief Finalize addition of custom targets.
02552 #
02553 # This function is called by basis_add_project_finalize() to finalize the
02554 # addition of the custom build targets such as, for example, build targets
02555 # to build script files, MATLAB Compiler targets, and MEX script generated
02556 # MEX-files.
02557 #
02558 # @returns Adds custom targets that actually build the executables and
02559 # libraries for which custom build targets where added by
02560 # basis_add_executable(), basis_add_library(), and basis_add_script().
02561 #
02562 # @sa basis_add_script_finalize()
02563 # @sa basis_add_mcc_target_finalize()
02564 # @sa basis_add_mex_target_finalize()
02565 function (basis_add_custom_finalize)
02566 basis_get_project_property (TARGETS PROPERTY TARGETS)
02567 foreach (TARGET_UID ${TARGETS})
02568 get_target_property (BASIS_TYPE ${TARGET_UID} "BASIS_TYPE")
02569 if (BASIS_TYPE MATCHES "SCRIPT")
02570 basis_add_script_finalize (${TARGET_UID})
02571 elseif (BASIS_TYPE MATCHES "MEX")
02572 basis_add_mex_target_finalize (${TARGET_UID})
02573 elseif (BASIS_TYPE MATCHES "MCC")
02574 basis_add_mcc_target_finalize (${TARGET_UID})
02575 endif ()
02576 endforeach ()
02577 endfunction ()
02578
02579
02580 ## @}
02581 # end of Doxygen group