#
# @tp @b COMPONENT name @endtp
# Name of component as part of which this executable will be installed
# if the specified @c DESTINATION is not "none".
# (default: @c BASIS_RUNTIME_COMPONENT) |
#
#
# @tp @b DESTINATION dir @endtp
# Installation directory relative to @c CMAKE_INSTALL_PREFIX.
# If "none" (case-insensitive) is given as argument, no default
# installation rules are added for this executable target.
# (default: @c INSTALL_RUNTIME_DIR or @c INSTALL_LIBEXEC_DIR
# if the @p LIBEXEC option is given) |
#
#
# @tp @b LANGUAGE lang @endtp
# Programming language in which source files are written (case-insensitive).
# If not specified, the programming language is derived from the file name
# extensions of the source files and, if applicable, the shebang directive
# on the first line of the script file. If the programming language could
# not be detected automatically, check the file name extensions of the
# source files and whether no unrecognized additional arguments were given
# or specify the programming language using this option.
# (default: auto-detected) |
#
#
# @tp @b LIBEXEC @endtp
# Specifies that the built executable is an auxiliary executable which
# is only called by other executables. (default: @c FALSE) |
#
#
# @tp @b [NO]EXPORT @endtp
# Whether to export this target. (default: @c TRUE) |
#
#
# @tp @b NO_BASIS_UTILITIES @endtp
# Specify that the BASIS utilities are not used by this executable and hence
# no link dependency on the BASIS utilities shall be added.
# (default: @c NOT @c BASIS_UTILITIES) |
#
#
# @tp @b USE_BASIS_UTILITIES @endtp
# Specify that the BASIS utilities are used and required by this executable
# and hence a link dependency on the BASIS utilities has to be added.
# (default: @c BASIS_UTILITIES) |
#
#
#
# @returns Adds an executable build target. In case of an executable which is
# not build from C++ source files, the function basis_finalize_targets()
# has to be invoked to finalize the addition of the custom build target.
# This is done by the basis_project_end() macro.
#
# @sa basis_add_executable_target()
# @sa basis_add_script()
# @sa basis_add_mcc_target()
#
# @ingroup CMakeAPI
function (basis_add_executable TARGET_NAME)
# --------------------------------------------------------------------------
# parse arguments
CMAKE_PARSE_ARGUMENTS (
ARGN
"EXECUTABLE;LIBEXEC;NO_BASIS_UTILITIES;USE_BASIS_UTILITIES;EXPORT;NOEXPORT"
"COMPONENT;DESTINATION;LANGUAGE"
""
${ARGN}
)
# derive target name from path if existing source path is given as first argument instead
# and get list of library source files
get_filename_component (S "${TARGET_NAME}" ABSOLUTE)
if (IS_DIRECTORY "${S}" AND NOT ARGN_UNPARSED_ARGUMENTS)
set (SOURCES "${S}")
basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE)
elseif (EXISTS "${S}" AND NOT IS_DIRECTORY "${S}" OR (NOT S MATCHES "\\.in$" AND EXISTS "${S}.in" AND NOT IS_DIRECTORY "${S}.in"))
set (SOURCES "${S}")
basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE)
else ()
set (SOURCES)
endif ()
if (ARGN_UNPARSED_ARGUMENTS)
list (APPEND SOURCES ${ARGN_UNPARSED_ARGUMENTS})
endif ()
if (NOT SOURCES)
message (FATAL_ERROR "basis_add_executable called with only one argument which does however not"
" appear to be a file name. Note that the filename extension must be"
" included if the target name should be derived from the base filename"
" of the source file.")
endif ()
# --------------------------------------------------------------------------
# make target UID
basis_check_target_name ("${TARGET_NAME}")
basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
# --------------------------------------------------------------------------
# process globbing expressions to get complete list of source files
basis_add_glob_target (${TARGET_UID} SOURCES ${SOURCES})
# --------------------------------------------------------------------------
# determine programming language
_basis_target_source_language ()
# --------------------------------------------------------------------------
# prepare arguments for subcommand
foreach (ARG IN LISTS ARGN_UNPARSED_ARGUMENTS)
list (REMOVE_ITEM ARGN "${ARG}")
endforeach ()
list (APPEND ARGN ${SOURCES})
# --------------------------------------------------------------------------
# C++
if (ARGN_LANGUAGE MATCHES "CXX")
basis_add_executable_target (.${TARGET_UID} ${ARGN})
# --------------------------------------------------------------------------
# MATLAB
elseif (ARGN_LANGUAGE MATCHES "MATLAB")
if (ARGN_LIBEXEC)
list (REMOVE_ITEM ARGN LIBEXEC)
basis_add_mcc_target (.${TARGET_UID} LIBEXEC ${ARGN})
else ()
list (REMOVE_ITEM ARGN EXECUTABLE)
basis_add_mcc_target (.${TARGET_UID} EXECUTABLE ${ARGN})
endif ()
# --------------------------------------------------------------------------
# others
else ()
if (ARGN_LIBEXEC)
list (REMOVE_ITEM ARGN LIBEXEC)
basis_add_script (.${TARGET_UID} LIBEXEC ${ARGN})
else ()
list (REMOVE_ITEM ARGN EXECUTABLE)
basis_add_script (.${TARGET_UID} EXECUTABLE ${ARGN})
endif ()
endif ()
# --------------------------------------------------------------------------
# re-glob source files before each build (if necessary)
if (TARGET __${TARGET_UID})
if (TARGET _${TARGET_UID})
add_dependencies (_${TARGET_UID} __${TARGET_UID})
endif ()
add_dependencies (${TARGET_UID} __${TARGET_UID})
endif ()
endfunction ()
# ----------------------------------------------------------------------------
## @brief Add library target.
#
# This is the main function to add a library target to the build system, where
# a library can be a binary archive, shared library, a MEX-file or module(s)
# written in a scripting language. In general we refer to any output file which
# is part of the software (i.e., excluding configuration files), but cannot be
# executed (e.g., a binary file in the ELF format) or interpreted
# (e.g., a Python module) directly, as library file. Natively, CMake supports only
# libraries built from C/C++ source code files. This function extends CMake's
# capabilities by adding custom build commands for non-natively supported
# programming languages and further standardizes the build of library targets.
# For example, by default, it is not necessary to specify installation rules
# separately as these are added by this function already (see below).
#
# @par Programming languages
# Besides adding usual library targets built from C/C++ source code files,
# this function can also add custom build targets for libraries implemented
# in other programming languages. It therefore tries to detect the programming
# language of the given source code files and delegates the addition of the
# build target to the proper helper functions. It in particular supports the
# following languages:
# @n
#
#
# @tp @b CXX @endtp
# Source files written in C/C++ are by default built into either
# @p STATIC, @p SHARED, or @p MODULE libraries. If the @p MEX option
# is given, however, a MEX-file (a shared library) is build using
# the MEX script instead of using the default C++ compiler directly. |
#
#
# @tp PYTHON|JYTHON|PERL|BASH @endtp
# Modules written in one of the named scripting languages are built similar
# to executable scripts except that the file name extension is preserved
# and no executable file permission is set on Unix. These modules are
# intended for import/inclusion in other modules or executables written
# in the particular scripting language only. |
#
#
# @tp @b MATLAB @endtp
# Libraries of M-files or shared libraries built using the MATLAB Compiler (mcc).
# This language option is used when the list of source files contains one or
# more *.m files. A custom target is added which depends on custom command(s)
# that build the library. If the type of the library is @c SHARED, a shared
# library is build using the MATLAB Compiler. Otherwise, the M-files are
# configured and installed such that they can be used in MATLAB. |
#
#
#
# @par Helper functions
# If the programming language of the input source files is not specified
# explicitly by providing the @p LANGUAGE argument, the extensions of the
# source files are inspected using basis_get_source_language(). Once the
# programming language is known, this function invokes the proper subcommand.
# In particular, it calls basis_add_library_target() for C++ sources (.cxx)
# if the target is not a MEX-file target, basis_add_mex_file() for C++ sources
# if the @p MEX option is given, basis_add_mcc_target() for MATLAB scripts (.m),
# and basis_add_script_library() for all other source files.
#
# @note DO NOT use the mentioned subcommands directly. Always use
# basis_add_library() to add a library target to your project. Only refer
# to the documentation of the subcommands to learn about the available
# options of the particular subcommand and the considered target properties.
#
# @par Output directories
# In case of modules written in a scripting language, the libraries are output to
# the
#
# @tp STATIC|SHARED|MODULE|MEX @endtp
# Type of the library. (default: @c SHARED for C++ libraries if
# @c BUILD_SHARED_LIBS evaluates to true or @c STATIC otherwise,
# and @c MODULE in all other cases) |
#
#
# @tp @b COMPONENT name @endtp
# Name of component as part of which this library will be installed
# if the @c RUNTIME_DESTINATION or @c LIBRARY_DESTINATION is not "none".
# Used only if @p RUNTIME_COMPONENT or @p LIBRARY_COMPONENT not specified.
# (default: see @p RUNTIME_COMPONENT and @p LIBRARY_COMPONENT) |
#
#
# @tp @b DESTINATION dir @endtp
# Installation directory for runtime and library component relative
# to @c CMAKE_INSTALL_PREFIX. Used only if @p RUNTIME_DESTINATION or
# @p LIBRARY_DESTINATION not specified. If "none" (case-insensitive)
# is given as argument, no default installation rules are added.
# (default: see @p RUNTIME_DESTINATION and @p LIBRARY_DESTINATION) |
#
#
# @tp @b LANGUAGE lang @endtp
# Programming language in which source files are written (case-insensitive).
# If not specified, the programming language is derived from the file name
# extensions of the source files and, if applicable, the shebang directive
# on the first line of the script file. If the programming language could
# not be detected automatically, check the file name extensions of the
# source files and whether no unrecognized additional arguments were given
# or specify the programming language using this option.
# (default: auto-detected) |
#
#
# @tp @b LIBRARY_COMPONENT name @endtp
# Name of component as part of which import/static library will be intalled
# if @c LIBRARY_DESTINATION is not "none".
# (default: @c COMPONENT if specified or @c BASIS_LIBRARY_COMPONENT otherwise) |
#
#
# @tp @b LIBRARY_DESTINATION dir @endtp
# Installation directory of the library component relative to
# @c CMAKE_INSTALL_PREFIX. If "none" (case-insensitive) is given as argument,
# no installation rule for the library component is added.
# (default: @c INSTALL_ARCHIVE_DIR) |
#
#
# @tp @b RUNTIME_COMPONENT name @endtp
# Name of component as part of which runtime library will be installed
# if @c RUNTIME_DESTINATION is not "none".
# (default: @c COMPONENT if specified or @c BASIS_RUNTIME_COMPONENT otherwise) |
#
#
# @tp @b RUNTIME_DESTINATION dir @endtp
# Installation directory of the runtime component relative to
# @c CMAKE_INSTALL_PREFIX. If "none" (case-insensitive) is given as argument,
# no installation rule for the runtime library is added.
# (default: @c INSTALL_LIBRARY_DIR on Unix or @c INSTALL_RUNTIME_DIR Windows) |
#
#
# @tp @b [NO]EXPORT @endtp
# Whether to export this target. (default: @c TRUE) |
#
#
# @tp @b NO_BASIS_UTILITIES @endtp
# Specify that the BASIS utilities are not used by this executable and hence
# no link dependency on the BASIS utilities shall be added.
# (default: @c NOT @c BASIS_UTILITIES) |
#
#
# @tp @b USE_BASIS_UTILITIES @endtp
# Specify that the BASIS utilities are used and required by this executable
# and hence a link dependency on the BASIS utilities has to be added.
# (default: @c BASIS_UTILITIES) |
#
#
#
# @returns Adds a library build target. In case of a library not written in C++
# or MEX-file targets, basis_finalize_targets() has to be invoked
# to finalize the addition of the build target(s). This is done
# by the basis_project_end() macro.
#
# @sa basis_add_library_target()
# @sa basis_add_script_library()
# @sa basis_add_mex_file()
# @sa basis_add_mcc_target()
#
# @ingroup CMakeAPI
function (basis_add_library TARGET_NAME)
# --------------------------------------------------------------------------
# parse arguments
CMAKE_PARSE_ARGUMENTS (
ARGN
"STATIC;SHARED;MODULE;MEX;USE_BASIS_UTILITIES;NO_BASIS_UTILITIES;EXPORT;NOEXPORT"
"COMPONENT;RUNTIME_COMPONENT;LIBRARY_COMPONENT;DESTINATION;RUNTIME_DESTINATION;LIBRARY_DESTINATION;LANGUAGE"
""
${ARGN}
)
# derive target name from path if existing source path is given as first argument instead
# and get list of library source files
get_filename_component (S "${TARGET_NAME}" ABSOLUTE)
if (IS_DIRECTORY "${S}" AND NOT ARGN_UNPARSED_ARGUMENTS)
set (SOURCES "${S}")
basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME)
elseif (EXISTS "${S}" AND NOT IS_DIRECTORY "${S}" OR (NOT S MATCHES "\\.in$" AND EXISTS "${S}.in" AND NOT IS_DIRECTORY "${S}.in"))
set (SOURCES "${S}")
if (ARGN_MEX)
basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE)
else ()
_basis_target_source_language ()
if ("$${ARGN_LANGUAGE}" STREQUAL "$CXX")
basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE)
else ()
basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME)
endif ()
endif ()
else ()
set (SOURCES)
endif ()
if (ARGN_UNPARSED_ARGUMENTS)
list (APPEND SOURCES ${ARGN_UNPARSED_ARGUMENTS})
endif ()
# --------------------------------------------------------------------------
# make target UID
basis_check_target_name ("${TARGET_NAME}")
basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
# --------------------------------------------------------------------------
# process globbing expressions to get complete list of source files
basis_add_glob_target (${TARGET_UID} SOURCES ${SOURCES})
# --------------------------------------------------------------------------
# determine programming language
_basis_target_source_language ()
# --------------------------------------------------------------------------
# prepare arguments for subcommand
foreach (ARG IN LISTS ARGN_UNPARSED_ARGUMENTS)
list (REMOVE_ITEM ARGN "${ARG}")
endforeach ()
list (APPEND ARGN ${SOURCES})
# --------------------------------------------------------------------------
# C++
if (ARGN_LANGUAGE MATCHES "CXX")
# MEX-file
if (ARGN_MEX)
if (ARGN_STATIC)
message (FATAL_ERROR "Target ${TARGET_UID}: Invalid library type! Only modules or shared libraries can be built by the MEX script.")
endif ()
list (REMOVE_ITEM ARGN MODULE)
list (REMOVE_ITEM ARGN SHARED)
list (REMOVE_ITEM ARGN MEX)
basis_add_mex_file (.${TARGET_UID} ${ARGN})
# library
else ()
basis_add_library_target (.${TARGET_UID} ${ARGN})
endif ()
# --------------------------------------------------------------------------
# MATLAB
elseif (ARGN_LANGUAGE MATCHES "MATLAB")
if (ARGN_STATIC OR ARGN_MEX)
message (FATAL_ERROR "Target ${TARGET_UID}: Invalid library type! Only shared libraries can be built by the MATLAB Compiler.")
endif ()
if (ARGN_SHARED)
list (REMOVE_ITEM ARGN SHARED)
basis_add_mcc_target (.${TARGET_UID} SHARED ${ARGN})
else ()
list (REMOVE_ITEM ARGN MODULE) # optional
basis_add_script_library (.${TARGET_UID} ${ARGN})
endif ()
# --------------------------------------------------------------------------
# other
else ()
if (ARGN_STATIC OR ARGN_SHARED OR ARGN_MEX)
message (FATAL_ERROR "Target ${TARGET_UID}: Invalid library type! Only modules can be built from scripts.")
endif ()
list (REMOVE_ITEM ARGN MODULE)
basis_add_script_library (.${TARGET_UID} ${ARGN})
endif ()
# --------------------------------------------------------------------------
# re-glob source files before each build (if necessary)
if (TARGET __${TARGET_UID})
if (TARGET _${TARGET_UID})
add_dependencies (_${TARGET_UID} __${TARGET_UID})
endif ()
add_dependencies (${TARGET_UID} __${TARGET_UID})
endif ()
endfunction ()
# ----------------------------------------------------------------------------
## @brief Add single arbitrary or executable script.
#
# @note This function should not be used directly for executable scripts or
# module libraries. Use basis_add_executable() or basis_add_library()
# in such (most) cases instead.
#
# This function can be used to add a single arbitrary script file (i.e., any
# text file which is input to a program), such as a CTest script for example,
# to the build if neither basis_add_executable() nor basis_add_library() are
# appropriate choices. In all other cases, either basis_add_executable() or
# basis_add_library() should be used. Note that the script file is by default
# not considered to be an executable. Instead it is assumed that the program
# which interprets/processes the script must be executed explicitly with this
# script as argument. Only scripts built with the @p EXECUTABLE or @p LIBEXEC
# type option are treated as executable files, where in case of Unix a shebang
# directive implicitly states the program used by the shell to interpret the
# script and on Windows a Windows Command which imitates the behavior of Unix
# shells is generated by BASIS. Do not use these type options, however, but
# only use the default @p MODULE option. The basis_add_executable() function
# should be used instead to add an executable script. The basis_add_script()
# function shall only be used for none-executable arbitrary script files which
# cannot be built by basis_add_executable() or basis_add_library().
#
# If the script name ends in
#
#
# @tp @b BASIS_UTILITIES @endtp
# Whether the BASIS utilities are used by this script. For the supported
# scripting languages for which BASIS utilities are implemented, BASIS
# will in most cases automatically detect whether these utilities are
# used by a script or not. Otherwise, set this property manually or use
# either the @p USE_BASIS_UTILITIES or the @p NO_BASIS_UTILITIES option
# when adding the script target. (default: auto-detected or @c UNKNOWN) |
#
#
# @tp @b BINARY_DIRECTORY @endtp
# Build tree directory of this target. (default: @c CMAKE_CURRENT_BINARY_DIR) |
#
#
# @tp @b COMPILE @endtp
# Whether to compile the script if the programming language allows such
# pre-compilation as in case of Python, for example. If @c TRUE, only the
# compiled file is installed. (default: @c BASIS_COMPILE_SCRIPTS) |
#
#
# @tp @b SCRIPT_DEFINITIONS @endtp
# CMake code which is evaluated after the inclusion of the default script
# configuration files. This code can be used to set the replacement text of the
# CMake variables ("@VAR@" patterns) used in the source file.
# See
# Build System Standard for details. (default: "") |
#
#
# @tp @b SCRIPT_DEFINITIONS_FILE @endtp
# CMake script file with compile definitions, also referred to as script
# configuration file. The named files are included after the default BASIS
# script configuration and before the @c SCRIPT_DEFINITIONS code is being
# evaluated. (default: @c BINARY_CONFIG_DIR/ScriptConfig.cmake) |
#
#
# @tp @b COMPONENT @endtp
# Name of component as part of which this script is installed if
# @c INSTALL_DIRECTORY is not set to "none".
# (default: see @p COMPONENT argument) |
#
#
# @tp @b EXPORT @endtp
# Whether to export this build target in which case an import library
# target is added to the custom exports file with the path to the
# built/installed script set as @c IMPORT_LOCATION. (default: @c TRUE) |
#
#
# @tp @b INSTALL_DIRECTORY @endtp
# Installation directory of script file configured for use in installation tree
# relative to @c CMAKE_INSTALL_PREFIX. Set to "none" (case-insensitive) to skip the
# addition of an installation rule. (default: see @p DESTINATION argument) |
#
#
# @tp @b LANGUAGE @endtp
# Read-only property of programming language of script file in uppercase letters.
# (default: see @p LANGUAGE argument) |
#
#
# @tp @b LINK_DEPENDS @endtp
# Paths or target names of script modules and libraries used by this script.
# In case of an (auxiliary) executable script, the directories of these modules
# are added to the search path for modules of the given programming language
# if such search paths are supported by the language and BASIS knows how to set
# these (as in case of Python/Jython, Perl, and MATLAB, in particular).
# Moreover, for each listed build target a dependency is added between this
# script target and the named build targets. Use basis_target_link_libraries()
# to add additional link dependencies.
# (default: BASIS utilities module if used or empty list otherwise) |
#
#
# @tp @b OUTPUT_DIRECTORY @endtp
# Output directory for built script file configured for use in build tree.
# (default: @c BINARY_LIBRARY_DIR for arbitrary scripts, @c BINARY_RUNTIME_DIR
# for executable scripts, and @c BINARY_LIBEXEC_DIR for auxiliary executables) |
#
#
# @tp @b OUTPUT_NAME @endtp
# Name of built script file including file name extension (if any).
# (default: basename of script file for arbitrary scripts, without extension
# for executable scripts on Unix, and .cmd extension on Windows
# in case of executable Python/Jython or Perl script) |
#
#
# @tp @b SOURCE_DIRECTORY @endtp
# Source directory of this target. (default: @c CMAKE_CURRENT_SOURCE_DIR) |
#
#
# @tp @b SOURCES @endtp
# Read-only property which lists the source file of this script target.
# Note that the first element in this list actually names a directory
# in the build, the one where the build script for this target is located
# instead of a source file and thus should be ignored. The second entry
# corresponds to the source file of this script target. |
#
#
#
# @attention Properties documented as read-only must not be modified.
#
# @note If this function is used within the @c PROJECT_TESTING_DIR, the built
# executable is output to the @c BINARY_TESTING_DIR directory tree instead.
# Moreover, no installation rules are added. Test executables are further
# not exported, regardless of the @c EXPORT property.
#
# @param [in] TARGET_NAME Name of build target. If an existing file is given as
# argument, it is added to the list of source files and
# the target name is derived from the name of this file.
# @param [in] ARGN The remaining arguments are parsed and the following arguments
# recognized. All unparsed arguments are treated as source files,
# where in particular exactly one source file is required if the
# @p TARGET_NAME argument does not name an existing source file.
# @par
#
#
# @tp MODULE|EXECUTABLE|LIBEXEC @endtp
# Type of script to built, i.e., either arbitrary module script which
# cannot be executed directly, an executable script with proper shebang
# directive and execute permissions on Unix or Windows Command on Windows,
# or an auxiliary executable. The type of the script mainly changes the
# default values of the target properties such as the output and installation
# directories. To add an (auxiliary) executable script, use
# basis_add_executable(), however, instead of this function.
# The @c EXECUTABLE and @c LIBEXEC options are only intended for
# internal use by BASIS. (default: MODULE) |
#
#
# @tp @b COMPONENT name @endtp
# Name of installation component as part of which this script is being
# installed if the @c INSTALL_DIRECTORY property is not "none".
# (default: @c BASIS_LIBRARY_COMPONENT for arbitrary scripts or
# @c BASIS_RUNTIME_COMPONENT for executable scripts) |
#
#
# @tp @b DESTINATION dir @endtp
# Installation directory for script file relative to @c CMAKE_INSTALL_PREFIX.
# If an absolute path is given as argument, it is made relative to the
# configured installation prefix.
# (default: @c INSTALL_LIBRARY_DIR for arbitrary scripts,
# @c INSTALL_RUNTIME_DIR for executable scripts, and @c INSTALL_LIBEXEC_DIR
# for auxiliary executable scripts) |
#
#
# @tp @b LANGUAGE lang @endtp
# Programming language in which script file is written (case-insensitive).
# If not specified, the programming language is derived from the file name
# extension of the source file and the shebang directive on the first line
# of the script if any. If the programming language could not be detected
# automatically, the @c LANGUAGE property is set to @c UNKNOWN. Note that
# for arbitrary script targets, the script file will still be built correctly
# even if the scripting language was not recognized. The automatic detection
# whether the BASIS utilities are used and required will fail, however.
# In this case, specify the programming language using this option.
# (default: auto-detected or @c UNKNOWN) |
#
#
# @tp @b [NO]EXPORT @endtp
# Whether to export this target. (default: @c TRUE) |
#
#
# @tp @b NO_BASIS_UTILITIES @endtp
# Specify that the BASIS utilities are not used by this script. If the
# programming language of the script is known and BASIS utilities are
# available for this language, BASIS will in most cases automatically
# detect whether these utilities are used by a script or not. Use this
# option to skip this check because the script does not make use of the
# BASIS utilities. |
#
#
# @tp @b USE_BASIS_UTILITIES @endtp
# Specify that the BASIS utilities are used and thus required by this script.
# If the programming language of the script is known and BASIS utilities are
# available for this language, BASIS will in most cases automatically
# detect whether these utilities are used by a script or not. Use this option
# to skip this check because it is already known that the script makes use of
# the BASIS utilities. Note that an error is raised if this option is given,
# but no BASIS utilities are available for the programming language of this
# script or if the programming language is unknown, respectively, not detected
# correctly. In this case, consider the use of the @p LANGUAGE argument. |
#
#
#
# @returns Adds a custom CMake target with the documented properties. The actual custom
# command to build the script is added by basis_build_script().
#
# @ingroup CMakeAPI
function (basis_add_script TARGET_NAME)
# parse arguments
CMAKE_PARSE_ARGUMENTS (
ARGN
"MODULE;EXECUTABLE;LIBEXEC;NO_BASIS_UTILITIES;USE_BASIS_UTILITIES;EXPORT;NOEXPORT"
"COMPONENT;DESTINATION;LANGUAGE"
""
${ARGN}
)
if (NOT ARGN_MODULE AND NOT ARGN_EXECUTABLE AND NOT ARGN_LIBEXEC)
set (ARGN_MODULE TRUE)
endif ()
if (ARGN_MODULE)
set (TYPE MODULE)
else ()
set (TYPE EXECUTABLE)
endif ()
string (TOLOWER "${TYPE}" type)
# derive target name from file name if existing source file given as first argument
get_filename_component (S "${TARGET_NAME}" ABSOLUTE)
if (EXISTS "${S}" AND NOT IS_DIRECTORY "${S}" OR (NOT S MATCHES "\\.in$" AND EXISTS "${S}.in" AND NOT IS_DIRECTORY "${S}.in"))
set (SOURCES "${S}")
if (ARGN_MODULE)
basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME)
else ()
basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE)
endif ()
set (SET_OUTPUT_NAME_TO_TARGET_NAMEE FALSE)
else ()
set (SOURCES)
set (SET_OUTPUT_NAME_TO_TARGET_NAME TRUE)
endif ()
# check target name
basis_check_target_name ("${TARGET_NAME}")
basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
message (STATUS "Adding ${type} script ${TARGET_UID}...")
if (ARGN_MODULE AND TYPE MATCHES "EXECUTABLE")
message (FATAL_ERROR "Target ${TARGET_UID}: MODULE and EXECUTABLE or LIBEXEC options are mutually exclusive!")
endif ()
# check/set parsed arguments
basis_set_flag (ARGN EXPORT ${BASIS_EXPORT_DEFAULT})
if (ARGN_USE_BASIS_UTILITIES AND ARGN_NO_BASIS_UTILITIES)
message (FATAL_ERROR "Options USE_BASIS_UTILITIES and NO_BASIS_UTILITIES are mutually exclusive!")
endif ()
list (LENGTH ARGN_UNPARSED_ARGUMENTS N)
if (SOURCES)
math (EXPR N "${N} + 1")
endif ()
if (N GREATER 1)
if (NOT SOURCES)
list (REMOVE_AT ARGN_UNPARSED_ARGUMENTS 0)
endif ()
message (FATAL_ERROR "Target ${TARGET_UID}: Too many or unrecognized arguments: ${ARGN_UNPARSED_ARGUMENTS}!\n"
" Only one script can be built by each script target.")
elseif (NOT SOURCES)
set (SOURCES "${ARGN_UNPARSED_ARGUMENTS}")
get_filename_component (SOURCES "${SOURCES}" ABSOLUTE)
endif ()
if (NOT EXISTS "${SOURCES}" AND NOT SOURCES MATCHES "\\.in$" AND EXISTS "${SOURCES}.in")
set (SOURCES "${SOURCES}.in")
endif ()
if (NOT EXISTS "${SOURCES}")
string (REGEX REPLACE "\\.in$" "" SOURCES "${SOURCES}")
message (FATAL_ERROR "Target ${TARGET_UID}: Source file ${SOURCES}[.in] does not exist!")
endif ()
# add custom target
add_custom_target (${TARGET_UID} ALL SOURCES ${SOURCES})
# dump CMake variables for configuration of script
set (BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TARGET_UID}")
basis_dump_variables ("${BUILD_DIR}.dir/cache.cmake.tmp")
# auto-detect programming language (may be as well UNKNOWN)
if (ARGN_LANGUAGE)
string (TOUPPER "${ARGN_LANGUAGE}" ARGN_LANGUAGE)
else ()
basis_get_source_language (ARGN_LANGUAGE ${SOURCES})
endif ()
# IS_TEST flag
basis_sanitize_for_regex (RE "${PROJECT_TESTING_DIR}")
if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${RE}")
set (IS_TEST TRUE)
else ()
set (IS_TEST FALSE)
endif ()
# default directory infix used below
if (ARGN_MODULE)
set (TYPE_INFIX "LIBRARY")
elseif (ARGN_LIBEXEC)
set (TYPE_INFIX "LIBEXEC")
else ()
set (TYPE_INFIX "RUNTIME")
endif ()
# output name
string (REGEX REPLACE "\\.in$" "" SOURCE_NAME "${SOURCES}")
if (SET_OUTPUT_NAME_TO_TARGET_NAME)
basis_get_target_name (OUTPUT_NAME ${TARGET_UID})
else ()
get_filename_component (OUTPUT_NAME "${SOURCE_NAME}" NAME_WE)
endif ()
if (ARGN_MODULE)
get_filename_component (SUFFIX "${SOURCE_NAME}" EXT)
else ()
if (WIN32)
if (ARGN_LANGUAGE MATCHES "[JP]YTHON|PERL")
set (SUFFIX ".cmd")
else ()
get_filename_component (SUFFIX "${SOURCE_NAME}" EXT)
endif ()
else ()
set (SUFFIX)
endif ()
endif ()
# output directory
if (IS_TEST)
set (OUTPUT_DIRECTORY "${TESTING_${TYPE_INFIX}_DIR}")
else ()
set (OUTPUT_DIRECTORY "${BINARY_${TYPE_INFIX}_DIR}")
endif ()
# installation component
if (NOT ARGN_COMPONENT)
if (ARGN_MODULE)
set (ARGN_COMPONENT "${BASIS_LIBRARY_COMPONENT}")
else ()
set (ARGN_COMPONENT "${BASIS_RUNTIME_COMPONENT}")
endif ()
endif ()
if (NOT ARGN_COMPONENT)
set (ARGN_COMPONENT "Unspecified")
endif ()
# installation directory
if (ARGN_DESTINATION)
if (ARGN_DESTINATION MATCHES "^[nN][oO][nN][eE]$")
set (ARGN_DESTINATION)
elseif (IS_ABSOLUTE "${ARGN_DESTINATION}")
file (RELATIVE_PATH ARGN_DESTINATION "${CMAKE_INSTALL_PREFIX}" "${ARGN_DESTINATION}")
endif ()
elseif (IS_TEST)
set (ARGN_DESTINATION) # do not install
else ()
set (ARGN_DESTINATION "${INSTALL_${TYPE_INFIX}_DIR}")
endif ()
# script configuration ("compile definitions")
if (EXISTS "${BINARY_CONFIG_DIR}/ScriptConfig.cmake")
set (CONFIG_FILE "${BINARY_CONFIG_DIR}/ScriptConfig.cmake")
else ()
set (CONFIG_FILE)
endif ()
# auto-detect use of BASIS utilities
set (LINK_DEPENDS)
if (ARGN_LANGUAGE MATCHES "[JP]YTHON")
set (UTILITIES_LANGUAGE "PYTHON")
else ()
set (UTILITIES_LANGUAGE "${ARGN_LANGUAGE}")
endif ()
if (ARGN_USE_BASIS_UTILITIES)
if (NOT BASIS_UTILITIES_ENABLED MATCHES "${UTILITIES_LANGUAGE}")
message (FATAL_ERROR "Target ${TARGET_UID} requires the BASIS utilities for ${UTILITIES_LANGUAGE}"
" but BASIS was either build without the build of these utilities enabled"
" or no utilities for this programming language are implemented. Remove the"
" USE_BASIS_UTILITIES option if no BASIS utilities are used by the script"
" ${SOURCES} or specify the correct programming language if it was not"
" detected correctly.")
endif ()
set (USES_BASIS_UTILITIES TRUE)
elseif (NOT ARGN_NO_BASIS_UTILITIES AND NOT UTILITIES_LANGUAGE MATCHES "UNKNOWN")
basis_utilities_check (USES_BASIS_UTILITIES ${SOURCES} ${UTILITIES_LANGUAGE})
else ()
set (USES_BASIS_UTILITIES FALSE)
endif ()
if (USES_BASIS_UTILITIES)
basis_set_project_property (PROPERTY PROJECT_USES_${UTILITIES_LANGUAGE}_UTILITIES TRUE)
if (BASIS_DEBUG)
message ("** Target ${TARGET_UID} uses the BASIS utilities for ${UTILITIES_LANGUAGE}.")
endif ()
endif ()
# set properties of custom build target
set_target_properties (
${TARGET_UID}
PROPERTIES
LANGUAGE ${ARGN_LANGUAGE}
BASIS_TYPE SCRIPT_${TYPE}
BASIS_UTILITIES ${USES_BASIS_UTILITIES}
BUILD_DIRECTORY "${BUILD_DIR}"
SOURCE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
BINARY_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
OUTPUT_DIRECTORY "${OUTPUT_DIRECTORY}"
INSTALL_DIRECTORY "${ARGN_DESTINATION}"
COMPONENT "${ARGN_COMPONENT}"
OUTPUT_NAME "${OUTPUT_NAME}"
PREFIX ""
SUFFIX "${SUFFIX}"
SCRIPT_DEFINITIONS ""
SCRIPT_DEFINITIONS_FILE "${CONFIG_FILE}"
LINK_DEPENDS "${LINK_DEPENDS}"
EXPORT ${EXPORT}
COMPILE ${BASIS_COMPILE_SCRIPTS}
TEST ${IS_TEST}
LIBEXEC ${ARGN_LIBEXEC}
)
# add target to list of targets
basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET_UID}")
message (STATUS "Adding ${type} script ${TARGET_UID}... - done")
endfunction ()
# ============================================================================
# internal helpers
# ============================================================================
# ----------------------------------------------------------------------------
## @brief Add executable target.
#
# This BASIS function overwrites CMake's
#
#
# @tp @b COMPONENT name @endtp
# Name of component as part of which this executable will be installed
# if the specified @c DESTINATION is not "none".
# (default: @c BASIS_RUNTIME_COMPONENT) |
#
#
# @tp @b DESTINATION dir @endtp
# Installation directory relative to @c CMAKE_INSTALL_PREFIX.
# If "none" (case-insensitive) is given as argument, no default
# installation rules are added for this executable target.
# (default: @c INSTALL_RUNTIME_DIR or @c INSTALL_LIBEXEC_DIR
# if @p LIBEXEC is given) |
#
#
# @tp @b LIBEXEC @endtp
# Specifies that the built executable is an auxiliary executable which
# is only called by other executables. (default: @c FALSE) |
#
#
# @tp @b [NO]EXPORT @endtp
# Whether to export this target. (default: @c TRUE) |
#
#
# @tp @b NO_BASIS_UTILITIES @endtp
# Specify that the BASIS utilities are not used by this executable and hence
# no link dependency on the BASIS utilities library shall be added.
# (default: @c NOT @c BASIS_UTILITIES) |
#
#
# @tp @b USE_BASIS_UTILITIES @endtp
# Specify that the BASIS utilities are used and required by this executable
# and hence a link dependency on the BASIS utilities library has to be added.
# (default: @c BASIS_UTILITIES) |
#
#
#
# @returns Adds executable target using CMake's add_executable() command.
#
# @sa basis_add_executable()
function (basis_add_executable_target TARGET_NAME)
# check target name
basis_check_target_name (${TARGET_NAME})
basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
message (STATUS "Adding executable ${TARGET_UID}...")
# parse arguments
CMAKE_PARSE_ARGUMENTS (
ARGN
"USE_BASIS_UTILITIES;NO_BASIS_UTILITIES;EXPORT;NOEXPORT;LIBEXEC"
"COMPONENT;DESTINATION"
""
${ARGN}
)
set (SOURCES ${ARGN_UNPARSED_ARGUMENTS})
basis_set_flag (ARGN EXPORT ${BASIS_EXPORT_DEFAULT})
if (ARGN_USE_BASIS_UTILITIES AND ARGN_NO_BASIS_UTILITIES)
message (FATAL_ERROR "Target ${TARGET_UID}: Options USE_BASIS_UTILITIES and NO_BASIS_UTILITIES are mutually exclusive!")
endif ()
if (ARGN_USE_BASIS_UTILITIES)
set (USES_BASIS_UTILITIES TRUE)
elseif (ARGN_NO_BASIS_UTILITIES)
set (USES_BASIS_UTILITIES FALSE)
else ()
set (USES_BASIS_UTILITIES ${BASIS_UTILITIES})
endif ()
# IS_TEST flag
basis_sanitize_for_regex (RE "${PROJECT_TESTING_DIR}")
if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${RE}")
set (IS_TEST TRUE)
else ()
set (IS_TEST FALSE)
endif ()
# installation component
if (NOT ARGN_COMPONENT)
set (ARGN_COMPONENT "${BASIS_RUNTIME_COMPONENT}")
endif ()
if (NOT ARGN_COMPONENT)
set (ARGN_COMPONENT "Unspecified")
endif ()
# installation directory
if (ARGN_DESTINATION)
if (ARGN_DESTINATION MATCHES "^[nN][oO][nN][eE]$")
set (ARGN_DESTINATION)
elseif (IS_ABSOLUTE "${ARGN_DESTINATION}")
file (RELATIVE_PATH ARGN_DESTINATION "${CMAKE_INSTALL_PREFIX}" "${ARGN_DESTINATION}")
endif ()
elseif (ARGN_LIBEXEC)
set (ARGN_DESTINATION "${INSTALL_LIBEXEC_DIR}")
else ()
set (ARGN_DESTINATION "${INSTALL_RUNTIME_DIR}")
endif ()
# configure (.in) source files
basis_configure_sources (SOURCES ${SOURCES})
# add executable target
add_executable (${TARGET_UID} ${SOURCES})
basis_make_target_uid (HEADERS_TARGET headers)
if (TARGET "${HEADERS_TARGET}")
add_dependencies (${TARGET_UID} ${HEADERS_TARGET})
endif ()
basis_get_target_name (OUTPUT_NAME ${TARGET_UID})
set_target_properties (${TARGET_UID} PROPERTIES BASIS_TYPE "EXECUTABLE" LANGUAGE "CXX" OUTPUT_NAME "${OUTPUT_NAME}")
if (ARGN_LIBEXEC)
set_target_properties (${TARGET_UID} PROPERTIES LIBEXEC 1 COMPILE_DEFINITIONS LIBEXEC SCRIPT_DEFINITIONS LIBEXEC)
else ()
set_target_properties (${TARGET_UID} PROPERTIES LIBEXEC 0)
endif ()
set_target_properties (${TARGET_UID} PROPERTIES TEST ${IS_TEST})
# output directory
if (IS_TEST)
if (ARGN_LIBEXEC)
set_target_properties (${TARGET_UID} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_LIBEXEC_DIR}")
else ()
set_target_properties (${TARGET_UID} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_RUNTIME_DIR}")
endif ()
elseif (ARGN_LIBEXEC)
set_target_properties (${TARGET_UID} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BINARY_LIBEXEC_DIR}")
else ()
set_target_properties (${TARGET_UID} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BINARY_RUNTIME_DIR}")
endif ()
# installation directory
set_target_properties (${TARGET_UID} PROPERTIES RUNTIME_INSTALL_DIRECTORY "${ARGN_DESTINATION}")
# link to BASIS utilities
if (USES_BASIS_UTILITIES)
basis_target_link_libraries (.${TARGET_UID} basis)
else ()
set_target_properties (${TARGET_UID} PROPERTIES BASIS_UTILITIES FALSE)
endif ()
# export
set (EXPORT_OPT)
if (EXPORT)
basis_add_export_target (EXPORT_OPT ${TARGET_UID} "${IS_TEST}" ${ARGN_DESTINATION})
endif ()
# installation
if (ARGN_DESTINATION)
if (IS_TEST)
# TODO install (selected?) tests
else ()
install (
TARGETS ${TARGET_UID} ${EXPORT_OPT}
DESTINATION "${ARGN_DESTINATION}"
COMPONENT "${ARGN_COMPONENT}"
)
endif ()
endif ()
# done
message (STATUS "Adding executable ${TARGET_UID}... - done")
endfunction ()
# ----------------------------------------------------------------------------
## @brief Add library built from C++ source code.
#
# @note This function should not be used directly. Instead, it is called
# by basis_add_library() if the (detected) programming language
# of the given source code files is @c CXX (i.e., C/C++) and the
# option @c MEX is not given.
#
# This function adds a library target which builds a library from C++ source
# code files. Refer to the documentation of basis_add_library() for a
# description of the general options for adding a library target.
#
# By default, the BASIS C++ utilities library is added as link dependency.
# If none of the BASIS C++ utilities are used by this target, the option
# NO_BASIS_UTILITIES can be given. To enable this option by default, set the
# variable @c BASIS_UTILITIES to @c FALSE, best in the
#
# @tp STATIC|SHARED|MODULE @endtp
# Type of the library. (default: @c SHARED if @c BUILD_SHARED_LIBS
# evaluates to true or @c STATIC otherwise) |
#
#
# @tp @b COMPONENT name @endtp
# Name of component as part of which this library will be installed
# if either the @c RUNTIME_INSTALL_DIRECTORY or
# @c LIBRARY_INSTALL_DIRECTORY property is not "none". Used only if
# either @p RUNTIME_COMPONENT or @p LIBRARY_COMPONENT not specified.
# (default: see @p RUNTIME_COMPONENT and @p LIBRARY_COMPONENT) |
#
#
# @tp @b DESTINATION dir @endtp
# Installation directory for runtime and library component relative
# to @c CMAKE_INSTALL_PREFIX. Used only if either @p RUNTIME_DESTINATION
# or @p LIBRARY_DESTINATION not specified. If "none" (case-insensitive)
# is given as argument, no default installation rules are added.
# (default: see @p RUNTIME_DESTINATION and @p LIBRARY_DESTINATION) |
#
#
# @tp @b LIBRARY_COMPONENT name @endtp
# Name of component as part of which import/static library will be intalled
# if @c LIBRARY_INSTALL_DIRECTORY property is not "none".
# (default: @c COMPONENT if specified or @c BASIS_LIBRARY_COMPONENT otherwise) |
#
#
# @tp @b LIBRARY_DESTINATION dir @endtp
# Installation directory of the library component relative to
# @c CMAKE_INSTALL_PREFIX. If "none" (case-insensitive) is given as argument,
# no installation rule for the library component is added.
# (default: @c INSTALL_ARCHIVE_DIR) |
#
#
# @tp @b RUNTIME_COMPONENT name @endtp
# Name of component as part of which runtime library will be installed
# if @c RUNTIME_INSTALL_DIRECTORY property is not "none".
# (default: @c COMPONENT if specified or @c BASIS_RUNTIME_COMPONENT otherwise) |
#
#
# @tp @b RUNTIME_DESTINATION dir @endtp
# Installation directory of the runtime component relative to
# @c CMAKE_INSTALL_PREFIX. If "none" (case-insensitive) is given as argument,
# no installation rule for the runtime library is added.
# (default: @c INSTALL_LIBRARY_DIR on Unix or @c INSTALL_RUNTIME_DIR Windows) |
#
#
# @tp @b [NO]EXPORT @endtp
# Whether to export this target. (default: @c TRUE) |
#
#
# @tp @b NO_BASIS_UTILITIES @endtp
# Specify that the BASIS utilities are not used by this executable and hence
# no link dependency on the BASIS utilities library shall be added.
# (default: @c NOT BASIS_UTILITIES) |
#
#
# @tp @b USE_BASIS_UTILITIES @endtp
# Specify that the BASIS utilities are used and required by this executable
# and hence a link dependency on the BASIS utilities library shall be added.
# (default: @c BASIS_UTILITIES) |
#
#
#
# @returns Adds library target using CMake's add_library() command.
#
# @sa basis_add_library()
function (basis_add_library_target TARGET_NAME)
# On UNIX-based systems setting the VERSION property only creates
# annoying files with the version string as suffix.
# Moreover, MEX-files may NEVER have a suffix after the MEX extension!
# Otherwise, the MATLAB Compiler when using the symbolic link
# without this suffix will create code that fails on runtime
# with an .auth file missing error.
#
# Thus, do NOT set VERSION and SOVERSION properties on library targets!
# check target name
basis_check_target_name (${TARGET_NAME})
basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
# parse arguments
CMAKE_PARSE_ARGUMENTS (
ARGN
"STATIC;SHARED;MODULE;USE_BASIS_UTILITIES;NO_BASIS_UTILITIES;EXPORT;NOEXPORT"
"COMPONENT;RUNTIME_COMPONENT;LIBRARY_COMPONENT;DESTINATION;RUNTIME_DESTINATION;LIBRARY_DESTINATION"
""
${ARGN}
)
set (SOURCES ${ARGN_UNPARSED_ARGUMENTS})
basis_set_flag (ARGN EXPORT ${BASIS_EXPORT_DEFAULT})
if (ARGN_USE_BASIS_UTILITIES AND ARGN_NO_BASIS_UTILITIES)
message (FATAL_ERROR "Target ${TARGET_UID}: Options USE_BASIS_UTILITIES and NO_BASIS_UTILITIES are mutually exclusive!")
endif ()
if (ARGN_USE_BASIS_UTILITIES)
set (USES_BASIS_UTILITIES TRUE)
elseif (ARGN_NO_BASIS_UTILITIES)
set (USES_BASIS_UTILITIES FALSE)
else ()
set (USES_BASIS_UTILITIES ${BASIS_UTILITIES})
endif ()
# IS_TEST flag
basis_sanitize_for_regex (RE "${PROJECT_TESTING_DIR}")
if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${RE}")
set (IS_TEST TRUE)
else ()
set (IS_TEST FALSE)
endif ()
# library type
if (NOT ARGN_SHARED AND NOT ARGN_STATIC AND NOT ARGN_MODULE)
if (BUILD_SHARED_LIBS)
set (ARGN_SHARED TRUE)
else ()
set (ARGN_STATIC TRUE)
endif ()
endif ()
set (TYPE)
if (ARGN_STATIC)
if (TYPE)
message (FATAL_ERROR "More than one library type specified for target ${TARGET_UID}!")
endif ()
set (TYPE "STATIC")
endif ()
if (ARGN_SHARED)
if (TYPE)
message (FATAL_ERROR "More than one library type specified for target ${TARGET_UID}!")
endif ()
set (TYPE "SHARED")
endif ()
if (ARGN_MODULE)
if (TYPE)
message (FATAL_ERROR "More than one library type specified for target ${TARGET_UID}!")
endif ()
set (TYPE "MODULE")
endif ()
string (TOLOWER "${TYPE}" type)
# status message
message (STATUS "Adding ${type} library ${TARGET_UID}...")
# installation component
if (ARGN_COMPONENT)
if (NOT ARGN_RUNTIME_COMPONENT)
set (ARGN_RUNTIME_COMPONENT "${ARGN_COMPONENT}")
endif ()
if (NOT ARGN_LIBRARY_COMPONENT)
set (ARGN_LIBRARY_COMPONENT "${ARGN_COMPONENT}")
endif ()
endif ()
if (NOT ARGN_RUNTIME_COMPONENT)
set (ARGN_RUNTIME_COMPONENT "${BASIS_RUNTIME_COMPONENT}")
endif ()
if (NOT ARGN_RUNTIME_COMPONENT)
set (ARGN_RUNTIME_COMPONENT "Unspecified")
endif ()
if (NOT ARGN_LIBRARY_COMPONENT)
set (ARGN_LIBRARY_COMPONENT "${BASIS_LIBRARY_COMPONENT}")
endif ()
if (NOT ARGN_LIBRARY_COMPONENT)
set (ARGN_LIBRARY_COMPONENT "Unspecified")
endif ()
# installation directories
if (ARGN_DESTINATION)
if (NOT ARGN_STATIC AND NOT ARGN_RUNTIME_DESTINATION)
set (ARGN_RUNTIME_DESTINATION "${ARGN_DESTINATION}")
endif ()
if (NOT ARGN_LIBRARY_DESTINATION)
set (ARGN_LIBRARY_DESTINATION "${ARGN_DESTINATION}")
endif ()
endif ()
if (NOT ARGN_RUNTIME_DESTINATION)
set (ARGN_RUNTIME_DESTINATION "${INSTALL_RUNTIME_DIR}")
endif ()
if (NOT ARGN_LIBRARY_DESTINATION)
set (ARGN_LIBRARY_DESTINATION "${INSTALL_LIBRARY_DIR}")
endif ()
if (ARGN_STATIC OR ARGN_RUNTIME_DESTINATION MATCHES "^[nN][oO][nN][eE]$")
set (ARGN_RUNTIME_DESTINATION)
endif ()
if (ARGN_LIBRARY_DESTINATION MATCHES "^[nN][oO][nN][eE]$")
set (ARGN_LIBRARY_DESTINATION)
endif ()
# configure (.in) source files
basis_configure_sources (SOURCES ${SOURCES})
# add library target
add_library (${TARGET_UID} ${TYPE} ${SOURCES})
basis_make_target_uid (HEADERS_TARGET headers)
if (TARGET ${HEADERS_TARGET})
add_dependencies (${TARGET_UID} ${HEADERS_TARGET})
endif ()
basis_get_target_name (OUTPUT_NAME ${TARGET_UID})
set_target_properties (${TARGET_UID} PROPERTIES BASIS_TYPE "${TYPE}_LIBRARY" LANGUAGE "CXX" OUTPUT_NAME "${OUTPUT_NAME}")
# output directory
if (IS_TEST)
set_target_properties (
${TARGET_UID}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${TESTING_RUNTIME_DIR}"
LIBRARY_OUTPUT_DIRECTORY "${TESTING_LIBRARY_DIR}"
ARCHIVE_OUTPUT_DIRECTORY "${TESTING_ARCHIVE_DIR}"
)
else ()
set_target_properties (
${TARGET_UID}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${BINARY_RUNTIME_DIR}"
LIBRARY_OUTPUT_DIRECTORY "${BINARY_LIBRARY_DIR}"
ARCHIVE_OUTPUT_DIRECTORY "${BINARY_ARCHIVE_DIR}"
)
endif ()
# installation directory
# these properties are used by basis_get_target_location() in particular
set_target_properties (
${TARGET_UID}
PROPERTIES
RUNTIME_INSTALL_DIRECTORY "${ARGN_RUNTIME_DESTINATION}"
LIBRARY_INSTALL_DIRECTORY "${ARGN_LIBRARY_DESTINATION}"
ARCHIVE_INSTALL_DIRECTORY "${ARGN_LIBRARY_DESTINATION}"
)
# link to BASIS utilities
if (USES_BASIS_UTILITIES)
basis_target_link_libraries (.${TARGET_UID} basis)
else ()
set_target_properties (${TARGET_UID} PROPERTIES BASIS_UTILITIES FALSE)
endif ()
# export
set (EXPORT_OPT)
if (EXPORT)
basis_add_export_target (EXPORT_OPT ${TARGET_UID} "${IS_TEST}" ${ARGN_RUNTIME_DESTINATION} ${ARGN_LIBRARY_DESTINATION})
endif ()
# installation
set (DESTINATION_OPTS)
if (IS_TEST)
# TODO At the moment, no tests are installed. Once there is a way to
# install selected tests, the shared libraries they depend on
# need to be installed as well.
else ()
if (ARGN_RUNTIME_DESTINATION)
list (APPEND DESTINATION_OPTS
RUNTIME
DESTINATION "${ARGN_RUNTIME_DESTINATION}"
COMPONENT "${ARGN_RUNTIME_COMPONENT}"
)
endif ()
if (ARGN_LIBRARY_DESTINATION)
list (APPEND DESTINATION_OPTS
LIBRARY
DESTINATION "${ARGN_LIBRARY_DESTINATION}"
COMPONENT "${ARGN_LIBRARY_COMPONENT}"
ARCHIVE
DESTINATION "${ARGN_LIBRARY_DESTINATION}"
COMPONENT "${ARGN_LIBRARY_COMPONENT}"
)
endif ()
endif ()
if (DESTINATION_OPTS)
install (TARGETS ${TARGET_UID} ${EXPORT_OPT} ${DESTINATION_OPTS})
endif ()
# done
message (STATUS "Adding ${type} library ${TARGET_UID}... - done")
endfunction ()
# ----------------------------------------------------------------------------
## @brief Add script library target.
#
# @note This function should not be used directly. Instead, it is called
# by basis_add_library() if the (detected) programming language
# of the given source code files is neither @c CXX (i.e., C/C++) nor
# @c MATLAB.
#
# This function adds a build target for libraries which are a collection of
# one or more modules written in a scripting language. The relative paths
# of the modules relative to the library's @p SOURCE_DIRECTORY property are
# preserved. This is important for the most widely used scripting languages
# such as Python, Perl, or MATLAB, where the file path relative to the
# package root directory defines the package namespace.
#
# A custom CMake build target with the following properties is added by this
# function to the build system. These properties are used by
# basis_build_script_library() to generate a build script written in CMake
# code which is executed by a custom CMake command. Before the invokation of
# basis_build_script_library(), the target properties can be modified using
# basis_set_target_properties().
#
# @note Custom BASIS build targets are finalized by BASIS using basis_project_end(),
# i.e., the end of the root CMake configuration file of the (sub-)project.
#
# @par Properties on script library targets
#
#
# @tp @b BASIS_TYPE @endtp
# Read-only property with value "SCRIPT_LIBRARY" for script library targets. |
#
#
# @tp @b BASIS_UTILITIES @endtp
# Whether the BASIS utilities are used by any module of this library.
# For the supported scripting languages for which BASIS utilities are
# implemented, BASIS will in most cases automatically detect whether
# these utilities are used by a module or not. Otherwise, set this
# property manually or use either the @p USE_BASIS_UTILITIES or the
# @p NO_BASIS_UTILITIES option when adding the library target.
# (default: auto-detected or @c UNKNOWN) |
#
#
# @tp @b BINARY_DIRECTORY @endtp
# Build tree directory of this target. (default: @c CMAKE_CURRENT_BINARY_DIR) |
#
#
# @tp @b COMPILE @endtp
# Whether to compile the library, respectively, it's modules if the
# programming language allows such pre-compilation as in case of Python,
# for example. If @c TRUE, only the compiled files are installed.
# (default: @c BASIS_COMPILE_SCRIPTS) |
#
#
# @tp @b SCRIPT_DEFINITIONS @endtp
# CMake code which is evaluated after the inclusion of the default script
# configuration files. This code can be used to set the replacement text of the
# CMake variables ("@VAR@" patterns) used in the source files.
# See
# Build System Standard for details. (default: "") |
#
#
# @tp @b SCRIPT_DEFINITIONS_FILE @endtp
# CMake script file with compile definitions, also referred to as script
# configuration file. The named files are included after the default BASIS
# script configuration and before the @c SCRIPT_DEFINITIONS code is being
# evaluated. (default: @c BINARY_CONFIG_DIR/ScriptConfig.cmake) |
#
#
# @tp @b EXPORT @endtp
# Whether to export this build target in which case an import library
# target is added to the custom exports file with the path to the
# built/installed modules set as @c IMPORT_LOCATION. (default: @c TRUE) |
#
#
# @tp @b LANGUAGE @endtp
# Read-only property of programming language of modules in uppercase letters.
# (default: see @p LANGUAGE argument) |
#
#
# @tp @b LIBRARY_COMPONENT @endtp
# Name of component as part of which this library is installed if
# @c LIBRARY_INSTALL_DIRECTORY is not set to "none".
# (default: see @p COMPONENT argument) |
#
#
# @tp @b LIBRARY_INSTALL_DIRECTORY @endtp
# Installation directory of library configured for use in installation tree
# relative to @c CMAKE_INSTALL_PREFIX. Set to "none" (case-insensitive) to skip the
# addition of an installation rule.
# (default: INSTALL_<LANGUAGE>_LIBRARY_DIR if defined or
# @c INSTALL_LIBRARY_DIR otherwise) |
#
#
# @tp @b LIBRARY_OUTPUT_DIRECTORY @endtp
# Output directory of library configured for use within the build tree.
# (default: BINARY_<LANGUAGE>_LIBRARY_DIR if defined or
# @c BINARY_LIBRARY_DIR otherwise) |
#
#
# @tp @b LINK_DEPENDS @endtp
# Paths or target names of script modules and libraries used by this script.
# For each listed build target, a dependency is added between this
# library target and the named build targets. Use basis_target_link_libraries()
# to add additional link dependencies. Further note that if this library is
# a link dependency of an executable script added by basis_add_executable()
# (i.e., basis_add_script() actually), the link dependencies of this library
# are inherited by the executable script.
# (default: BASIS utilities module if used or empty list otherwise) |
#
#
# @tp @b PREFIX @endtp
# Common module prefix. The given directory path is appended to both
# @c LIBRAR_OUTPUT_DIRECTORY and @c LIBRARY_INSTALL_DIRECTORY and can,
# for example, be used to install modules of a Python package as part of
# another Python package, where @c LIBRARY_OUTPUT_DIRECTORY or
# @c LIBRARY_INSTALL_DIRECTORY, respectively, is the directory of the
# main package which is added to the @c PYTHONPATH. Possibly missing
# __init__.py files in case of Python are generated by the _initpy target
# which is automatically added by BASIS in that case and further added to
# the dependencies of this library target.
# (default: @c PROJECT_NAMESPACE_PYTHON if @c LANGUAGE is @c PYTHON with
# periods (.) replaced by slashes (/), @c PROJECT_NAMESPACE_PERL if
# @c LANGUAGE is @c PERL with :: replaced by slashes (/),
# and "" otherwise) |
#
#
# @tp @b SOURCE_DIRECTORY @endtp
# Source directory of this target. This directory is in particular
# used to convert the paths of the given source files to relative paths.
# The built modules within the build and installation tree will have the
# same relative path (relative to the @c LIBRARY_OUTPUT_DIRECTORY or
# @c LIBRARY_INSTALL_DIRECTORY, respectively).
# (default: @c CMAKE_CURRENT_SOURCE_DIR) |
#
#
# @tp @b SOURCES @endtp
# Read-only property which lists the source files of this library.
# Note that the first element in this list actually names a directory
# in the build, the one where the build script for this target is located
# instead of a source file and thus should be ignored. |
#
#
#
# @attention Properties documented as read-only must not be modified.
#
# @param [in] TARGET_NAME Name of build target.
# @param [in] ARGN The remaining arguments are parsed and the following
# arguments extracted. All unparsed arguments are treated
# as the module files of the script library.
# @par
#
#
# @tp @b COMPONENT name @endtp
# Name of installation component as part of which this library is being
# installed if the @c LIBRARY_INSTALL_DIRECTORY property is not "none".
# (default: @c BASIS_LIBRARY_COMPONENT) |
#
#
# @tp @b DESTINATION dir @endtp
# Installation directory for library relative to @c CMAKE_INSTALL_PREFIX.
# If an absolute path is given as argument, it is made relative to the
# configured installation prefix. (default: @c INSTALL_LIBRARY_DIR) |
#
#
# @tp @b LANGUAGE lang @endtp
# Programming language in which modules are written (case-insensitive).
# If not specified, the programming language is derived from the file name
# extensions of the source files and the shebang directive on the first line
# of each module if any. If the programming language could not be detected
# automatically, the @c LANGUAGE property is set to @c UNKNOWN. Note that
# for script library targets, the library may still be built correctly
# even if the scripting language was not recognized. The automatic detection
# whether the BASIS utilities are used and required will fail, however.
# In this case, specify the programming language using this option.
# (default: auto-detected or @c UNKNOWN) |
#
#
# @tp @b [NO]EXPORT @endtp
# Whether to export this target. (default: @c TRUE) |
#
#
# @tp @b NO_BASIS_UTILITIES @endtp
# Specify that the BASIS utilities are not used by this library. If the
# programming language of the modules is known and BASIS utilities are
# available for this language, BASIS will in most cases automatically
# detect whether these utilities are used by any module of this library.
# Use this option to skip this check in the case that no module makes
# use of the BASIS utilities. |
#
#
# @tp @b USE_BASIS_UTILITIES @endtp
# Specify that the BASIS utilities are used and thus required by this library.
# If the programming language of the modules is known and BASIS utilities are
# available for this language, BASIS will in most cases automatically
# detect whether these utilities are used by any module of this library.
# Use this option to skip this check when it is already known that no module
# makes use of the BASIS utilities. Note that an error is raised if this option
# is given, but no BASIS utilities are available for the programming language
# of this script or if the programming language is unknown, respectively, not
# detected correctly. In this case, consider the use of the @p LANGUAGE argument. |
#
#
#
# @returns Adds a custom CMake target with the documented properties. The actual custom
# command to build the library is added by basis_build_script_library().
#
# @sa basis_add_library()
function (basis_add_script_library TARGET_NAME)
# check target name
basis_check_target_name ("${TARGET_NAME}")
basis_make_target_uid (TARGET_UID "${TARGET_NAME}")
message (STATUS "Adding script library ${TARGET_UID}...")
# dump CMake variables for configuration of script
set (BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TARGET_UID}")
basis_dump_variables ("${BUILD_DIR}.dir/cache.cmake.tmp")
# parse arguments
CMAKE_PARSE_ARGUMENTS (
ARGN
"NO_BASIS_UTILITIES;USE_BASIS_UTILITIES;EXPORT;NOEXPORT"
"COMPONENT;DESTINATION;LANGUAGE"
""
${ARGN}
)
basis_set_flag (ARGN EXPORT ${BASIS_EXPORT_DEFAULT})
set (SOURCES "${ARGN_UNPARSED_ARGUMENTS}")
# IS_TEST flag
basis_sanitize_for_regex (RE "${PROJECT_TESTING_DIR}")
if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${RE}")
set (IS_TEST TRUE)
else ()
set (IS_TEST FALSE)
endif ()
# check source files
set (_SOURCES)
foreach (S IN LISTS SOURCES)
get_filename_component (S "${S}" ABSOLUTE)
if (NOT EXISTS "${S}" AND NOT S MATCHES "\\.in$" AND EXISTS "${S}.in" AND NOT IS_DIRECTORY "${S}.in")
set (S "${S}.in")
elseif (IS_DIRECTORY "${S}")
message (FATAL_ERROR "Target ${TARGET_UID}: Directory ${S} given where file name expected!")
endif ()
if (NOT EXISTS "${S}")
string (REGEX REPLACE "\\.in$" "" S "${S}")
message (FATAL_ERROR "Target ${TARGET_UID}: Source file ${S}[.in] does not exist!")
endif ()
list (APPEND _SOURCES "${S}")
endforeach ()
if (NOT _SOURCES)
message (FATAL_ERROR "Target ${TARGET_UID}: No source files specified!")
endif ()
set (SOURCES "${_SOURCES}")
unset (_SOURCES)
# auto-detect programming language (may be as well UNKNOWN)
string (TOUPPER "${ARGN_LANGUAGE}" ARGN_LANGUAGE)
if (NOT ARGN_LANGUAGE)
basis_get_source_language (ARGN_LANGUAGE ${SOURCES})
if (ARGN_LANGUAGE MATCHES "AMBIGUOUS|UNKNOWN")
message (FATAL_ERROR "Target ${TARGET_UID}: Failed to determine programming"
" language of modules! Make sure that all modules are"
" written in the same language and that the used programming"
" language is supported by BASIS, i.e., either Python (Jython),"
" Perl, Bash, or MATLAB. Otherwise, try to specify the language"
" explicitly using the LANGUAGE option.")
endif ()
endif ()
# output directory
if (IS_TEST)
if (DEFINED TESTING_${ARGN_LANGUAGE}_LIBRARY_DIR)
set (OUTPUT_DIRECTORY "${TESTING_${ARGN_LANGUAGE}_LIBRARY_DIR}")
else ()
set (OUTPUT_DIRECTORY "${TESTING_LIBRARY_DIR}")
endif ()
else ()
if (DEFINED BINARY_${ARGN_LANGUAGE}_LIBRARY_DIR)
set (OUTPUT_DIRECTORY "${BINARY_${ARGN_LANGUAGE}_LIBRARY_DIR}")
else ()
set (OUTPUT_DIRECTORY "${BINARY_LIBRARY_DIR}")
endif ()
endif ()
# installation component
if (NOT ARGN_COMPONENT)
set (ARGN_COMPONENT "${BASIS_LIBRARY_COMPONENT}")
endif ()
if (NOT ARGN_COMPONENT)
set (ARGN_COMPONENT "Unspecified")
endif ()
# installation directory
if (IS_TEST)
if (ARGN_DESTINATION)
message (WARNING "Target ${TARGET_UID} is a library used for testing only."
" Installation to the specified directory will be skipped.")
set (ARGN_DESTINATION)
endif ()
else ()
if (ARGN_DESTINATION)
if (IS_ABSOLUTE "${ARGN_DESTINATION}")
file (RELATIVE_PATH ARGN_DESTINATION "${CMAKE_INSTALL_PREFIX}" "${ARGN_DESTINATION}")
endif ()
else ()
if (DEFINED INSTALL_${ARGN_LANGUAGE}_LIBRARY_DIR)
set (ARGN_DESTINATION "${INSTALL_${ARGN_LANGUAGE}_LIBRARY_DIR}")
else ()
set (ARGN_DESTINATION "${INSTALL_LIBRARY_DIR}")
endif ()
endif ()
endif ()
# common module prefix
if (ARGN_LANGUAGE MATCHES "^([JP]YTHON|PERL|MATLAB|BASH)$")
basis_library_prefix (PREFIX ${ARGN_LANGUAGE})
else ()
set (PREFIX)
endif ()
# script configuration ("compile definitions")
if (EXISTS "${BINARY_CONFIG_DIR}/ScriptConfig.cmake")
set (CONFIG_FILE "${BINARY_CONFIG_DIR}/ScriptConfig.cmake")
else ()
set (CONFIG_FILE)
endif ()
# auto-detect use of BASIS utilities
if (ARGN_LANGUAGE MATCHES "[JP]YTHON")
set (UTILITIES_LANGUAGE "PYTHON")
else ()
set (UTILITIES_LANGUAGE "${ARGN_LANGUAGE}")
endif ()
if (ARGN_USE_BASIS_UTILITIES)
if (NOT BASIS_UTILITIES_ENABLED MATCHES "${UTILITIES_LANGUAGE}")
message (FATAL_ERROR "Target ${TARGET_UID} requires the BASIS utilities for ${UTILITIES_LANGUAGE}"
" but BASIS was either build without the build of these utilities enabled"
" or no utilities for this programming language are implemented. Remove the"
" USE_BASIS_UTILITIES option if no BASIS utilities are used by the modules"
" of the library or specify the correct programming language if it was not"
" detected correctly.")
endif ()
set (USES_BASIS_UTILITIES TRUE)
elseif (BASIS_UTILITIES AND NOT ARGN_NO_BASIS_UTILITIES AND NOT UTILITIES_LANGUAGE MATCHES "UNKNOWN")
set (USES_BASIS_UTILITIES FALSE)
foreach (M IN LISTS SOURCES)
basis_utilities_check (USES_BASIS_UTILITIES "${M}" ${UTILITIES_LANGUAGE})
if (USES_BASIS_UTILITIES)
break ()
endif ()
endforeach ()
else ()
set (USES_BASIS_UTILITIES FALSE)
endif ()
# add custom target
add_custom_target (${TARGET_UID} ALL SOURCES ${SOURCES})
set_target_properties (
${TARGET_UID}
PROPERTIES
LANGUAGE "${ARGN_LANGUAGE}"
BASIS_TYPE "SCRIPT_LIBRARY"
BASIS_UTILITIES "${USES_BASIS_UTILITIES}"
BUILD_DIRECTORY "${BUILD_DIR}"
SOURCE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
BINARY_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
LIBRARY_OUTPUT_DIRECTORY "${OUTPUT_DIRECTORY}"
LIBRARY_INSTALL_DIRECTORY "${ARGN_DESTINATION}"
LIBRARY_COMPONENT "${BASIS_LIBRARY_COMPONENT}"
PREFIX "${PREFIX}"
SCRIPT_DEFINITIONS ""
SCRIPT_DEFINITIONS_FILE "${CONFIG_FILE}"
LINK_DEPENDS ""
EXPORT "${EXPORT}"
COMPILE "${BASIS_COMPILE_SCRIPTS}"
TEST "${IS_TEST}"
)
# link to BASIS utilities
if (USES_BASIS_UTILITIES)
basis_target_link_libraries (.${TARGET_UID} basis)
if (BASIS_DEBUG)
message ("** Target ${TARGET_UID} uses the BASIS utilities for ${UTILITIES_LANGUAGE}.")
endif ()
endif ()
# add target to list of targets
basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET_UID}")
message (STATUS "Adding script library ${TARGET_UID}... - done")
endfunction ()
# ============================================================================
# custom build commands
# ============================================================================
# ----------------------------------------------------------------------------
## @brief Finalize custom targets by adding the missing build commands.
#
# This function is called by basis_project_end() in order to finalize the
# addition of the custom build targets such as, for example, build targets
# for the build of executable scripts, Python packages, MATLAB Compiler
# executables and shared libraries, and MEX-files.
#
# @returns Generates the CMake build scripts and adds custom build commands
# and corresponding targets for the execution of these scripts.
#
# @sa basis_build_script()
# @sa basis_build_script_library()
# @sa basis_build_mcc_target()
# @sa basis_build_mex_file()
function (basis_finalize_targets)
basis_get_project_property (TARGETS PROPERTY TARGETS)
foreach (TARGET_UID ${TARGETS})
if (NOT TARGET _${TARGET_UID})
get_target_property (BASIS_TYPE ${TARGET_UID} BASIS_TYPE)
if (BASIS_TYPE MATCHES "^EXECUTABLE$|^(SHARED|MODULE)_LIBRARY$")
if (BASIS_INSTALL_RPATH AND NOT CMAKE_SKIP_RPATH)
# Only if BASIS is allowed to take care of the INSTALL_RPATH property
# and the use of this property was not disabled by the project
basis_set_target_install_rpath (${TARGET_UID})
endif ()
elseif (BASIS_TYPE MATCHES "SCRIPT_LIBRARY")
basis_build_script_library (${TARGET_UID})
elseif (BASIS_TYPE MATCHES "SCRIPT")
basis_build_script (${TARGET_UID})
elseif (BASIS_TYPE MATCHES "MEX")
basis_build_mex_file (${TARGET_UID})
elseif (BASIS_TYPE MATCHES "MCC")
basis_build_mcc_target (${TARGET_UID})
endif ()
endif ()
endforeach ()
endfunction ()
# ----------------------------------------------------------------------------
## @brief Set INSTALL_RPATH property of executable or shared library target.
#
# This function sets the @c INSTALL_RPATH property of a specified executable or
# shared library target using the @c LINK_DEPENDS obtained using the
# basis_get_target_link_libraries() function. It determines the installation
# location of each dependency using the basis_get_target_location() function.
#
# @returns Sets the @c INSTALL_RPATH property of the specified target.
#
# @sa basis_get_target_link_libraries()
function (basis_set_target_install_rpath TARGET_NAME)
basis_get_target_uid (TARGET_UID "${TARGET_NAME}")
if (BASIS_VERBOSE)
message (STATUS "Setting INSTALL_RPATH property of ${TARGET_UID}...")
endif ()
if (NOT TARGET "${TARGET_UID}")
message (FATAL_ERROR "Unknown target: ${TARGET_UID}")
endif ()
if (BASIS_DEBUG)
message ("** basis_set_target_install_rpath():")
message ("** TARGET_NAME: ${TARGET_UID}")
endif ()
if (CMAKE_HOST_APPLE)
set (ORIGIN "@loader_path")
else ()
set (ORIGIN "\$ORIGIN")
endif ()
# always prefer libraries located within the same directory
set (INSTALL_RPATH "${ORIGIN}/.")
# common default RPATH (rarely used)
if (CMAKE_INSTALL_RPATH)
set (INSTALL_RPATH "${INSTALL_RPATH};${CMAKE_INSTALL_RPATH}")
endif ()
# get location of target used to make paths relative to this $ORIGIN
basis_get_target_location (TARGET_LOCATION ${TARGET_UID} POST_INSTALL_PATH)
# directories of external projects belonging to same bundle which
# were added using [basis_]link_directories() command
basis_get_project_property (BUNDLE_LINK_DIRS PROPERTY BUNDLE_LINK_DIRS)
foreach (LINK_DIR ${BUNDLE_LINK_DIRS})
list (FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${LINK_DIR}" IDX)
if (IDX EQUAL -1)
if (BASIS_DEBUG AND BASIS_VERBOSE)
message ("** BUNDLE_LINK_DIR: ${LINK_DIR}")
endif ()
basis_get_relative_path (RPATH "${TARGET_LOCATION}" "${LINK_DIR}")
list (APPEND INSTALL_RPATH "${ORIGIN}/${RPATH}")
endif ()
endforeach ()
# directories of link libraries
#
# only the libraries of this project and targets imported
# from other projects which are part of the same bundle
basis_get_target_link_libraries (LINK_DEPENDS ${TARGET_UID})
if (BASIS_DEBUG AND BASIS_VERBOSE)
message ("** LINK_DEPENDS: [${LINK_DEPENDS}]")
endif ()
foreach (LINK_DEPEND ${LINK_DEPENDS})
set (DEPEND_LOCATION)
if (TARGET "${LINK_DEPEND}")
basis_get_target_property (BUNDLED ${LINK_DEPEND} BUNDLED)
basis_get_target_property (IMPORTED ${LINK_DEPEND} IMPORTED)
if (NOT IMPORTED OR BUNDLED)
basis_get_target_location (DEPEND_LOCATION ${LINK_DEPEND} POST_INSTALL_PATH)
if (BASIS_DEBUG AND BASIS_VERBOSE)
message ("** LOCATION(${LINK_DEPEND}): ${DEPEND_LOCATION}")
endif ()
endif ()
elseif (IS_ABSOLUTE "${LINK_DEPEND}")
if (IS_DIRECTORY "${LINK_DEPEND}")
set (DEPEND_LOCATION "${LINK_DEPEND}")
else ()
get_filename_component (DEPEND_LOCATION "${LINK_DEPEND}" PATH)
endif ()
list (FIND BUNDLE_LINK_DIRS "${DEPEND_LOCATION}" IDX)
if (IDX EQUAL -1)
set (DEPEND_LOCATION)
endif ()
endif ()
if (DEPEND_LOCATION)
list (FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${DEPEND_LOCATION}" IDX)
if (IDX EQUAL -1)
basis_get_relative_path (RPATH "${TARGET_LOCATION}" "${DEPEND_LOCATION}")
list (APPEND INSTALL_RPATH "${ORIGIN}/${RPATH}")
endif ()
endif ()
endforeach ()
# remove duplicates
if (INSTALL_RPATH)
list (REMOVE_DUPLICATES INSTALL_RPATH)
endif ()
# set INSTALL_RPATH property
set_target_properties (${TARGET_UID} PROPERTIES INSTALL_RPATH "${INSTALL_RPATH}")
if (BASIS_DEBUG)
message ("** INSTALL_RPATH: [${INSTALL_RPATH}]")
endif ()
if (BASIS_VERBOSE)
message (STATUS "Setting INSTALL_RPATH property of ${TARGET_UID}... - done")
endif ()
endfunction ()
# ----------------------------------------------------------------------------
## @brief Add custom command for build of single script.
#
# This function is called by basis_finalize_targets() which in turn is called
# by basis_project_end(), i.e., the end of the root CMake configuration file
# of the (sub-)project.
#
# @param [in] TARGET_UID Name/UID of custom target added by basis_add_script().
#
# @sa basis_add_script()
function (basis_build_script TARGET_UID)
# does this target exist ?
basis_get_target_uid (TARGET_UID "${TARGET_UID}")
if (NOT TARGET "${TARGET_UID}")
message (FATAL_ERROR "Unknown build target: ${TARGET_UID}")
endif ()
if (BASIS_VERBOSE)
message (STATUS "Adding build command for target ${TARGET_UID}...")
endif ()
# get target properties
basis_get_target_link_libraries (LINK_DEPENDS ${TARGET_UID}) # paths of script modules/packages
# including BASIS utilities if used
set (
PROPERTIES
LANGUAGE # programming language of script
BASIS_TYPE # must match "^SCRIPT_(EXECUTABLE|LIBEXEC|MODULE)$"
BUILD_DIRECTORY # CMakeFiles build directory
SOURCE_DIRECTORY # CMake source directory
BINARY_DIRECTORY # CMake binary directory
OUTPUT_DIRECTORY # output directory for built script
INSTALL_DIRECTORY # installation directory for built script
COMPONENT # installation component
OUTPUT_NAME # name of built script including extension (if any)
PREFIX # name prefix
SUFFIX # name suffix (e.g., extension for executable script)
SCRIPT_DEFINITIONS # CMake code to set variables used to configure script
SCRIPT_DEFINITIONS_FILE # script configuration file
EXPORT # whether this target shall be exported
COMPILE # whether to compile script if applicable
SOURCES # path of script source file
)
get_target_property (IS_TEST ${TARGET_UID} TEST) # whether this script is used for testing only
foreach (PROPERTY ${PROPERTIES})
get_target_property (${PROPERTY} ${TARGET_UID} ${PROPERTY})
endforeach ()
set (EXECUTABLE FALSE)
set (LIBEXEC FALSE)
set (MODULE FALSE)
if (BASIS_TYPE MATCHES "^SCRIPT_(EXECUTABLE|LIBEXEC|MODULE)$")
set (${CMAKE_MATCH_1} TRUE)
if (LIBEXEC)
set (EXECUTABLE TRUE)
endif ()
else ()
message (FATAL_ERROR "Target ${TARGET_UID}: Unexpected BASIS_TYPE: ${BASIS_TYPE}")
endif ()
if (NOT BINARY_DIRECTORY)
message (FATAL_ERROR "Target ${TARGET_UID}: Missing BINARY_DIRECTORY property!")
endif ()
file (RELATIVE_PATH _relpath "${CMAKE_BINARY_DIR}" "${BINARY_DIRECTORY}")
if (_relpath MATCHES "^\\.\\./")
message (FATAL_ERROR "Target ${TARGET_UID}: BINARY_DIRECTORY must be inside of build tree!")
endif ()
unset (_relpath)
if (INSTALL_DIRECTORY AND NOT COMPONENT)
set (COMPONENT "Unspecified")
endif ()
list (GET SOURCES 0 BUILD_DIR) # CMake <3.1 stores path to internal build directory here
if (BUILD_DIR MATCHES "CMakeFiles")
list (REMOVE_AT SOURCES 0)
endif ()
list (LENGTH SOURCES L)
if (NOT L EQUAL 1)
message (FATAL_ERROR "Target ${TARGET_UID}: Expected one element in SOURCES list!"
" Have you modified this (read-only) property or is your"
" (newer) CMake version not compatible with BASIS?")
endif ()
set (SOURCE_FILE "${SOURCES}")
set (BUILD_DIR "${BUILD_DIRECTORY}.dir")
# output directory and name
if (NOT OUTPUT_NAME)
basis_get_target_name (OUTPUT_NAME ${TARGET_UID})
endif ()
if (PREFIX)
set (OUTPUT_NAME "${PREFIX}${OUTPUT_NAME}")
endif ()
if (SUFFIX)
set (OUTPUT_NAME "${OUTPUT_NAME}${SUFFIX}")
endif ()
if (CMAKE_GENERATOR MATCHES "Visual Studio|Xcode")
set (OUTPUT_FILE "${BUILD_DIR}/build/${OUTPUT_NAME}")
set (OUTPUT_DIR "${OUTPUT_DIRECTORY}/$