MatlabTools.cmake
Go to the documentation of this file.
00001 ############################################################################## 00002 # @file MatlabTools.cmake 00003 # @brief Enables use of MATLAB Compiler and build of MEX-files. 00004 # 00005 # Copyright (c) 2011, 2012, 2013 University of Pennsylvania. All rights reserved.<br /> 00006 # See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file. 00007 # 00008 # Contact: SBIA Group <sbia-software at uphs.upenn.edu> 00009 # 00010 # @ingroup CMakeTools 00011 ############################################################################## 00012 00013 if (__BASIS_MATLABTOOLS_INCLUDED) 00014 return () 00015 else () 00016 set (__BASIS_MATLABTOOLS_INCLUDED TRUE) 00017 endif () 00018 00019 00020 # ============================================================================ 00021 # modules 00022 # ============================================================================ 00023 00024 # Note: Required because generate_matlab_executable.cmake uses this module. 00025 00026 include (CMakeParseArguments) 00027 include ("${CMAKE_CURRENT_LIST_DIR}/CommonTools.cmake") 00028 include ("${CMAKE_CURRENT_LIST_DIR}/UtilitiesTools.cmake") 00029 00030 # ============================================================================ 00031 # options 00032 # ============================================================================ 00033 00034 ## @addtogroup BasisSettings 00035 # @{ 00036 00037 00038 ## @brief Enable/Disable compilation of MATLAB sources if the MATLAB Compiler is available. 00039 option (BASIS_COMPILE_MATLAB "Enable compilation of MATLAB sources if MATLAB Compiler (mcc) is available." ON) 00040 00041 ## @brief Enable/Disable invocation of MATLAB Compiler in MATLAB mode. 00042 option ( 00043 BASIS_MCC_MATLAB_MODE 00044 "Prefer MATLAB mode over standalone mode to invoke MATLAB Compiler." 00045 "ON" # prefer as it releases the license immediately once done 00046 ) 00047 00048 mark_as_advanced (BASIS_COMPILE_MATLAB) 00049 mark_as_advanced (BASIS_MCC_MATLAB_MODE) 00050 00051 00052 ## @} 00053 # end of Doxygen group 00054 00055 00056 # ============================================================================ 00057 # build configuration 00058 # ============================================================================ 00059 00060 ## @addtogroup BasisSettings 00061 # @{ 00062 00063 00064 ## @brief Compile flags used to build MATLAB Compiler targets. 00065 set ( 00066 BASIS_MCC_FLAGS 00067 "-R -singleCompThread" 00068 CACHE STRING 00069 "Common MATLAB Compiler flags (separated by ' '; use '\\' to mask ' ')." 00070 ) 00071 00072 ## @brief Compile flags used to build MEX-files using the MEX script. 00073 set ( 00074 BASIS_MEX_FLAGS 00075 "" 00076 CACHE STRING 00077 "Common MEX switches (separated by ' '; use '\\' to mask ' ')." 00078 ) 00079 00080 ## @brief Timeout for building MATLAB Compiler targets. 00081 set (BASIS_MCC_TIMEOUT "1800" CACHE STRING "Timeout for MATLAB Compiler execution") 00082 ## @brief Maximum number of retries on MATLAB Compiler license checkout. 00083 set (BASIS_MCC_RETRY_ATTEMPTS "4" CACHE STRING "Maximum number of retries on MATLAB Compiler license checkout error.") 00084 ## @brief Delay between retries to build MATLAB Compiler compiled targets on license checkout errors. 00085 set (BASIS_MCC_RETRY_DELAY "30" CACHE STRING "Delay between retries to build MATLAB Compiler compiled targets on license checkout error.") 00086 ## @brief Timeout for building MEX-file targets. 00087 set (BASIS_MEX_TIMEOUT "600" CACHE STRING "Timeout for MEX script execution") 00088 00089 mark_as_advanced (BASIS_MCC_FLAGS) 00090 mark_as_advanced (BASIS_MCC_TIMEOUT) 00091 mark_as_advanced (BASIS_MCC_RETRY_ATTEMPTS) 00092 mark_as_advanced (BASIS_MCC_RETRY_DELAY) 00093 mark_as_advanced (BASIS_MEX_FLAGS) 00094 mark_as_advanced (BASIS_MEX_TIMEOUT) 00095 00096 00097 ## @} 00098 # end of Doxygen group 00099 00100 00101 # ============================================================================ 00102 # utilities 00103 # ============================================================================ 00104 00105 # ---------------------------------------------------------------------------- 00106 ## @brief Determine version of MATLAB installation. 00107 # 00108 # @param [out] VERSION Value returned by the "version" command of MATLAB or 00109 # an empty string if execution of MATLAB failed. 00110 # 00111 # @returns Sets the variable named by @p VERSION to the full MATLAB version. 00112 # 00113 # @ingroup CMakeUtilities 00114 function (basis_get_full_matlab_version VERSION) 00115 if (NOT MATLAB_EXECUTABLE) 00116 set (${VERSION} "" PARENT_SCOPE) 00117 return () 00118 endif () 00119 set (WORKING_DIR "${CMAKE_BINARY_DIR}/CMakeFiles") 00120 set (OUTPUT_FILE "${WORKING_DIR}/MatlabVersion.txt") 00121 # read MATLAB version from existing output file 00122 set (_MATLAB_VERSION) 00123 if (EXISTS "${OUTPUT_FILE}") 00124 file (READ "${OUTPUT_FILE}" LINES) 00125 string (REGEX REPLACE "\n" ";" LINES "${LINES}") 00126 string (REGEX REPLACE "^;|;$" "" LINES "${LINES}") 00127 list (LENGTH LINES NLINES) 00128 if (NLINES EQUAL 2) 00129 list (GET LINES 0 _MATLAB_EXECUTABLE) 00130 list (GET LINES 1 _MATLAB_VERSION) 00131 basis_sanitize_for_regex (RE "${MATLAB_EXECUTABLE}") 00132 if (NOT _MATLAB_EXECUTABLE MATCHES "^${RE}$") 00133 set (_MATLAB_VERSION) 00134 endif () 00135 unset (RE) 00136 endif () 00137 endif () 00138 # run matlab command to write return value of "version" command to text file 00139 if (NOT _MATLAB_VERSION) 00140 message (STATUS "Determining MATLAB version...") 00141 set (CMD "${MATLAB_EXECUTABLE}" -nodesktop -nosplash -nojvm -singleCompThread) 00142 if (WIN32) 00143 list (APPEND CMD -automation) 00144 endif () 00145 # The following direct command works on Mac OS, but not Cent OS Linux because 00146 # of the surrounding double quotes which are needed on Mac OS, but not Linux. 00147 # Therefore, write MATLAB script first to file and execute it in order to 00148 # have the same CMake code on all platforms. Furthermore, if the quotes might 00149 # no longer be required also on Mac OS, we do not have to worry about it here. 00150 # -schuha 00151 #list (APPEND CMD -r "\"fid = fopen('${OUTPUT_FILE}', 'w'), [...], fclose(fid), quit force\"") 00152 list (APPEND CMD "-r" basis_get_full_matlab_version) 00153 file (WRITE "${WORKING_DIR}/basis_get_full_matlab_version.m" 00154 "% DO NOT EDIT. Automatically created by BASIS (basis_get_full_matlab_version). 00155 fid = fopen ('${OUTPUT_FILE}', 'w') 00156 if fid == -1, fprintf(2, '??? Error: Failed to open file ${OUTPUT_FILE} for writing!'), quit force, end 00157 fprintf (fid, '${MATLAB_EXECUTABLE}\\n%s\\n', version) 00158 fclose (fid) 00159 quit force 00160 " 00161 ) 00162 execute_process ( 00163 COMMAND ${CMD} 00164 WORKING_DIRECTORY "${WORKING_DIR}" 00165 RESULT_VARIABLE RETVAL 00166 TIMEOUT 600 # MATLAB startup can be *very* slow the first time 00167 ERROR_VARIABLE STDERR 00168 OUTPUT_QUIET 00169 ) 00170 if (NOT RETVAL EQUAL 0 OR STDERR MATCHES "\\?\\?\\? Error") 00171 set (${VERSION} "" PARENT_SCOPE) 00172 if (RETVAL MATCHES "timeout") 00173 set (REASON ": ${RETVAL}") 00174 elseif (NOT RETVAL EQUAL 0) 00175 set (REASON " with exit code: ${RETVAL}") 00176 else () 00177 set (REASON ": Failed to open file ${OUTPUT_FILE} for writing") 00178 endif () 00179 message (STATUS "Determining MATLAB version... - failed${REASON}") 00180 return () 00181 endif () 00182 # read MATLAB version from text file 00183 file (READ "${OUTPUT_FILE}" LINES) 00184 string (REGEX REPLACE "\n" ";" LINES "${LINES}") 00185 string (REGEX REPLACE "^;|;$" "" LINES "${LINES}") 00186 list (LENGTH LINES NLINES) 00187 if (NLINES EQUAL 2) 00188 list (GET LINES 1 _MATLAB_VERSION) 00189 else () 00190 set (${VERSION} "" PARENT_SCOPE) 00191 message (STATUS "Determining MATLAB version... - failed") 00192 return () 00193 endif () 00194 if (BASIS_VERBOSE) 00195 message (STATUS "Determining MATLAB version... - done: ${_MATLAB_VERSION}") 00196 else () 00197 message (STATUS "Determining MATLAB version... - done") 00198 endif () 00199 endif () 00200 # return 00201 set (${VERSION} "${_MATLAB_VERSION}" PARENT_SCOPE) 00202 endfunction () 00203 00204 # ---------------------------------------------------------------------------- 00205 ## @brief Get version of MATLAB installation. 00206 # 00207 # @param [out] ARGV1 If given, the named variable is set to the version string 00208 # ("<major>.<minor>.<patch>") of the MATLAB installation. 00209 # Otherwise, the variables @c MATLAB_VERSION_STRING, 00210 # @c MATLAB_VERSION_MAJOR, @c MATLAB_VERSION_MINOR, 00211 # @c MATLAB_VERSION_PATCH, and @c MATLAB_RELEASE are set 00212 # in the scope of the caller. 00213 # 00214 # @ingroup CMakeUtilities 00215 function (basis_get_matlab_version) 00216 if (ARGC GREATER 1) 00217 message (FATAL_ERROR "basis_get_matlab_version(): Too many arguments!") 00218 endif () 00219 basis_get_full_matlab_version (VERSION) 00220 if (VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)") 00221 set (VERSION_STRING "${CMAKE_MATCH_0}") 00222 set (VERSION_MAJOR "${CMAKE_MATCH_1}") 00223 set (VERSION_MINOR "${CMAKE_MATCH_2}") 00224 set (VERSION_PATCH "${CMAKE_MATCH_3}") 00225 else () 00226 set (VERSION_STRING "0.0") 00227 set (VERSION_MAJOR "0") 00228 set (VERSION_MINOR "0") 00229 set (VERSION_PATCH "0") 00230 endif () 00231 if (ARGC EQUAL 1) 00232 set (${ARGV0} "${VERSION_STRING}" PARENT_SCOPE) 00233 else () 00234 set (MATLAB_VERSION_STRING "${VERSION_STRING}" PARENT_SCOPE) 00235 set (MATLAB_VERSION_MAJOR "${VERSION_MAJOR}" PARENT_SCOPE) 00236 set (MATLAB_VERSION_MINOR "${VERSION_MINOR}" PARENT_SCOPE) 00237 set (MATLAB_VERSION_PATCH "${VERSION_PATCH}" PARENT_SCOPE) 00238 if (VERSION MATCHES ".*\\\((.+)\\\)") 00239 set (MATLAB_RELEASE "${CMAKE_MATCH_1}" PARENT_SCOPE) 00240 else () 00241 set (MATLAB_RELEASE "" PARENT_SCOPE) 00242 endif () 00243 endif () 00244 endfunction () 00245 00246 # ---------------------------------------------------------------------------- 00247 ## @brief Get release version of MATLAB installation. 00248 # 00249 # @param [out] ARGV1 If given, the named variable is set to the release string 00250 # of the MATLAB installation, e.g., "R2009b". Otherwise, 00251 # the variable @c MATLAB_RELEASE is set in the scope of the 00252 # caller. 00253 # 00254 # @ingroup CMakeUtilities 00255 function (basis_get_matlab_release) 00256 if (ARGC GREATER 1) 00257 message (FATAL_ERROR "basis_get_matlab_release(): Too many arguments!") 00258 endif () 00259 basis_get_full_matlab_version (VERSION) 00260 if (VERSION MATCHES ".*\\\((.+)\\\)") 00261 set (RELEASE "${CMAKE_MATCH_1}") 00262 else () 00263 set (RELEASE "") 00264 endif () 00265 if (ARGC EQUAL 1) 00266 set (${ARGV0} "${RELEASE}" PARENT_SCOPE) 00267 else () 00268 set (MATLAB_RELEASE "${RELEASE}") 00269 endif () 00270 endfunction () 00271 00272 # ---------------------------------------------------------------------------- 00273 ## @brief Determine extension of MEX-files for this architecture. 00274 # 00275 # @param [out] ARGN The first argument ARGV0 is set to the extension of 00276 # MEX-files (excluding '.'). If the CMake variable MEX_EXT 00277 # is set, its value is returned. Otherwise, this function 00278 # tries to determine it from the system information. 00279 # If the extension could not be determined, an empty string 00280 # is returned. If no argument is given, the extension is 00281 # cached as the variable MEX_EXT. 00282 # 00283 # @returns Sets the variable named by the first argument to the 00284 # platform-specific extension of MEX-files. 00285 # 00286 # @ingroup CMakeUtilities 00287 function (basis_mexext) 00288 # default return value 00289 set (MEXEXT "${MEX_EXT}") 00290 # use MEXEXT if possible 00291 if (NOT MEXEXT AND MATLAB_MEXEXT_EXECUTABLE) 00292 execute_process ( 00293 COMMAND "${MATLAB_MEXEXT_EXECUTABLE}" 00294 RESULT_VARIABLE RETVAL 00295 OUTPUT_VARIABLE MEXEXT 00296 ERROR_QUIET 00297 OUTPUT_STRIP_TRAILING_WHITESPACE 00298 ) 00299 if (RETVAL) 00300 set (MEXEXT "") 00301 endif () 00302 endif () 00303 # otherwise, determine extension given CMake variables describing the system 00304 if (NOT MEXEXT) 00305 if (CMAKE_SYSTEM_NAME MATCHES "Linux") 00306 if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") 00307 set (MEXEXT "mexa64") 00308 elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "x86" OR 00309 CMAKE_SYSTEM_PROCESSOR MATCHES "i686") 00310 set (MEXEXT "mexglx") 00311 endif () 00312 elseif (CMAKE_SYSTEM_NAME MATCHES "Windows") 00313 if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") 00314 set (MEXEXT "mexw64") 00315 elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "x86" OR 00316 CMAKE_SYSTEM_PROCESSOR MATCHES "i686") 00317 set (MEXEXT "mexw32") 00318 endif () 00319 elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") 00320 if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") 00321 set (MEXEXT "mexmaci64") 00322 else () 00323 set (MEXEXT "mexmaci") 00324 endif () 00325 elseif (CMAKE_SYSTEM_NAME MATCHES "SunOS") 00326 set (MEXEXT "mexs64") 00327 endif () 00328 endif () 00329 # return value 00330 if (ARGC GREATER 0) 00331 set ("${ARGV0}" "${MEXEXT}" PARENT_SCOPE) 00332 else () 00333 if (NOT DEFINED MEX_EXT) 00334 set (MARKIT 1) 00335 else () 00336 set (MARKIT 0) 00337 endif () 00338 set (MEX_EXT "${MEXEXT}" CACHE STRING "The extension of MEX-files for this architecture." FORCE) 00339 if (MARKIT) 00340 mark_as_advanced (MEX_EXT) 00341 endif () 00342 endif () 00343 endfunction () 00344 00345 # ---------------------------------------------------------------------------- 00346 ## @brief This function writes a MATLAB M-file with addpath() statements. 00347 # 00348 # This function writes an MATLAB M-file into the top directory of the build 00349 # tree which contains an addpath() statement for each directory that was added 00350 # via basis_include_directories(). 00351 # 00352 # @returns Creates file add_<project>_paths.m in the current binary directory. 00353 # 00354 # @ingroup CMakeUtilities 00355 function (basis_create_addpaths_mfile) 00356 basis_get_project_property (INCLUDE_DIRS PROPERTY PROJECT_INCLUDE_DIRS) 00357 basis_write_addpaths_mfile("${CMAKE_CURRENT_BINARY_DIR}/add_${PROJECT_NAME_L}_paths.m" ${INCLUDE_DIRS}) 00358 endfunction () 00359 00360 # ---------------------------------------------------------------------------- 00361 ## @brief This function writes a MATLAB M-file with addpath() statements. 00362 # 00363 # @param [in] MFILE Name of M-file. 00364 # @param [in] ARGN The remaining arguments are the paths which should be added 00365 # to the search path of MATLAB when this M-file is being 00366 # executed. If the option APPEND is given, the paths are 00367 # appended to the specified M-file. Otherwise, any existing 00368 # file will be overwritten. The given directory paths can 00369 # be relative, in which case they are interpreted relative 00370 # to the location of the written M-file using the mfilename() 00371 # function of MATLAB. 00372 # 00373 # @ingroup CMakeUtilities 00374 macro (basis_write_addpaths_mfile MFILE) 00375 CMAKE_PARSE_ARGUMENTS (ARGN "APPEND" "" "" ${ARGN}) 00376 if (NOT ARGN_APPEND) 00377 file (WRITE "${MFILE}" "% DO NOT edit. This file is automatically generated by BASIS. 00378 [mfiledir, ~, ~, ~] = fileparts(mfilename('fullpath'));\n") 00379 endif () 00380 foreach (P IN LISTS ARGN_UNPARSED_ARGUMENTS) 00381 if (P MATCHES "^\\.?$") 00382 file (APPEND "${MFILE}" "addpath(mfiledir);\n") 00383 elseif (IS_ABSOLUTE "${P}") 00384 file (APPEND "${MFILE}" "addpath('${P}');\n") 00385 else () 00386 file (APPEND "${MFILE}" "addpath([mfiledir '/${P}']);\n") 00387 endif () 00388 endforeach () 00389 endmacro () 00390 00391 # ---------------------------------------------------------------------------- 00392 ## @brief Generate MATLAB wrapper executable. 00393 # 00394 # This function writes a Bash script on Unix or a Windows Command script on 00395 # Windows platforms which execute the specified MATLAB command using the -r 00396 # option of the matlab executable and the -nodesktop and -nosplash options. 00397 # It is used by the build scripts generated by the basis_build_mcc_target() 00398 # in order to build an executable from MATLAB source files without the use 00399 # of the MATLAB Compiler. In this case, the MATLAB source files are simply 00400 # copied to the installation directory and the wrapper script written by 00401 # this function used to execute the main function with the command-line 00402 # arguments passed on to this executable. 00403 # 00404 # @param [in] OUTPUT_FILE Name of the output executable file. 00405 # @param [in] ARGN The remaining options 00406 # @par 00407 # <table border=0> 00408 # <tr> 00409 # @tp @b DESTINATION dir @endtp 00410 # <td>Installation destination. (default: directory of @c OUTPUT_FILE)</td> 00411 # </tr> 00412 # <tr> 00413 # @tp @b COMMAND name @endtp 00414 # <td>Name of the MATLAB command to execute, i.e., 00415 # the name of the main function.</td> 00416 # </tr> 00417 # <tr> 00418 # @tp @b STARTUP mfile @endtp 00419 # <td>Absolute path of a startup M-file.</td> 00420 # </tr> 00421 # <tr> 00422 # @tp @b MATLABPATH dir1[ dir2...] 00423 # <td>List of directories to be added to the MATLAB search path.</td> 00424 # </tr> 00425 # <tr> 00426 # @tp @b OPTIONS opt1[ opt2...] 00427 # <td>Additional options to pass on to the <tt>matlab</tt> executable.</td> 00428 # </tr> 00429 # </table> 00430 function (basis_generate_matlab_executable OUTPUT_FILE) 00431 CMAKE_PARSE_ARGUMENTS (ARGN "" "COMMAND;STARTUP;DESTINATION" "OPTIONS;MATLABPATH" ${ARGN}) 00432 if (NOT MATLAB_EXECUTABLE) 00433 set (MATLAB_EXECUTABLE matlab) 00434 endif () 00435 if (NOT OUTPUT_FILE) 00436 message ("basis_generate_matlab_executable(): Missing OUTPUT_FILE argument!") 00437 endif () 00438 if (NOT ARGN_DESTINATION) 00439 get_filename_component (ARGN_DESTINATION "${OUTPUT_FILE}" PATH) 00440 endif () 00441 # source path 00442 set (MATLABPATH) 00443 foreach (P IN LISTS ARGN_MATLABPATH) 00444 if (P MATCHES "^\\.?$") 00445 set (P "$__DIR__") 00446 elseif (NOT IS_ABSOLUTE "${P}") 00447 set (P "$__DIR__/${P}") 00448 endif () 00449 list (APPEND MATLABPATH "${P}") 00450 endforeach () 00451 if (MATLABPATH) 00452 list (REMOVE_DUPLICATES MATLABPATH) 00453 endif () 00454 # startup script 00455 if (ARGN_STARTUP) 00456 get_filename_component (STARTUP_COMMAND "${ARGN_STARTUP}" NAME_WE) 00457 get_filename_component (STARTUP_DIR "${ARGN_STARTUP}" PATH) 00458 get_filename_component (STARTUP_PKG "${STARTUP_DIR}" NAME) 00459 if (STARTUP_PKG MATCHES "^\\+") 00460 get_filename_component (STARTUP_DIR "${STARTUP_DIR}" PATH) 00461 string (REGEX REPLACE "^\\+" "" STARTUP_PKG "${STARTUP_PKG}") 00462 set (STARTUP_COMMAND "${STARTUP_PKG}.${STARTUP_COMMAND}") 00463 endif () 00464 if (IS_ABSOLUTE "${STARTUP_DIR}") 00465 file (RELATIVE_PATH STARTUP_DIR "${ARGN_DESTINATION}" "${STARTUP_DIR}") 00466 endif () 00467 if (STARTUP_DIR) 00468 set (STARTUP_DIR "$__DIR__/${STARTUP_DIR}") 00469 else () 00470 set (STARTUP_DIR "$__DIR__") 00471 endif () 00472 list (FIND MATLABPATH "${STARTUP_DIR}" IDX) 00473 if (IDX EQUAL -1) 00474 set (STARTUP_CODE ", addpath('${STARTUP_DIR}')") 00475 else () 00476 set (STARTUP_CODE) 00477 endif () 00478 set (STARTUP_CODE "${STARTUP_CODE}, ${STARTUP_COMMAND}") 00479 else () 00480 set (STARTUP_CODE) 00481 endif () 00482 # write wrapper executable 00483 if (MATLABPATH) 00484 basis_list_to_delimited_string (MATLABPATH "', '" NOAUTOQUOTE ${MATLABPATH}) 00485 set (MATLABPATH ", addpath('${MATLABPATH}', '-begin')") 00486 else () 00487 set (MATLABPATH) 00488 endif () 00489 file (WRITE "${OUTPUT_FILE}" 00490 # note that Bash variables within the script are denoted by $var 00491 # instead of ${var} to prevent CMake from substituting these patterns 00492 "#! /bin/bash 00493 00494 readonly __DIR__=\"${BASIS_BASH___DIR__}\" 00495 00496 errlog= 00497 finish() 00498 { 00499 local status=0 00500 if [[ -n \"$errlog\" ]]; then 00501 grep '??? Error' \"$errlog\" &> /dev/null 00502 [[ $? -ne 0 ]] || status=1 00503 /bin/rm \"$errlog\" 00504 fi 00505 exit $status 00506 } 00507 00508 if [[ -d \"$TMPDIR\" ]]; then 00509 tmpdir=$TMPDIR 00510 else 00511 tmpdir=/tmp 00512 fi 00513 00514 errlog=`mktemp \"$tmpdir/${ARGN_COMMAND}-log.XXXXXX\"` 00515 [[ $? -eq 0 ]] || { 00516 echo \"Failed to create temporary log file in '$tmpdir'!\" 1>&2 00517 exit 1 00518 } 00519 00520 args= 00521 while [[ $# -gt 0 ]]; do 00522 [[ -z \"$args\" ]] || args=\"$args, \" 00523 args=\"$args'$1'\" 00524 shift 00525 done 00526 00527 echo 'Launching MATLAB to execute ${ARGN_COMMAND} function...' 00528 trap finish EXIT # DO NOT install trap earlier ! 00529 '${MATLAB_EXECUTABLE}' -nodesktop -nosplash ${ARGN_OPTIONS} \\ 00530 -r \"try${MATLABPATH}${STARTUP_CODE}, ${ARGN_COMMAND}($args), catch err, fprintf(2, ['??? Error executing ${ARGN_COMMAND}\\n' err.message '\\n']), end, quit force\" \\ 00531 2> >(tee \"$errlog\" >&2)" 00532 ) # end of file(WRITE) command 00533 if (UNIX) 00534 execute_process (COMMAND /bin/chmod +x "${OUTPUT_FILE}") 00535 endif () 00536 endfunction () 00537 00538 # ============================================================================ 00539 # MEX-file target 00540 # ============================================================================ 00541 00542 # ---------------------------------------------------------------------------- 00543 ## @brief Add MEX-file target. 00544 # 00545 # @note This function should not be used directly. Instead, it is called 00546 # by basis_add_library() if the (detected) programming language 00547 # of the given source code files is @c CXX (i.e., C/C++) and the @c MEX 00548 # type option is given. 00549 # 00550 # This function is used to add a shared library target which is built 00551 # using the MATLAB MEX script (mex). 00552 # 00553 # By default, the BASIS C++ utilities library is added as link dependency. 00554 # If none of the BASIS C++ utilities are used by this target, the option 00555 # NO_BASIS_UTILITIES can be given. To enable this option by default, set the 00556 # variable @c BASIS_UTILITIES to @c FALSE, best in the <tt>Settings.cmake</tt> 00557 # file located in the @c PROJECT_CONFIG_DIR (add such file if missing). 00558 # If the use of the BASIS C++ utilities is disabled by default, the 00559 # @c USE_BASIS_UTILITIES option can be used to enable them for this target 00560 # only. Note that the utilities library is a static library and thus the linker 00561 # would simply not include any of the BASIS utility functions in the final 00562 # binary file if not used. The only advantage of setting @c BASIS_UTILITIES to 00563 # @c FALSE or to always specify @c NO_BASIS_UTILITIES if no target uses the 00564 # utilities is that the BASIS utilities library will not be build in this case. 00565 # 00566 # A custom CMake build target with the following properties is added by this 00567 # function to the build system. These properties are used by 00568 # basis_build_mex_target() to generate a build script written in CMake 00569 # code which is executed by a custom CMake command. Before the invokation of 00570 # basis_build_mex_target(), the target properties can be modified using 00571 # basis_set_target_properties(). 00572 # 00573 # @note Custom BASIS build targets are finalized by BASIS at the end of 00574 # basis_project_impl(), i.e., the end of the root CMake configuration file 00575 # of the (sub-)project. 00576 # 00577 # @par Properties on script library targets 00578 # <table border=0> 00579 # <tr> 00580 # @tp @b MFILE file @endtp 00581 # <td>MATLAB source file with function prototype and documentation of MEX-file. 00582 # (default: none)</td> 00583 # </tr> 00584 # <tr> 00585 # @tp @b PREFIX prefix @endtp 00586 # <td>Output prefix of build MEX-file such as package name 00587 # (the prefix must include the leading + and trailing /).</td> 00588 # </tr> 00589 # </table> 00590 # 00591 # @attention Properties documented as read-only must not be modified. 00592 # 00593 # An install command for the added library target is added by this function 00594 # as well. The MEX-file will be installed as part of the specified @p COMPONENT 00595 # in the @c INSTALL_LIBRARY_DIR on Unix and @c INSTALL_RUNTIME_DIR on Windows. 00596 # 00597 # @param [in] TARGET_NAME Name of build target. 00598 # @param [in] ARGN The remaining arguments are parsed and the following 00599 # arguments extracted. All unparsed arguments are treated 00600 # as the source files of the MEX-file. 00601 # @par 00602 # <table border="0"> 00603 # <tr> 00604 # @tp @b COMPONENT name @endtp 00605 # <td>Name of installation component as part of which this MEX-file is being 00606 # installed if the @c LIBRARY_INSTALL_DIRECTORY property is not "none". 00607 # (default: @c BASIS_LIBRARY_COMPONENT)</td> 00608 # </tr> 00609 # <tr> 00610 # @tp @b [NO]EXPORT @endtp 00611 # <td>Whether to export this target. (default: @c TRUE)</td> 00612 # </tr> 00613 # <tr> 00614 # @tp @b NO_BASIS_UTILITIES @endtp 00615 # <td>Specify that the BASIS utilities are not used by this MEX-file and 00616 # hence no link dependency on the BASIS utilities shall be added. 00617 # (default: @c NOT BASIS_UTILITIES)</td> 00618 # </tr> 00619 # <tr> 00620 # @tp @b USE_BASIS_UTILITIES @endtp 00621 # <td>Specify that the BASIS utilities are used and required by this MEX-file 00622 # and hence a link dependency on the BASIS utilities must be added. 00623 # (default: @c BASIS_UTILITIES)</td> 00624 # </tr> 00625 # </table> 00626 # 00627 # @returns Adds custom target to build MEX-file using the MEX script. 00628 # 00629 # @sa basis_add_library() 00630 # 00631 # @ingroup CMakeUtilities 00632 function (basis_add_mex_file TARGET_NAME) 00633 # check target name 00634 basis_check_target_name ("${TARGET_NAME}") 00635 basis_make_target_uid (TARGET_UID "${TARGET_NAME}") 00636 message (STATUS "Adding MEX-file ${TARGET_UID}...") 00637 # required commands available ? 00638 if (NOT MATLAB_MEX_EXECUTABLE) 00639 message (FATAL_ERROR "MATLAB MEX script (mex) not found! It is required to build target ${TARGET_UID}." 00640 " Forgot to add MATLAB as dependency? Otherwise, set MATLAB_MEX_EXECUTABLE manually and try again.") 00641 endif () 00642 # parse arguments 00643 CMAKE_PARSE_ARGUMENTS ( 00644 ARGN 00645 "USE_BASIS_UTILITIES;NO_BASIS_UTILITIES;EXPORT;NOEXPORT" 00646 "COMPONENT;DESTINATION" 00647 "" 00648 ${ARGN} 00649 ) 00650 set (SOURCES ${ARGN_UNPARSED_ARGUMENTS}) 00651 basis_set_flag (ARGN EXPORT ${BASIS_EXPORT}) 00652 if (ARGN_USE_BASIS_UTILITIES AND ARGN_NO_BASIS_UTILITIES) 00653 message (FATAL_ERROR "Target ${TARGET_UID}: Options USE_BASIS_UTILITIES and NO_BASIS_UTILITIES are mutually exclusive!") 00654 endif () 00655 if (ARGN_USE_BASIS_UTILITIES) 00656 set (USES_BASIS_UTILITIES TRUE) 00657 elseif (ARGN_NO_BASIS_UTILITIES) 00658 set (USES_BASIS_UTILITIES FALSE) 00659 else () 00660 set (USES_BASIS_UTILITIES ${BASIS_UTILITIES}) 00661 endif () 00662 basis_mexext (MEXEXT) 00663 # TEST flag 00664 basis_sanitize_for_regex (RE "${PROJECT_TESTING_DIR}") 00665 if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${RE}") 00666 set (TEST TRUE) 00667 else () 00668 set (TEST FALSE) 00669 endif () 00670 # installation component 00671 if (NOT ARGN_COMPONENT) 00672 set (ARGN_COMPONENT "${BASIS_LIBRARY_COMPONENT}") 00673 endif () 00674 if (NOT ARGN_COMPONENT) 00675 set (ARGN_COMPONENT "Unspecified") 00676 endif () 00677 # installation directory 00678 if (ARGN_DESTINATION) 00679 if (ARGN_DESTINATION MATCHES "^[nN][oO][nN][eE]$") 00680 set (ARGN_DESTINATION) 00681 elseif (IS_ABSOLUTE "${ARGN_DESTINATION}") 00682 file (RELATIVE_PATH ARGN_DESTINATION "${CMAKE_INSTALL_PREFIX}" "${ARGN_DESTINATION}") 00683 endif () 00684 else () 00685 set (ARGN_DESTINATION "${INSTALL_MATLAB_LIBRARY_DIR}") 00686 endif () 00687 # configure (.in) source files 00688 basis_configure_sources (SOURCES ${SOURCES}) 00689 # link to BASIS utilities 00690 if (USES_BASIS_UTILITIES) 00691 if (NOT TARGET ${BASIS_CXX_UTILITIES_LIBRARY}) 00692 message (FATAL_ERROR "Target ${TARGET_UID} makes use of the BASIS C++ utilities" 00693 " but BASIS was build without C++ utilities enabled." 00694 " Either specify the option NO_BASIS_UTILITIES, set the global" 00695 " variable BASIS_UTILITIES to FALSE" 00696 " (in ${PROJECT_CONFIG_DIR}/Settings.cmake) or" 00697 " rebuild BASIS with C++ utilities enabled.") 00698 endif () 00699 # add project-specific library target if not present yet 00700 basis_add_utilities_library (BASIS_UTILITIES_TARGET) 00701 # non-project specific and project-specific utilities 00702 list (APPEND LINK_DEPENDS ${BASIS_CXX_UTILITIES_LIBRARY} ${BASIS_UTILITIES_TARGET}) 00703 endif () 00704 # add custom target 00705 add_custom_target (${TARGET_UID} ALL SOURCES ${SOURCES}) 00706 get_directory_property (INCLUDE_DIRS INCLUDE_DIRECTORIES) 00707 get_directory_property (LINK_DIRS LINK_DIRECTORIES) 00708 _set_target_properties ( 00709 ${TARGET_UID} 00710 PROPERTIES 00711 LANGUAGE "CXX" 00712 BASIS_TYPE MEX 00713 BASIS_UTILITIES ${USES_BASIS_UTILITIES} 00714 BASIS_INCLUDE_DIRECTORIES "${INCLUDE_DIRS}" 00715 BASIS_LINK_DIRECTORIES "${LINK_DIRS}" 00716 SOURCE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 00717 BINARY_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" 00718 LIBRARY_OUTPUT_DIRECTORY "${BINARY_MATLAB_LIBRARY_DIR}" 00719 LIBRARY_INSTALL_DIRECTORY "${ARGN_DESTINATION}" 00720 LIBRARY_COMPONENT "${ARGN_COMPONENT}" 00721 COMPILE_FLAGS "${BASIS_MEX_FLAGS}" 00722 LINK_FLAGS "" 00723 LINK_DEPENDS "${LINK_DEPENDS}" 00724 PREFIX "" 00725 OUTPUT_NAME "" 00726 SUFFIX ".${MEXEXT}" 00727 MFILE "" 00728 TEST ${TEST} 00729 EXPORT ${EXPORT} 00730 ) 00731 # add target to list of targets 00732 basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET_UID}") 00733 message (STATUS "Adding MEX-file ${TARGET_UID}... - done") 00734 endfunction () 00735 00736 # ============================================================================ 00737 # MATLAB Compiler target 00738 # ============================================================================ 00739 00740 # ---------------------------------------------------------------------------- 00741 ## @brief Add MATLAB Compiler target. 00742 # 00743 # @note This function should not be used directly. Instead, it is called 00744 # by either basis_add_executable() or basis_add_library() if the 00745 # (detected) programming language of the given source code files is 00746 # @c MATLAB. 00747 # 00748 # This function is used to add an executable or shared library target which is 00749 # built using the MATLAB Compiler (MCC). 00750 # 00751 # A custom CMake build target with the following properties is added by this 00752 # function to the build system. These properties are used by 00753 # basis_build_mcc_target() to generate a build script written in CMake 00754 # code which is executed by a custom CMake command. Before the invokation of 00755 # basis_build_mcc_target(), the target properties can be modified using 00756 # basis_set_target_properties(). 00757 # 00758 # @note Custom BASIS build targets are finalized by BASIS at the end of 00759 # basis_project_impl(), i.e., the end of the root CMake configuration file 00760 # of the (sub-)project. 00761 # 00762 # @par Properties on MATLAB Compiler targets 00763 # <table border=0> 00764 # <tr><td>TODO</td></tr> 00765 # </table> 00766 # 00767 # An install command for the added executable or library target is added by 00768 # this function as well. The executable will be installed as part of the 00769 # @p RUNTIME_COMPONENT in the directory @c INSTALL_RUNTIME_DIR. The runtime 00770 # library will be installed as part of the @p RUNTIME_COMPONENT in the directory 00771 # @c INSTALL_LIBRARY_DIR on Unix and @c INSTALL_RUNTIME_DIR on Windows. 00772 # Static/import libraries will be installed as part of the @p LIBRARY_COMPONENT 00773 # in the directory @c INSTALL_ARCHIVE_DIR. 00774 # 00775 # @note If this function is used within the @c PROJECT_TESTING_DIR, the built 00776 # executable is output to the @c BINARY_TESTING_DIR directory tree instead. 00777 # Moreover, no installation rules are added. Test executables are further 00778 # not exported, regardless of the value of the @c EXPORT property. 00779 # 00780 # @param [in] TARGET_NAME Name of build target. 00781 # @param [in] ARGN The remaining arguments are parsed and the following 00782 # arguments extracted. All unparsed arguments are treated 00783 # as the MATLAB or C/C++ source files, respectively. 00784 # @par 00785 # <table border="0"> 00786 # <tr> 00787 # @tp <b>EXECUTABLE</b>|<b>LIBEXEC</b>|<b>SHARED</b> @endtp 00788 # <td>Type of the MATLAB Compiler target which can be either a stand-alone 00789 # executable, an auxiliary executable, or a shared library. 00790 # (default: @c EXECUTABLE)</td> 00791 # </tr> 00792 # <tr> 00793 # @tp @b COMPONENT name @endtp 00794 # <td>Name of component as part of which this executable or library will be 00795 # installed if the @c RUNTIME_INSTALL_DIRECTORY or @c LIBRARY_INSTALL_DIRECTORY 00796 # property is not "none". Used only if @p RUNTIME_COMPONENT or 00797 # @p LIBRARY_COMPONENT not specified. 00798 # (default: see @p RUNTIME_COMPONENT and @p LIBRARY_COMPONENT arguments)</td> 00799 # </tr> 00800 # <tr> 00801 # @tp @b DESTINATION dir @endtp 00802 # <td>Installation directory for executable or runtime and library component 00803 # of shared library relative to @c CMAKE_INSTALL_PREFIX. Used only if 00804 # @p RUNTIME_DESTINATION or @p LIBRARY_DESTINATION not specified. 00805 # If "none" (case-insensitive) is given as argument, no default installation 00806 # rules are added. (default: see @p RUNTIME_DESTINATION and 00807 # @p LIBRARY_DESTINATION arguments)</td> 00808 # </tr> 00809 # <tr> 00810 # @tp @b LIBRARY_COMPONENT name @endtp 00811 # <td>Name of component as part of which import/static library will be intalled 00812 # if a shared library is build and the @c LIBRARY_INSTALL_DIRECTORY property is 00813 # not "none". (default: @c COMPONENT if specified or @c BASIS_LIBRARY_COMPONENT 00814 # otherwise)</td> 00815 # </tr> 00816 # <tr> 00817 # @tp @b LIBRARY_DESTINATION dir @endtp 00818 # <td>Installation directory of the library component relative to 00819 # @c CMAKE_INSTALL_PREFIX. If "none" (case-insensitive) is given as argument or 00820 # an executable is build, no installation rule for the library component is added. 00821 # (default: @c INSTALL_ARCHIVE_DIR)</td> 00822 # </tr> 00823 # <tr> 00824 # @tp @b RUNTIME_COMPONENT name @endtp 00825 # <td>Name of component as part of which executable or runtime library, respectively, 00826 # will be installed if the @c RUNTIME_INSTALL_DIRECTORY property is not "none". 00827 # (default: @c COMPONENT if specified or @c BASIS_RUNTIME_COMPONENT otherwise)</td> 00828 # </tr> 00829 # <tr> 00830 # @tp @b RUNTIME_DESTINATION dir @endtp 00831 # <td>Installation directory of the executable or runtime component of the shared library 00832 # relative to @c CMAKE_INSTALL_PREFIX. If "none" (case-insensitive) is given as argument, 00833 # no installation rule for the runtime library is added. 00834 # (default: @c INSTALL_LIBRARY_DIR for shared libraries on Unix or 00835 # @c INSTALL_RUNTIME_DIR otherwise)</td> 00836 # </tr> 00837 # <tr> 00838 # @tp @b [NO]EXPORT @endtp 00839 # <td>Whether to export this target. (default: @c TRUE)</td> 00840 # </tr> 00841 # <tr> 00842 # @tp @b NO_BASIS_UTILITIES @endtp 00843 # <td>Specify that the BASIS utilities are not used by this executable or shared library 00844 # and hence no link dependency on the BASIS utilities shall be added. 00845 # (default: @c NOT BASIS_UTILITIES)</td> 00846 # </tr> 00847 # <tr> 00848 # @tp @b USE_BASIS_UTILITIES @endtp 00849 # <td>Specify that the BASIS utilities are used and required by this executable 00850 # or shared library, respectively, and hence a link dependency on the BASIS utilities 00851 # must be added. 00852 # (default: @c BASIS_UTILITIES)</td> 00853 # </tr> 00854 # </table> 00855 # 00856 # @todo Consider NO_BASIS_UTILITIES and USE_BASIS_UTILITIES options after the BASIS 00857 # utilities for MATLAB have been implemented. 00858 # 00859 # @returns Adds custom target which builds depending on the @p BASIS_TYPE property 00860 # either an executable or a shared library using the MATLAB Compiler. 00861 # 00862 # @sa basis_add_executable() 00863 # @sa basis_add_library() 00864 # 00865 # @ingroup CMakeUtilities 00866 function (basis_add_mcc_target TARGET_NAME) 00867 # check target name 00868 basis_check_target_name ("${TARGET_NAME}") 00869 basis_make_target_uid (TARGET_UID "${TARGET_NAME}") 00870 # parse arguments 00871 CMAKE_PARSE_ARGUMENTS ( 00872 ARGN 00873 "SHARED;EXECUTABLE;LIBEXEC;EXPORT;NOEXPORT" 00874 "COMPONENT;RUNTIME_COMPONENT;LIBRARY_COMPONENT;DESTINATION;RUNTIME_DESTINATION;LIBRARY_DESTINATION" 00875 "" 00876 ${ARGN} 00877 ) 00878 set (SOURCES "${ARGN_UNPARSED_ARGUMENTS}") 00879 basis_set_flag (ARGN EXPORT ${BASIS_EXPORT}) 00880 if (ARGN_SHARED AND (ARGN_EXECUTABLE OR ARGN_LIBEXEC)) 00881 message (FATAL_ERROR "Target ${TARGET_UID}: Options SHARED and EXECUTABLE or LIBEXEC are mutually exclusive!") 00882 endif () 00883 if (ARGN_SHARED) 00884 message (FATAL_ERROR "Target ${TARGET_UID}: Build of shared MATLAB library not yet supported.") 00885 set (TYPE LIBRARY) 00886 else () 00887 set (TYPE EXECUTABLE) 00888 endif () 00889 string (TOLOWER "${TYPE}" type) 00890 message (STATUS "Adding MATLAB ${type} ${TARGET_UID}...") 00891 # TEST flag 00892 basis_sanitize_for_regex (RE "${PROJECT_TESTING_DIR}") 00893 if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${RE}") 00894 set (TEST TRUE) 00895 else () 00896 set (TEST FALSE) 00897 endif () 00898 # output directory 00899 if (TEST) 00900 set (LIBRARY_OUTPUT_DIRECTORY "${TESTING_LIBRARY_DIR}") 00901 if (ARGN_LIBEXEC) 00902 set (RUNTIME_OUTPUT_DIRECTORY "${TESTING_LIBEXEC_DIR}") 00903 else () 00904 set (RUNTIME_OUTPUT_DIRECTORY "${TESTING_RUNTIME_DIR}") 00905 endif () 00906 else () 00907 set (LIBRARY_OUTPUT_DIRECTORY "${BINARY_LIBRARY_DIR}") 00908 if (ARGN_LIBEXEC) 00909 set (RUNTIME_OUTPUT_DIRECTORY "${BINARY_LIBEXEC_DIR}") 00910 else () 00911 set (RUNTIME_OUTPUT_DIRECTORY "${BINARY_RUNTIME_DIR}") 00912 endif () 00913 endif () 00914 # installation component 00915 if (ARGN_COMPONENT) 00916 if (NOT ARGN_LIBRARY_COMPONENT) 00917 set (ARGN_LIBRARY_COMPONENT "${ARGN_COMPONENT}") 00918 endif () 00919 if (NOT ARGN_RUNTIME_COMPONENT) 00920 set (ARGN_RUNTIME_COMPONENT "${ARGN_COMPONENT}") 00921 endif () 00922 endif () 00923 if (NOT ARGN_RUNTIME_COMPONENT) 00924 set (ARGN_RUNTIME_COMPONENT "${BASIS_RUNTIME_COMPONENT}") 00925 endif () 00926 if (NOT ARGN_RUNTIME_COMPONENT) 00927 set (ARGN_RUNTIME_COMPONENT "Unspecified") 00928 endif () 00929 if (NOT ARGN_LIBRARY_COMPONENT) 00930 set (ARGN_LIBRARY_COMPONENT "${BASIS_LIBRARY_COMPONENT}") 00931 endif () 00932 if (NOT ARGN_LIBRARY_COMPONENT) 00933 set (ARGN_LIBRARY_COMPONENT "Unspecified") 00934 endif () 00935 # installation directories 00936 if (ARGN_DESTINATION) 00937 if (NOT ARGN_RUNTIME_DESTINATION) 00938 set (ARGN_RUNTIME_DESTINATION "${ARGN_DESTINATION}") 00939 endif () 00940 if (NOT ARGN_LIBRARY_DESTINATION) 00941 set (ARGN_LIBRARY_DESTINATION "${ARGN_DESTINATION}") 00942 endif () 00943 endif () 00944 if (NOT ARGN_RUNTIME_DESTINATION) 00945 if (TEST) 00946 set (ARGN_RUNTIME_DESTINATION) # do not install 00947 else () 00948 if (ARGN_LIBEXEC) 00949 set (ARGN_RUNTIME_DESTINATION "${INSTALL_LIBEXEC_DIR}") 00950 else () 00951 set (ARGN_RUNTIME_DESTINATION "${INSTALL_RUNTIME_DIR}") 00952 endif () 00953 endif () 00954 endif () 00955 if (NOT ARGN_LIBRARY_DESTINATION) 00956 set (ARGN_LIBRARY_DESTINATION "${INSTALL_LIBRARY_DIR}") 00957 endif () 00958 if (ARGN_RUNTIME_DESTINATION MATCHES "^[nN][oO][nN][eE]$") 00959 set (ARGN_RUNTIME_DESTINATION) 00960 endif () 00961 if (ARGN_LIBRARY_DESTINATION MATCHES "^[nN][oO][nN][eE]$") 00962 set (ARGN_LIBRARY_DESTINATION) 00963 endif () 00964 # whether to compile and compilation flags (for mcc) 00965 if (TYPE MATCHES "LIBRARY" AND NOT MATLAB_MCC_EXECUTABLE) 00966 message (FATAL_ERROR "MATLAB Compiler not found! It is required to build target ${TARGET_UID}." 00967 " Set MATLAB_DIR and/or MATLAB_MCC_EXECUTABLE manually and try again.") 00968 endif () 00969 if ((BASIS_COMPILE_MATLAB AND MATLAB_MCC_EXECUTABLE) OR TYPE MATCHES "LIBRARY") 00970 set (COMPILE TRUE) 00971 else () 00972 if (BASIS_COMPILE_MATLAB) 00973 message (WARNING "MATLAB Compiler not found. Will generate a wrapper script for target" 00974 " ${TARGET_UID} which executes the MATLAB code using the -r option of" 00975 " the MATLAB interpreter. It is recommended to compile the MATLAB code" 00976 " using the MATLAB Compiler if possible, however. Therefore, make sure" 00977 " that the MATLAB Compiler is available and check the value of the" 00978 " advanced MATLAB_MCC_EXECUTABLE variable in CMake.") 00979 endif () 00980 set (COMPILE FALSE) 00981 endif () 00982 if (WIN32 AND NOT COMPILE) 00983 # TODO implement generation of Windows Command on Windows 00984 set (CONTACT) 00985 if (PROJECT_CONTACT) 00986 set (CONTACT "\n\nYou may further want to contact ${CONTACT} in order to ask for" 00987 " a binary distribution package which contains pre-build binaries" 00988 " created using the MATLAB Compiler and download the MATLAB Compiler" 00989 " Runtime only if no MATLAB Compiler license is available to you.") 00990 basis_list_to_string (CONTACT ${CONTACT}) 00991 endif () 00992 if (NOT BASIS_COMPILE_MATLAB) 00993 basis_update_value (BASIS_COMPILE_MATLAB ON) 00994 endif () 00995 message (FATAL_ERROR "The optional generation of a Windows Command which executes" 00996 " the MATLAB code using the -r option of the MATLAB interpreter" 00997 " as an alternative to the build of the MATLAB sources using" 00998 " the MATLAB Compiler is not yet implemented. You will have" 00999 " to obtain a MATLAB Compiler license and set the advanced" 01000 " MATLAB_MCC_EXECUTABLE variable in CMake or use this package" 01001 " on a Unix system instead.${CONTACT}") 01002 endif () 01003 set (COMPILE_FLAGS "${BASIS_MCC_FLAGS}") 01004 if (COMPILE) 01005 if (NOT MATLAB_MCC_EXECUTABLE) 01006 find_package (MATLAB COMPONENTS mcc QUIET) 01007 endif () 01008 else () 01009 if (NOT MATLAB_EXECUTABLE) 01010 find_package (MATLAB COMPONENTS matlab QUIET) 01011 endif () 01012 endif () 01013 # suffix 01014 if (WIN32 AND EXECUTABLE AND COMPILE_FLAGS MATCHES "^NOMCC$") 01015 set (SUFFIX ".cmd") 01016 else () 01017 set (SUFFIX) 01018 endif () 01019 # configure (.in) source files 01020 basis_configure_sources (SOURCES ${SOURCES}) 01021 # add custom target 01022 add_custom_target (${TARGET_UID} ALL SOURCES ${SOURCES}) 01023 get_directory_property (INCLUDE_DIRS INCLUDE_DIRECTORIES) 01024 get_directory_property (LINK_DIRS LINK_DIRECTORIES) 01025 _set_target_properties ( 01026 ${TARGET_UID} 01027 PROPERTIES 01028 LANGUAGE "MATLAB" 01029 BASIS_TYPE "MCC_${TYPE}" 01030 BASIS_UTILITIES FALSE # TODO Implement utilities for MATLAB 01031 BASIS_INCLUDE_DIRECTORIES "${INCLUDE_DIRS}" 01032 BASIS_LINK_DIRECTORIES "${LINK_DIRS}" 01033 SOURCE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 01034 BINARY_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" 01035 LIBRARY_OUTPUT_DIRECTORY "${LIBRARY_OUTPUT_DIRECTORY}" 01036 LIBRARY_INSTALL_DIRECTORY "${ARGN_LIBRARY_DESTINATION}" 01037 LIBRARY_COMPONENT "${ARGN_LIBRARY_COMPONENT}" 01038 RUNTIME_OUTPUT_DIRECTORY "${RUNTIME_OUTPUT_DIRECTORY}" 01039 RUNTIME_INSTALL_DIRECTORY "${ARGN_RUNTIME_DESTINATION}" 01040 RUNTIME_COMPONENT "${ARGN_RUNTIME_COMPONENT}" 01041 OUTPUT_NAME "${TARGET_NAME}" 01042 SUFFIX "${SUFFIX}" 01043 COMPILE_FLAGS "${COMPILE_FLAGS}" 01044 COMPILE "${COMPILE}" 01045 LINK_DEPENDS "" 01046 EXPORT ${EXPORT} 01047 LIBEXEC ${ARGN_LIBEXEC} 01048 TEST ${TEST} 01049 ) 01050 # add target to list of targets 01051 basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET_UID}") 01052 message (STATUS "Adding MATLAB ${type} ${TARGET_UID}... - done") 01053 endfunction () 01054 01055 # ============================================================================ 01056 # custom build commands 01057 # ============================================================================ 01058 01059 # ---------------------------------------------------------------------------- 01060 ## @brief Add custom command for build of MEX-file. 01061 # 01062 # This function is called by basis_finalize_targets() which in turn is called 01063 # at the end of basis_project_impl(), i.e., the end of the root CMake 01064 # configuration file of the (sub-)project. 01065 # 01066 # @param [in] TARGET_UID Name/UID of custom target added by basis_add_mex_file(). 01067 # 01068 # @sa basis_add_mex_file() 01069 # 01070 # @ingroup CMakeUtilities 01071 function (basis_build_mex_file TARGET_UID) 01072 # does this target exist ? 01073 basis_get_target_uid (TARGET_UID "${TARGET_UID}") 01074 if (NOT TARGET "${TARGET_UID}") 01075 message (FATAL_ERROR "Unknown build target: ${TARGET_UID}") 01076 endif () 01077 if (BASIS_VERBOSE) 01078 message (STATUS "Adding build command for target ${TARGET_UID}...") 01079 endif () 01080 # get target properties 01081 basis_get_target_name (TARGET_NAME ${TARGET_UID}) 01082 set ( 01083 PROPERTIES 01084 BASIS_TYPE 01085 BASIS_UTILITIES 01086 BASIS_INCLUDE_DIRECTORIES 01087 BASIS_LINK_DIRECTORIES 01088 SOURCE_DIRECTORY 01089 BINARY_DIRECTORY 01090 LIBRARY_OUTPUT_DIRECTORY 01091 LIBRARY_INSTALL_DIRECTORY 01092 LIBRARY_COMPONENT 01093 PREFIX 01094 OUTPUT_NAME 01095 SUFFIX 01096 COMPILE_FLAGS 01097 LINK_DEPENDS 01098 LINK_FLAGS 01099 MFILE 01100 TEST 01101 EXPORT 01102 SOURCES 01103 ) 01104 foreach (PROPERTY ${PROPERTIES}) 01105 get_target_property (${PROPERTY} ${TARGET_UID} ${PROPERTY}) 01106 endforeach () 01107 # sanity check of property values 01108 if (NOT BASIS_TYPE MATCHES "^MEX$") 01109 message (FATAL_ERROR "Target ${TARGET_UID}: Invalid BASIS_TYPE: ${BASIS_TYPE}") 01110 endif () 01111 list (GET SOURCES 0 BUILD_DIR) # strange, but CMake stores path to internal build directory here 01112 list (REMOVE_AT SOURCES 0) 01113 set (BUILD_DIR "${BUILD_DIR}.dir") 01114 if (NOT IS_DIRECTORY "${BUILD_DIR}") 01115 file (MAKE_DIRECTORY "${BUILD_DIR}") 01116 endif () 01117 if (NOT SOURCES) 01118 message (FATAL_ERROR "Target ${TARGET_UID}: Empty SOURCES list!" 01119 " Have you accidentally modified this read-only property or" 01120 " is your (newer) CMake version not compatible with BASIS?") 01121 endif () 01122 if (NOT LIBRARY_COMPONENT) 01123 set (LIBRARY_COMPONENT "Unspecified") 01124 endif () 01125 if (MFILE) 01126 if (NOT IS_ABSOLUTE "${MFILE}") 01127 set (MFILE "${SOURCE_DIRECTORY}/${MFILE}") 01128 endif () 01129 if (NOT EXISTS "${MFILE}") 01130 message (FATAL_ERROR "M-file ${MFILE} of MEX-file target ${TARGET_UID} does not exist!") 01131 endif () 01132 endif () 01133 # output name 01134 if (NOT OUTPUT_NAME) 01135 set (OUTPUT_NAME "${TARGET_NAME}") 01136 endif () 01137 if (SUFFIX) 01138 set (OUTPUT_NAME "${OUTPUT_NAME}${SUFFIX}") 01139 endif () 01140 string (REGEX REPLACE "/+" "/" PREFIX "${PREFIX}") 01141 string (REGEX REPLACE "/$" "" PREFIX "${PREFIX}") 01142 if (PREFIX AND NOT PREFIX MATCHES "^/") 01143 set (PREFIX "/${PREFIX}") 01144 endif () 01145 # initialize dependencies of custom build command 01146 set (DEPENDS ${SOURCES}) 01147 # get list of libraries to link to 01148 set (LINK_LIBS) 01149 foreach (LIB ${LINK_DEPENDS}) 01150 basis_get_target_uid (UID "${LIB}") 01151 if (TARGET ${UID}) 01152 basis_get_target_location (LIB_FILE ${UID} ABSOLUTE) 01153 list (APPEND DEPENDS ${UID}) 01154 else () 01155 set (LIB_FILE "${LIB}") 01156 endif () 01157 list (APPEND LINK_LIBS "${LIB_FILE}") 01158 endforeach () 01159 get_filename_component (OUTPUT_NAME_WE "${OUTPUT_NAME}" NAME_WE) 01160 # decompose user supplied MEX switches 01161 macro (extract VAR) 01162 string (REGEX REPLACE "${VAR}=\"([^\"]+)\"|${VAR}=([^\" ])*" "" COMPILE_FLAGS "${COMPILE_FLAGS}") 01163 if (CMAKE_MATCH_1) 01164 set (${VAR} "${CMAKE_MATCH_1}") 01165 elseif (CMAKE_MATCH_2) 01166 set (${VAR} "${CMAKE_MATCH_2}") 01167 else () 01168 set (${VAR}) 01169 endif () 01170 endmacro () 01171 if (UNIX) 01172 extract (CC) 01173 extract (CFLAGS) 01174 extract (CXX) 01175 extract (CXXFLAGS) 01176 extract (CLIBS) 01177 extract (CXXLIBS) 01178 extract (LD) 01179 extract (LDXX) 01180 extract (LDFLAGS) 01181 extract (LDCXXFLAGS) 01182 if (LINK_FLAGS) 01183 set (LDFLAGS "${LDFLAGS} ${LINK_FLAGS}") 01184 endif () 01185 # set defaults for not provided options 01186 if (NOT CC) 01187 set (CC "${CMAKE_C_COMPILER}") 01188 endif () 01189 if (NOT CFLAGS) 01190 set (CFLAGS "${CMAKE_C_FLAGS}") 01191 endif () 01192 if (NOT CFLAGS MATCHES "( |^)-fPIC( |$)") 01193 set (CFLAGS "-fPIC ${CFLAGS}") 01194 endif () 01195 if (NOT CXX) 01196 set (CXX "${CMAKE_CXX_COMPILER}") 01197 endif () 01198 if (NOT CXXFLAGS) 01199 set (CXXFLAGS "${CMAKE_CXX_FLAGS}") 01200 endif () 01201 if (NOT CXXFLAGS MATCHES "( |^)-fPIC( |$)") 01202 set (CXXFLAGS "-fPIC ${CXXFLAGS}") 01203 endif () 01204 if (NOT LD) 01205 set (LD "${CMAKE_CXX_COMPILER}") # do not use CMAKE_LINKER here 01206 endif () 01207 if (NOT LDFLAGS) 01208 set (LDFLAGS "\$LDFLAGS ${CMAKE_SHARED_LINKER_FLAGS}") 01209 endif () 01210 # We chose to use CLIBS and CXXLIBS instead of the -L and -l switches 01211 # to add also link libraries added via basis_target_link_libraries() 01212 # because the MEX script will not use these arguments if CLIBS or CXXLIBS 01213 # is set. Moreover, the -l switch can only be used to link to a shared 01214 # library and not a static one (on UNIX). 01215 #foreach (LIB ${LINK_LIBS}) 01216 # if (LIB MATCHES "[/\\\.]") 01217 # set (CXXLIBS "${CXXLIBS} ${LIB}") 01218 # endif () 01219 #endforeach () 01220 endif () 01221 # get remaining switches 01222 basis_string_to_list (MEX_USER_ARGS "${COMPILE_FLAGS}") 01223 # assemble MEX switches 01224 set (MEX_ARGS) 01225 if (UNIX) 01226 list (APPEND MEX_ARGS "CC=${CC}" "CFLAGS=${CFLAGS}") # C compiler and flags 01227 if (CLIBS) 01228 list (APPEND MEX_ARGS "CLIBS=${CLIBS}") # C link libraries 01229 endif () 01230 list (APPEND MEX_ARGS "CXX=${CXX}" "CXXFLAGS=${CXXFLAGS}") # C++ compiler and flags 01231 if (CXXLIBS) 01232 list (APPEND MEX_ARGS "CXXLIBS=${CXXLIBS}") # C++ link libraries 01233 endif () 01234 if (LD) 01235 list (APPEND MEX_ARGS "LD=${LD}") # C linker 01236 endif () 01237 if (LDFLAGS) 01238 list (APPEND MEX_ARGS "LDFLAGS=${LDFLAGS}") # C link flags 01239 endif () 01240 if (LDCXX) 01241 list (APPEND MEX_ARGS "LDCXX=${LDCXX}") # C++ linker 01242 endif () 01243 if (LDCXXFLAGS) 01244 list (APPEND MEX_ARGS "LDCXXFLAGS=${LDCXXFLAGS}") # C++ link flags 01245 endif () 01246 endif () 01247 list (APPEND MEX_ARGS "-outdir" "${BUILD_DIR}") # output directory 01248 list (APPEND MEX_ARGS "-output" "${OUTPUT_NAME_WE}") # output name (w/o extension) 01249 foreach (INCLUDE_PATH ${BASIS_INCLUDE_DIRECTORIES}) # include directories 01250 list (FIND MEX_ARGS "-I${INCLUDE_PATH}" IDX) # as specified via 01251 if (INCLUDE_PATH AND IDX EQUAL -1) # basis_include_directories() 01252 list (APPEND MEX_ARGS "-I${INCLUDE_PATH}") 01253 endif () 01254 endforeach () 01255 set (MEX_LIBPATH) 01256 set (MEX_LIBS) 01257 foreach (LINK_DIR ${BASIS_LINK_DIRECTORIES}) # link directories 01258 if (WIN32) 01259 string (REPLACE "/" "\\" LINK_DIR "${LINK_DIR}") 01260 set (LINK_DIR "/LIBPATH:\\\"${LINK_DIR}\\\"") 01261 else () 01262 set (LINK_DIR "-L${LINK_DIR}") 01263 endif () 01264 list (APPEND MEX_LIBPATH "${LINK_DIR}") # as specified via basis_link_directories() 01265 endforeach () 01266 foreach (LIBRARY ${LINK_LIBS}) # link libraries 01267 get_filename_component (LINK_DIR "${LIBRARY}" PATH) # as specified via basis_target_link_libraries() 01268 get_filename_component (LINK_LIB "${LIBRARY}" NAME) 01269 string (REGEX REPLACE "\\.(so|a)(\\.[0-9]+)*$" "" LINK_LIB "${LINK_LIB}") 01270 string (REGEX REPLACE "^-l" "" LINK_LIB "${LINK_LIB}") 01271 if (WIN32) 01272 string (REPLACE "/" "\\" LINK_DIR "${LINK_DIR}") 01273 set (LINK_DIR "/LIBPATH:\\\"${LINK_DIR}\\\"") 01274 if (NOT LINK_LIB MATCHES "\\.lib$") 01275 set (LINK_LIB "${LINK_LIB}.lib") 01276 endif () 01277 else () 01278 string (REGEX REPLACE "^lib" "" LINK_LIB "${LINK_LIB}") 01279 set (LINK_DIR "-L${LINK_DIR}") 01280 set (LINK_LIB "-l${LINK_LIB}") 01281 endif () 01282 list (APPEND MEX_LIBPATH "${LINK_DIR}") 01283 list (APPEND MEX_LIBS "${LINK_LIB}") 01284 endforeach () 01285 if (MEX_LIBPATH) 01286 list (REMOVE_DUPLICATES MEX_LIBPATH) 01287 endif () 01288 if (MEX_LIBS) 01289 list (REMOVE_DUPLICATES MEX_LIBS) 01290 endif () 01291 if (MEX_LIBPATH OR MEX_LIBS) 01292 if (WIN32) 01293 basis_list_to_delimited_string (MEX_LIBPATH " " NOAUTOQUOTE ${MEX_LIBPATH}) 01294 basis_list_to_delimited_string (MEX_LIBS " " ${MEX_LIBS}) 01295 list (APPEND MEX_ARGS "LINKFLAGS#$LINKFLAGS ${MEX_LIBPATH} ${MEX_LIBS}") 01296 else () 01297 list (APPEND MEX_ARGS ${MEX_LIBPATH} ${MEX_LIBS}) 01298 endif () 01299 endif () 01300 # other user switches 01301 list (APPEND MEX_ARGS ${MEX_USER_ARGS}) 01302 # source files 01303 list (APPEND MEX_ARGS ${SOURCES}) 01304 # build command for invocation of MEX script 01305 set (BUILD_CMD "${MATLAB_MEX_EXECUTABLE}" -v ${MEX_ARGS}) 01306 set (BUILD_LOG "${BUILD_DIR}/build.log") 01307 set (BUILD_OUTPUT "${LIBRARY_OUTPUT_DIRECTORY}${PREFIX}/${OUTPUT_NAME}") 01308 set (BUILD_OUTPUTS "${BUILD_OUTPUT}") 01309 if (MFILE) 01310 set (BUILD_MFILE "${LIBRARY_OUTPUT_DIRECTORY}${PREFIX}/${OUTPUT_NAME_WE}.m") 01311 list (APPEND BUILD_OUTPUTS "${BUILD_MFILE}") 01312 else () 01313 set (BUILD_MFILE) 01314 endif () 01315 # configure build script 01316 set (COMMAND "${BUILD_CMD}") 01317 configure_file ("${BASIS_SCRIPT_EXECUTE_PROCESS}" "${BUILD_DIR}/build.cmake" @ONLY) 01318 # relative paths used for comments of commands 01319 file (RELATIVE_PATH REL "${CMAKE_BINARY_DIR}" "${BUILD_OUTPUT}") 01320 # add custom command to build executable using MEX script 01321 add_custom_command ( 01322 OUTPUT "${BUILD_OUTPUT}" 01323 # rebuild when input sources were modified 01324 DEPENDS ${DEPENDS} 01325 # invoke MEX script, wrapping the command in CMake execute_process() 01326 # command allows for inspection of command output for error messages 01327 # and specification of timeout 01328 COMMAND "${CMAKE_COMMAND}" 01329 "-DCOMMAND=${COMMAND}" 01330 "-DWORKING_DIRECTORY=${BUILD_DIR}" 01331 "-DTIMEOUT=${BASIS_MEX_TIMEOUT}" 01332 "-DERROR_EXPRESSION=[E|e]rror" 01333 "-DOUTPUT_FILE=${BUILD_LOG}" 01334 "-DERROR_FILE=${BUILD_LOG}" 01335 "-DVERBOSE=OFF" 01336 "-DLOG_ARGS=ON" 01337 "-P" "${BASIS_SCRIPT_EXECUTE_PROCESS}" 01338 # post-build command 01339 COMMAND "${CMAKE_COMMAND}" -E copy "${BUILD_DIR}/${OUTPUT_NAME}" "${BUILD_OUTPUT}" 01340 COMMAND "${CMAKE_COMMAND}" -E remove "${BUILD_DIR}/${OUTPUT_NAME}" 01341 # inform user where build log can be found 01342 COMMAND "${CMAKE_COMMAND}" -E echo "Build log written to ${BUILD_LOG}" 01343 # comment 01344 COMMENT "Building MEX-file ${REL}..." 01345 VERBATIM 01346 ) 01347 if (BUILD_MFILE) 01348 add_custom_command ( 01349 OUTPUT "${BUILD_MFILE}" 01350 DEPENDS "${MFILE}" 01351 COMMAND "${CMAKE_COMMAND}" -E copy "${MFILE}" "${BUILD_MFILE}" 01352 COMMENT "Copying M-file of ${REL}..." 01353 ) 01354 endif () 01355 # add custom target 01356 add_custom_target (_${TARGET_UID} DEPENDS ${BUILD_OUTPUTS} SOURCES ${SOURCES}) 01357 if (TARGET __${TARGET_UID}) # re-glob source files 01358 add_dependencies (_${TARGET_UID} __${TARGET_UID}) 01359 endif () 01360 add_dependencies (${TARGET_UID} _${TARGET_UID}) 01361 # cleanup on "make clean" 01362 set_property ( 01363 DIRECTORY 01364 APPEND PROPERTY 01365 ADDITIONAL_MAKE_CLEAN_FILES 01366 "${BUILD_DIR}/${OUTPUT_NAME}" 01367 "${BUILD_OUTPUTS}" 01368 "${BUILD_LOG}" 01369 ) 01370 # export target 01371 if (EXPORT) 01372 if (TEST) 01373 basis_set_project_property (APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}") 01374 else () 01375 basis_set_project_property (APPEND PROPERTY CUSTOM_EXPORT_TARGETS "${TARGET_UID}") 01376 endif () 01377 endif () 01378 # install MEX-file 01379 if (LIBRARY_INSTALL_DIRECTORY) 01380 install ( 01381 FILES ${BUILD_OUTPUTS} 01382 DESTINATION "${LIBRARY_INSTALL_DIRECTORY}${PREFIX}" 01383 COMPONENT "${LIBRARY_COMPONENT}" 01384 ) 01385 endif () 01386 if (BASIS_VERBOSE) 01387 message (STATUS "Adding build command for target ${TARGET_UID}... - done") 01388 endif () 01389 endfunction () 01390 01391 # ---------------------------------------------------------------------------- 01392 ## @brief Add custom command for build of MATLAB Compiler target. 01393 # 01394 # This function is called by basis_finalize_targets() which in turn is called 01395 # at the end of basis_project_impl(), i.e., the end of the root CMake 01396 # configuration file of the (sub-)project. 01397 # 01398 # @param [in] TARGET_UID Name/UID of custom target added by basis_add_mcc_target(). 01399 # 01400 # @sa basis_add_mcc_target() 01401 # 01402 # @ingroup CMakeUtilities 01403 function (basis_build_mcc_target TARGET_UID) 01404 # does this target exist ? 01405 basis_get_target_uid (TARGET_UID "${TARGET_UID}") 01406 if (NOT TARGET "${TARGET_UID}") 01407 message (FATAL_ERROR "Unknown target ${TARGET_UID}!") 01408 endif () 01409 if (BASIS_VERBOSE) 01410 message (STATUS "Adding build command for target ${TARGET_UID}...") 01411 endif () 01412 # get target properties 01413 basis_get_target_name (TARGET_NAME ${TARGET_UID}) 01414 set ( 01415 PROPERTIES 01416 BASIS_TYPE 01417 BASIS_UTILITIES 01418 BASIS_INCLUDE_DIRECTORIES 01419 BASIS_LINK_DIRECTORIES 01420 SOURCE_DIRECTORY 01421 BINARY_DIRECTORY 01422 LIBRARY_OUTPUT_DIRECTORY 01423 LIBRARY_INSTALL_DIRECTORY 01424 LIBRARY_COMPONENT 01425 RUNTIME_OUTPUT_DIRECTORY 01426 RUNTIME_INSTALL_DIRECTORY 01427 RUNTIME_COMPONENT 01428 PREFIX 01429 OUTPUT_NAME 01430 SUFFIX 01431 SOURCES 01432 COMPILE_FLAGS 01433 COMPILE 01434 LINK_DEPENDS 01435 TEST 01436 EXPORT 01437 ) 01438 foreach (PROPERTY ${PROPERTIES}) 01439 get_target_property (${PROPERTY} ${TARGET_UID} ${PROPERTY}) 01440 endforeach () 01441 # sanity checks of property values 01442 set (EXECUTABLE FALSE) 01443 set (LIBEXEC FALSE) 01444 set (LIBRARY FALSE) 01445 if (BASIS_TYPE MATCHES "^MCC_(EXECUTABLE|LIBEXEC|LIBRARY)$") 01446 set (${CMAKE_MATCH_1} TRUE) 01447 if (LIBEXEC) 01448 set (EXECUTABLE TRUE) 01449 endif () 01450 else () 01451 message (FATAL_ERROR "Target ${TARGET_UID}: Invalid BASIS_TYPE: ${BASIS_TYPE}") 01452 endif () 01453 list (GET SOURCES 0 BUILD_DIR) # strange, but CMake stores path to internal build directory here 01454 list (REMOVE_AT SOURCES 0) 01455 set (BUILD_DIR "${BUILD_DIR}.dir") 01456 if (NOT SOURCES) 01457 message (FATAL_ERROR "Target ${TARGET_UID}: Empty SOURCES list!" 01458 " Have you accidentally modified this read-only property or" 01459 " is your (newer) CMake version not compatible with BASIS?") 01460 endif () 01461 list (GET SOURCES 0 MAIN_SOURCE) # entry point 01462 if (NOT RUNTIME_COMPONENT) 01463 set (RUNTIME_COMPONENT "Unspecified") 01464 endif () 01465 if (NOT LIBRARY_COMPONENT) 01466 set (LIBRARY_COMPONENT "Unspecified") 01467 endif () 01468 # output name 01469 if (NOT OUTPUT_NAME) 01470 set (OUTPUT_NAME "${TARGET_NAME}") 01471 endif () 01472 if (PREFIX) 01473 set (OUTPUT_NAME "${PREFIX}${OUTPUT_NAME}") 01474 endif () 01475 if (SUFFIX) 01476 set (OUTPUT_NAME "${OUTPUT_NAME}${SUFFIX}") 01477 endif () 01478 # split compile flags at spaces into list 01479 basis_string_to_list (MCC_USER_FLAGS "${COMPILE_FLAGS}") 01480 # initialize dependencies of custom build command 01481 set (DEPENDS ${SOURCES}) 01482 # build output file and comment 01483 file (RELATIVE_PATH REL "${CMAKE_BINARY_DIR}" "${BUILD_DIR}/${OUTPUT_NAME}") 01484 if (LIBRARY) 01485 set (BUILD_OUTPUT "${LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT_NAME}") 01486 set (BUILD_COMMENT "Building MATLAB library ${REL}...") 01487 else () 01488 set (BUILD_OUTPUT "${RUNTIME_OUTPUT_DIRECTORY}/${OUTPUT_NAME}") 01489 set (BUILD_COMMENT "Building MATLAB executable ${REL}...") 01490 endif () 01491 # -------------------------------------------------------------------------- 01492 # assemble build command for build of executable wrapper script 01493 if (EXECUTABLE AND NOT COMPILE) 01494 # used to recognize source files which are located in the build tree 01495 basis_sanitize_for_regex (BINARY_CODE_DIR_RE "${BINARY_CODE_DIR}") 01496 # main MATLAB function and search path 01497 get_filename_component (MATLAB_COMMAND "${MAIN_SOURCE}" NAME_WE) 01498 get_filename_component (SOURCE_DIR "${MAIN_SOURCE}" PATH) 01499 get_filename_component (SOURCE_PACKAGE "${SOURCE_DIR}" NAME) 01500 if (SOURCE_PACKAGE MATCHES "^\\+") 01501 get_filename_component (SOURCE_DIR "${SOURCE_DIR}" PATH) 01502 set (MATLAB_COMMAND "${SOURCE_PACKAGE}.${MATLAB_COMMAND}") 01503 string (REGEX REPLACE "^\\+" "" MATLAB_COMMAND "${MATLAB_COMMAND}") 01504 else () 01505 set (SOURCE_PACKAGE "${MATLAB_COMMAND}") 01506 endif () 01507 basis_get_relative_path (DIR "${PROJECT_SOURCE_DIR}" "${SOURCE_DIR}") 01508 set (BINARY_DIR "${PROJECT_BINARY_DIR}/${DIR}") # location of configured sources 01509 # output file 01510 set (OUTPUT_FILE "${BUILD_OUTPUT}") 01511 get_filename_component (OUTPUT_DIR "${OUTPUT_FILE}" PATH) 01512 # installation 01513 set (INSTALL_FILE "${BUILD_DIR}/${OUTPUT_NAME}") # file to be installed 01514 set (INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${RUNTIME_INSTALL_DIRECTORY}") # location of installed wrapper 01515 set (INSTALL_SOURCE_DIR "${INSTALL_MATLAB_LIBRARY_DIR}") # location of installed MATLAB sources 01516 if (NOT SOURCE_PACKAGE MATCHES "^\\+") 01517 set (INSTALL_SOURCE_DIR "${INSTALL_SOURCE_DIR}/${SOURCE_PACKAGE}") 01518 endif () 01519 # startup file 01520 if (SOURCE_PACKAGE MATCHES "^\\+") 01521 set (BUILD_STARTUP_FILE "${BINARY_DIR}/${SOURCE_PACKAGE}/startup.m") 01522 set (INSTALL_STARTUP_FILE "${BUILD_DIR}/startup.m") 01523 set (INSTALL_STARTUP_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_SOURCE_DIR}/${SOURCE_PACKAGE}") 01524 else () 01525 set (BUILD_STARTUP_FILE "${BINARY_DIR}/startup.m") 01526 set (INSTALL_STARTUP_FILE "${BUILD_DIR}/startup.m") 01527 set (INSTALL_STARTUP_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_SOURCE_DIR}") 01528 endif () 01529 get_filename_component (BUILD_STARTUP_DIR "${BUILD_STARTUP_FILE}" PATH) 01530 list (APPEND BUILD_OUTPUT "${BUILD_STARTUP_FILE}") 01531 list (APPEND BUILD_OUTPUT "${INSTALL_STARTUP_FILE}") 01532 # MATLAB search path 01533 # 01534 # The following paths are written to the startup M-file such 01535 # that they can conveniently be added to the search path within an 01536 # interactive MATLAB sesssion. The path to this startup file is 01537 # added to the search path by the wrapper executable first, and 01538 # then this startup file is evaluated which adds all additional 01539 # paths. If no startup file is specified, all paths are added 01540 # to the search path on the command-line in the wrapper script. 01541 set (BUILD_MATLABPATH) 01542 set (INSTALL_MATLABPATH) 01543 # if any source file was configured and hence is located in the 01544 # build tree instead of the source tree, add corresponding build 01545 # tree path to BUILD_MATLABPATH as well 01546 if (SOURCES MATCHES "^${BINARY_CODE_DIR_RE}") 01547 file (RELATIVE_PATH REL "${BUILD_STARTUP_DIR}" "${BINARY_DIR}") 01548 if (REL) 01549 list (APPEND BUILD_MATLABPATH "${REL}") 01550 else () 01551 list (APPEND BUILD_MATLABPATH ".") 01552 endif () 01553 endif () 01554 list (APPEND BUILD_MATLABPATH "${SOURCE_DIR}") 01555 # The following is not required because startup script is located 01556 # in the same directory as the other sources and basis_generate_matlab_executable() 01557 # adds this path automatically in order to run the startup script. 01558 # Moreover, if anyone wants to run the startup script, they have to 01559 # add this path manually or make it the current directory first. 01560 #file (RELATIVE_PATH REL "${INSTALL_STARTUP_DIR}" "${CMAKE_INSTALL_PREFIX}/${INSTALL_SOURCE_DIR}") 01561 #if (REL) 01562 # list (APPEND INSTALL_MATLABPATH "${REL}") 01563 #else () 01564 # list (APPEND INSTALL_MATLABPATH ".") 01565 #endif () 01566 # link dependencies, i.e., MEX-files 01567 foreach (LINK_DEPEND ${LINK_DEPENDS}) 01568 basis_get_target_uid (UID "${LINK_DEPEND}") 01569 if (TARGET ${UID}) 01570 basis_get_target_location (LINK_DEPEND ${UID} ABSOLUTE) 01571 if (LINK_DEPEND MATCHES "\\.mex") 01572 get_filename_component (LINK_PATH "${LINK_DEPEND}" PATH) 01573 list (APPEND BUILD_MATLABPATH "${LINK_PATH}") 01574 list (APPEND DEPENDS ${UID}) 01575 endif () 01576 basis_get_target_location (LINK_DEPEND ${UID} POST_INSTALL) 01577 basis_get_target_property (BUNDLED ${UID} BUNDLED) 01578 basis_get_target_property (IMPORTED ${UID} IMPORTED) 01579 if (NOT IMPORTED OR BUNDLED) 01580 file (RELATIVE_PATH REL "${INSTALL_STARTUP_DIR}" "${LINK_DEPEND}") 01581 if (REL) 01582 set (LINK_DEPEND "${REL}") 01583 else () 01584 set (LINK_DEPEND ".") 01585 endif () 01586 endif () 01587 if (LINK_DEPEND MATCHES "\\.mex") 01588 get_filename_component (LINK_PATH "${LINK_DEPEND}" PATH) 01589 list (APPEND INSTALL_MATLABPATH "${LINK_PATH}") 01590 endif () 01591 elseif (IS_ABSOLUTE "${LINK_DEPEND}") 01592 if (IS_DIRECTORY "${LINK_DEPEND}") 01593 list (APPEND BUILD_MATLABPATH "${LINK_DEPEND}") 01594 list (APPEND INSTALL_MATLABPATH "${LINK_DEPEND}") 01595 elseif (EXISTS "${LINK_DEPEND}" AND LINK_DEPEND MATCHES "\\.mex") 01596 get_filename_component (LINK_PATH "${LINK_DEPEND}" PATH) 01597 list (APPEND BUILD_MATLABPATH "${LINK_PATH}") 01598 list (APPEND INSTALL_MATLABPATH "${LINK_PATH}") 01599 endif () 01600 endif () 01601 endforeach () 01602 # cleanup directory paths 01603 string (REGEX REPLACE "/+" "/" BUILD_MATLABPATH "${BUILD_MATLABPATH}") 01604 string (REGEX REPLACE "/+" "/" INSTALL_MATLABPATH "${INSTALL_MATLABPATH}") 01605 string (REGEX REPLACE "/(;|$)" "\\1" BUILD_MATLABPATH "${BUILD_MATLABPATH}") 01606 string (REGEX REPLACE "/(;|$)" "\\1" INSTALL_MATLABPATH "${INSTALL_MATLABPATH}") 01607 # remove duplicates 01608 if (BUILD_MATLABPATH) 01609 list (REMOVE_DUPLICATES BUILD_MATLABPATH) 01610 endif () 01611 if (INSTALL_MATLABPATH) 01612 list (REMOVE_DUPLICATES INSTALL_MATLABPATH) 01613 endif () 01614 # configure build script 01615 set (BUILD_SCRIPT "${BUILD_DIR}/build.cmake") 01616 configure_file ("${BASIS_MODULE_PATH}/generate_matlab_executable.cmake.in" "${BUILD_SCRIPT}" @ONLY) 01617 # add custom command to build wrapper executable 01618 add_custom_command ( 01619 OUTPUT ${BUILD_OUTPUT} 01620 # rebuild when input sources were modified 01621 MAIN_DEPENDENCY "${MAIN_SOURCE}" 01622 DEPENDS "${BUILD_SCRIPT}" "${CMAKE_CURRENT_LIST_FILE}" ${DEPENDS} 01623 # invoke MATLAB Compiler in either MATLAB or standalone mode 01624 # wrapping command in CMake execute_process () command allows for inspection 01625 # parsing of command output for error messages and specification of timeout 01626 COMMAND "${CMAKE_COMMAND}" "-P" "${BUILD_SCRIPT}" 01627 # comment 01628 COMMENT "${BUILD_COMMENT}" 01629 ) 01630 # install source files - preserving relative paths in SOURCE_DIR 01631 foreach (SOURCE IN LISTS SOURCES) 01632 get_filename_component (REL "${SOURCE}" PATH) 01633 if (SOURCE MATCHES "^${BINARY_CODE_DIR_RE}") 01634 basis_get_relative_path (REL "${BINARY_DIR}" "${REL}") 01635 else () 01636 basis_get_relative_path (REL "${SOURCE_DIR}" "${REL}") 01637 endif () 01638 if (REL MATCHES "^\\.?$|^\\.\\./") 01639 install ( 01640 FILES "${SOURCE}" 01641 DESTINATION "${INSTALL_SOURCE_DIR}" 01642 COMPONENT "${RUNTIME_COMPONENT}" 01643 ) 01644 else () 01645 install ( 01646 FILES "${SOURCE}" 01647 DESTINATION "${INSTALL_SOURCE_DIR}/${REL}" 01648 COMPONENT "${RUNTIME_COMPONENT}" 01649 ) 01650 endif () 01651 endforeach () 01652 # -------------------------------------------------------------------------- 01653 # assemble build command for build using MATLAB Compiler 01654 else () 01655 set (INSTALL_FILE "${BUILD_OUTPUT}") # file to be installed 01656 # get list of libraries to link to (e.g., MEX-file) 01657 set (LINK_LIBS) 01658 foreach (LIB ${LINK_DEPENDS}) 01659 basis_get_target_uid (UID "${LIB}") 01660 if (TARGET ${UID}) 01661 basis_get_target_location (LIB_FILE ${UID} ABSOLUTE) 01662 list (APPEND DEPENDS ${UID}) 01663 else () 01664 set (LIB_FILE "${LIB}") 01665 endif () 01666 list (APPEND LINK_LIBS "${LIB_FILE}") 01667 endforeach () 01668 # MATLAB search path 01669 foreach (P ${SOURCES}) 01670 get_filename_component (P "${P}" PATH) 01671 list (APPEND MATLABPATH "${P}") 01672 endforeach () 01673 list (APPEND MATLABPATH ${BASIS_INCLUDE_DIRECTORIES}) 01674 # MATLAB Compiler arguments 01675 string (REGEX REPLACE " +" ";" MCC_ARGS "${COMPILE_FLAGS}") # user specified flags 01676 foreach (P IN LISTS MATLABPATH) # search path, -I options 01677 string (REGEX REPLACE "/(\\+|@).*$" "" P "${P}") # remove package/class subdirectories 01678 list (FIND MCC_ARGS "${P}" IDX) # skip if already added 01679 if (IDX GREATER 0) 01680 math (EXPR IDX "${IDX} - 1") 01681 list (GET MCC_ARGS ${IDX} OPT) 01682 if (NOT OPT MATCHES "^-I$") 01683 set (IDX -1) 01684 endif () 01685 endif () 01686 if (EXISTS "${P}" AND IDX EQUAL -1) 01687 list (APPEND MCC_ARGS -I "${P}") 01688 endif () 01689 endforeach () 01690 if (LIBRARY) 01691 list (APPEND MCC_ARGS -l) # build library 01692 else () # or 01693 list (APPEND MCC_ARGS -m) # build standalone application 01694 endif () 01695 list (APPEND MCC_ARGS -d "${BUILD_DIR}") # (temp) output directory 01696 list (APPEND MCC_ARGS -o "${OUTPUT_NAME}") # output name 01697 list (APPEND MCC_ARGS ${MAIN_SOURCE}) # main source M-file 01698 foreach (LIB ${LINK_LIBS}) # link libraries, e.g. MEX-files 01699 list (FIND MCC_ARGS "${LIB}" IDX) 01700 if (LIB AND IDX EQUAL -1) 01701 list (APPEND MCC_ARGS "-a" "${LIB}") 01702 endif () 01703 endforeach () 01704 # build command for invocation of MATLAB Compiler in standalone mode 01705 set (BUILD_CMD "${MATLAB_MCC_EXECUTABLE}" ${MCC_USER_ARGS} ${MCC_ARGS}) 01706 set (BUILD_LOG "${BUILD_DIR}/build.log") 01707 set (WORKING_DIR "${SOURCE_DIRECTORY}") 01708 set (MATLAB_MODE OFF) 01709 # build command for invocation of MATLAB Compiler in MATLAB mode 01710 if (BASIS_MCC_MATLAB_MODE) 01711 set (MATLAB_MODE ON) 01712 if (NOT MATLAB_EXECUTABLE) 01713 message (WARNING "MATLAB executable not found. It is required to build target ${TARGET_UID} in MATLAB mode." 01714 " Forgot to MATLAB as dependency? Otherwise, set MATLAB_EXECUTABLE manually and try again or set BASIS_MCC_MATLAB_MODE to OFF." 01715 " Will build target ${TARGET_UID} in standalone mode instead.") 01716 set (MATLAB_MODE OFF) 01717 endif () 01718 if (MATLAB_MODE) 01719 basis_list_to_delimited_string (ARGS "', '" NOAUTOQUOTE ${MCC_USER_ARGS} ${MCC_ARGS}) 01720 set ( 01721 BUILD_CMD 01722 "${MATLAB_EXECUTABLE}" # run MATLAB 01723 "-nosplash" # do not display splash screen on start up 01724 "-nodesktop" # run in command line mode 01725 "-nojvm" # we do not need the Java Virtual Machine 01726 "-r" "try, mcc('-v', '${ARGS}'), catch err, fprintf(2, err.message), end, quit force" 01727 ) 01728 endif () 01729 endif () 01730 # post-build command 01731 if (LIBRARY) 01732 set ( 01733 POST_BUILD_COMMAND "${CMAKE_COMMAND}" -E copy 01734 "${BUILD_DIR}/${OUTPUT_NAME}" 01735 "${LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT_NAME}" 01736 ) 01737 else () 01738 set ( 01739 POST_BUILD_COMMAND "${CMAKE_COMMAND}" -E copy 01740 "${BUILD_DIR}/${OUTPUT_NAME}" 01741 "${RUNTIME_OUTPUT_DIRECTORY}/${OUTPUT_NAME}" 01742 ) 01743 endif () 01744 # add custom command to build executable using MATLAB Compiler 01745 add_custom_command ( 01746 OUTPUT ${BUILD_OUTPUT} 01747 # rebuild when input sources were modified 01748 MAIN_DEPENDENCY "${MAIN_SOURCE}" 01749 DEPENDS ${DEPENDS} 01750 # invoke MATLAB Compiler in either MATLAB or standalone mode 01751 # wrapping command in CMake execute_process() command allows for inspection 01752 # of command output for error messages and specification of timeout 01753 COMMAND "${CMAKE_COMMAND}" 01754 "-DCOMMAND=${BUILD_CMD}" 01755 "-DWORKING_DIRECTORY=${WORKING_DIR}" 01756 "-DTIMEOUT=${BASIS_MCC_TIMEOUT}" 01757 "-DRETRY_EXPRESSION=License checkout failed" 01758 "-DRETRY_ATTEMPTS=${BASIS_MCC_RETRY_ATTEMPTS}" 01759 "-DRETRY_DELAY=${BASIS_MCC_RETRY_DELAY}" 01760 "-DERROR_EXPRESSION=[E|e]rror" 01761 "-DOUTPUT_FILE=${BUILD_LOG}" 01762 "-DERROR_FILE=${BUILD_LOG}" 01763 "-DVERBOSE=OFF" 01764 "-DLOG_ARGS=ON" 01765 "-P" "${BASIS_SCRIPT_EXECUTE_PROCESS}" 01766 # post build command(s) 01767 COMMAND ${POST_BUILD_COMMAND} 01768 # inform user where build log can be found 01769 COMMAND "${CMAKE_COMMAND}" -E echo "Build log written to ${BUILD_LOG}" 01770 # comment 01771 COMMENT "${BUILD_COMMENT}" 01772 VERBATIM 01773 ) 01774 endif () 01775 # -------------------------------------------------------------------------- 01776 # add custom target 01777 add_custom_target (_${TARGET_UID} DEPENDS ${BUILD_OUTPUT} SOURCES ${SOURCES}) 01778 if (TARGET __${TARGET_UID}) # re-glob source files 01779 add_dependencies (_${TARGET_UID} __${TARGET_UID}) 01780 endif () 01781 add_dependencies (${TARGET_UID} _${TARGET_UID}) 01782 # cleanup on "make clean" 01783 set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${BUILD_OUTPUT}) 01784 if (COMPILE) 01785 set_property ( 01786 DIRECTORY 01787 APPEND PROPERTY 01788 ADDITIONAL_MAKE_CLEAN_FILES 01789 "${BUILD_DIR}/${OUTPUT_NAME}.prj" 01790 "${BUILD_DIR}/mccExcludedFiles.log" 01791 "${BUILD_DIR}/mccBuild.log" 01792 "${BUILD_DIR}/readme.txt" 01793 ) 01794 if (LIBRARY) 01795 # TODO 01796 else () 01797 set_property ( 01798 DIRECTORY 01799 APPEND PROPERTY 01800 ADDITIONAL_MAKE_CLEAN_FILES 01801 "${BUILD_DIR}/${OUTPUT_NAME}" 01802 "${BUILD_DIR}/run_${OUTPUT_NAME}.sh" 01803 "${BUILD_DIR}/${OUTPUT_NAME}_main.c" 01804 "${BUILD_DIR}/${OUTPUT_NAME}_mcc_component_data.c" 01805 ) 01806 endif () 01807 endif () 01808 # export target 01809 if (EXPORT) 01810 if (TEST) 01811 basis_set_project_property (APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}") 01812 else () 01813 basis_set_project_property (APPEND PROPERTY CUSTOM_EXPORT_TARGETS "${TARGET_UID}") 01814 endif () 01815 endif () 01816 # install executable or library 01817 if (LIBRARY) 01818 # TODO 01819 else () 01820 if (RUNTIME_INSTALL_DIRECTORY) 01821 install ( 01822 PROGRAMS "${INSTALL_FILE}" 01823 DESTINATION "${RUNTIME_INSTALL_DIRECTORY}" 01824 COMPONENT "${RUNTIME_COMPONENT}" 01825 ) 01826 endif () 01827 endif () 01828 # done 01829 if (BASIS_VERBOSE) 01830 message (STATUS "Adding build command for target ${TARGET_UID}... - done") 01831 endif () 01832 endfunction ()