00001 ############################################################################## 00002 # @file MatlabTools.cmake 00003 # @brief Enables use of MATLAB Compiler and build of MEX-files. 00004 # 00005 # Copyright (c) 2011, 2012 University of Pennsylvania. All rights reserved.<br /> 00006 # See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file. 00007 # 00008 # Contact: SBIA Group <sbia-software at uphs.upenn.edu> 00009 # 00010 # @ingroup CMakeTools 00011 ############################################################################## 00012 00013 if (__BASIS_MATLABTOOLS_INCLUDED) 00014 return () 00015 else () 00016 set (__BASIS_MATLABTOOLS_INCLUDED TRUE) 00017 endif () 00018 00019 00020 # ============================================================================ 00021 # options 00022 # ============================================================================ 00023 00024 ## @addtogroup BasisSettings 00025 # @{ 00026 00027 00028 ## @brief Enable/Disable invocation of MATLAB Compiler in MATLAB mode. 00029 option ( 00030 BASIS_MCC_MATLAB_MODE 00031 "Prefer MATLAB mode over standalone mode to invoke MATLAB Compiler." 00032 "ON" # prefer as it releases the license immediately once done 00033 ) 00034 00035 mark_as_advanced (BASIS_MCC_MATLAB_MODE) 00036 00037 00038 ## @} 00039 # end of Doxygen group 00040 00041 00042 # ============================================================================ 00043 # build configuration 00044 # ============================================================================ 00045 00046 ## @addtogroup BasisSettings 00047 # @{ 00048 00049 00050 ## @brief Script used to invoke the MATLAB Compiler in MATLAB mode. 00051 set (BASIS_SCRIPT_MCC "${CMAKE_CURRENT_LIST_DIR}/runmcc.m") 00052 00053 ## @brief Compile flags used to build MATLAB Compiler targets. 00054 set ( 00055 BASIS_MCC_FLAGS 00056 "-v -R -singleCompThread" 00057 CACHE STRING 00058 "Common MATLAB Compiler flags (separated by ' '; use '\\' to mask ' ')." 00059 ) 00060 00061 ## @brief Compile flags used to build MEX-files using the MEX script. 00062 set ( 00063 BASIS_MEX_FLAGS 00064 "-v" 00065 CACHE STRING 00066 "Common MEX switches (separated by ' '; use '\\' to mask ' ')." 00067 ) 00068 00069 ## @brief Timeout for building MATLAB Compiler targets. 00070 set (BASIS_MCC_TIMEOUT "600" CACHE STRING "Timeout for MATLAB Compiler execution") 00071 ## @brief Maximum number of retries on MATLAB Compiler license checkout. 00072 set (BASIS_MCC_RETRY_ATTEMPTS "4" CACHE STRING "Maximum number of retries on MATLAB Compiler license checkout error.") 00073 ## @brief Delay between retries to build MATLAB Compiler compiled targets on license checkout errors. 00074 set (BASIS_MCC_RETRY_DELAY "30" CACHE STRING "Delay between retries to build MATLAB Compiler compiled targets on license checkout error.") 00075 ## @brief Timeout for building MEX-file targets. 00076 set (BASIS_MEX_TIMEOUT "600" CACHE STRING "Timeout for MEX script execution") 00077 00078 mark_as_advanced (BASIS_MCC_FLAGS) 00079 mark_as_advanced (BASIS_MCC_TIMEOUT) 00080 mark_as_advanced (BASIS_MCC_RETRY_ATTEMPTS) 00081 mark_as_advanced (BASIS_MCC_RETRY_DELAY) 00082 mark_as_advanced (BASIS_MEX_FLAGS) 00083 mark_as_advanced (BASIS_MEX_TIMEOUT) 00084 00085 00086 ## @} 00087 # end of Doxygen group 00088 00089 00090 # ============================================================================ 00091 # utilities 00092 # ============================================================================ 00093 00094 # ---------------------------------------------------------------------------- 00095 ## @brief Determine version of MATLAB installation. 00096 # 00097 # @param [out] VERSION Value returned by the "version" command of MATLAB or 00098 # an empty string if execution of MATLAB failed. 00099 # 00100 # @returns Sets the variable named by @p VERSION to the full MATLAB version. 00101 # 00102 # @ingroup CMakeUtilities 00103 function (basis_get_full_matlab_version VERSION) 00104 if (NOT MATLAB_EXECUTABLE) 00105 message (FATAL_ERROR "MATLAB_EXECUTABLE not found. Forgot to add MATLAB as dependency?") 00106 endif () 00107 00108 set (OUTPUT_FILE "${CMAKE_BINARY_DIR}/MatlabVersion.txt") 00109 # run matlab command to write return value of "version" command to text file 00110 if (NOT EXISTS "${OUTPUT_FILE}") 00111 set (CMD "${MATLAB_EXECUTABLE}" "-nodesktop" "-nosplash") 00112 if (WIN32) 00113 list (APPEND CMD "-automation") 00114 endif () 00115 list (APPEND CMD "-r") 00116 set (MATLAB_CMD 00117 "fid = fopen ('${OUTPUT_FILE}', 'w')" 00118 "fprintf (fid, '%s', version)" 00119 "fclose (fid)" 00120 "exit" 00121 ) 00122 message (STATUS "Determining MATLAB version...") 00123 execute_process ( 00124 COMMAND ${CMD} "${MATLAB_CMD}" 00125 RESULT_VARIABLE RETVAL 00126 OUTPUT_QUIET 00127 ERROR_QUIET 00128 ) 00129 if (NOT RETVAL EQUAL 0) 00130 set (VERSION "" PARENT_SCOPE) 00131 message (STATUS "Determining MATLAB version... - failed") 00132 return () 00133 endif () 00134 message (STATUS "Determining MATLAB version... - done") 00135 endif () 00136 # read MATLAB version from text file 00137 file (READ "${OUTPUT_FILE}" VERSION) 00138 # return 00139 set (VERSION "${VERSION}" PARENT_SCOPE) 00140 endfunction () 00141 00142 # ---------------------------------------------------------------------------- 00143 ## @brief Determine version of MATLAB installation. 00144 # 00145 # @param [out] ARGN The first argument ARGV0 is set to the version of the 00146 # MATLAB installation, i.e., "7.9.0", for example, or an 00147 # empty string if execution of MATLAB failed. 00148 # If no output variable name is specified, the variable 00149 # MATLAB_VERSION is added to the cache if not present yet. 00150 # Note that if no output variable is given and MATLAB_VERSION 00151 # is already set, nothing is done. 00152 # 00153 # @returns Sets the variable named by the first argument to the determined 00154 # MATLAB version. 00155 # 00156 # @ingroup CMakeUtilities 00157 function (basis_get_matlab_version) 00158 if (ARGC GREATER 1) 00159 message (FATAL_ERROR "basis_get_matlab_version (): Invalid number of arguments.") 00160 endif () 00161 if (ARGC EQUAL 0 AND MATLAB_VERSION) 00162 return () 00163 endif () 00164 basis_get_full_matlab_version (VERSION) 00165 if (VERSION MATCHES "^([0-9]+\\.[0-9]+\\.[0-9]+)") 00166 set (VERSION "${CMAKE_MATCH_1}") 00167 else () 00168 set (VERSION "") 00169 endif () 00170 if (ARGC EQUAL 1) 00171 set (${ARGV0} "${VERSION}" PARENT_SCOPE) 00172 else () 00173 set (MATLAB_VERSION "${VERSION}" CACHE STRING "The version string of the MATLAB installation." FORCE) 00174 mark_as_advanced (MATLAB_VERSION) 00175 endif () 00176 endfunction () 00177 00178 # ---------------------------------------------------------------------------- 00179 ## @brief Determine release version of MATLAB installation. 00180 # 00181 # @param [out] ARGN The first argument ARGV0 is set to the release version of 00182 # the MATLAB installation, i.e., "R2009b", for example, 00183 # or an empty string if execution of MATLAB failed. 00184 # If no output variable name is specified, the variable 00185 # MATLAB_RELEASE is added to the cache if not present yet. 00186 # Note that if no output variable is given and MATLAB_RELEASE 00187 # is already set, nothing is done. 00188 # 00189 # @returns Sets the variable named by the first argument to the release version 00190 # of MATLAB. 00191 # 00192 # @ingroup CMakeUtilities 00193 function (basis_get_matlab_release) 00194 if (ARGC GREATER 1) 00195 message (FATAL_ERROR "basis_get_matlab_release (): Invalid number of arguments.") 00196 endif () 00197 if (ARGC EQUAL 0 AND MATLAB_RELEASE) 00198 return () 00199 endif () 00200 basis_get_full_matlab_version (VERSION) 00201 if (VERSION MATCHES ".*\\\((.+)\\\)") 00202 set (RELEASE "${CMAKE_MATCH_1}") 00203 else () 00204 set (RELEASE "") 00205 endif () 00206 if (ARGC EQUAL 1) 00207 set (${ARGV0} "${RELEASE}" PARENT_SCOPE) 00208 else () 00209 set (MATLAB_RELEASE "${RELEASE}" CACHE STRING "The release version of the MATLAB installation." FORCE) 00210 mark_as_advanced (MATLAB_RELEASE) 00211 endif () 00212 endfunction () 00213 00214 # ---------------------------------------------------------------------------- 00215 ## @brief Determine extension of MEX-files for this architecture. 00216 # 00217 # @param [out] ARGN The first argument ARGV0 is set to the extension of 00218 # MEX-files (excluding '.'). If the CMake variable MEX_EXT 00219 # is set, its value is returned. Otherwise, this function 00220 # tries to determine it from the system information. 00221 # If the extension could not be determined, an empty string 00222 # is returned. If no argument is given, the extension is 00223 # cached as the variable MEX_EXT. 00224 # 00225 # @returns Sets the variable named by the first argument to the 00226 # platform-specific extension of MEX-files. 00227 # 00228 # @ingroup CMakeUtilities 00229 function (basis_mexext) 00230 # default return value 00231 set (MEXEXT "${MEX_EXT}") 00232 00233 # use MEXEXT if possible 00234 if (NOT MEXEXT AND MATLAB_MEXEXT_EXECUTABLE) 00235 execute_process ( 00236 COMMAND "${MATLAB_MEXEXT_EXECUTABLE}" 00237 RESULT_VARIABLE RETVAL 00238 OUTPUT_VARIABLE MEXEXT 00239 ERROR_QUIET 00240 OUTPUT_STRIP_TRAILING_WHITESPACE 00241 ) 00242 00243 if (RETVAL) 00244 set (MEXEXT "") 00245 endif () 00246 endif () 00247 00248 # otherwise, determine extension given CMake variables describing the system 00249 if (NOT MEXEXT) 00250 if (CMAKE_SYSTEM_NAME MATCHES "Linux") 00251 if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") 00252 set (MEXEXT "mexa64") 00253 elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "x86" OR 00254 CMAKE_SYSTEM_PROCESSOR MATCHES "i686") 00255 set (MEXEXT "mexglx") 00256 endif () 00257 elseif (CMAKE_SYSTEM_NAME MATCHES "Windows") 00258 if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") 00259 set (MEXEXT "mexw64") 00260 elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "x86" OR 00261 CMAKE_SYSTEM_PROCESSOR MATCHES "i686") 00262 set (MEXEXT "mexw32") 00263 endif () 00264 elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") 00265 if (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") 00266 set (MEXEXT "mexaci64") 00267 else () 00268 set (MEXEXT "mexaci") 00269 endif () 00270 elseif (CMAKE_SYSTEM_NAME MATCHES "SunOS") 00271 set (MEXEXT "mexs64") 00272 endif () 00273 endif () 00274 00275 # return value 00276 if (ARGC GREATER 0) 00277 set ("${ARGV0}" "${MEXEXT}" PARENT_SCOPE) 00278 else () 00279 if (NOT DEFINED MEX_EXT) 00280 set (MARKIT 1) 00281 else () 00282 set (MARKIT 0) 00283 endif () 00284 set (MEX_EXT "${MEXEXT}" CACHE STRING "The extension of MEX-files for this architecture." FORCE) 00285 if (MARKIT) 00286 mark_as_advanced (MEX_EXT) 00287 endif () 00288 endif () 00289 endfunction () 00290 00291 # ---------------------------------------------------------------------------- 00292 ## @brief This function writes a MATLAB M-file with addpath() statements. 00293 # 00294 # This function writes an MATLAB M-file into the top directory of the build 00295 # tree which contains an addpath() statement for each directory that was added 00296 # via basis_include_directories(). 00297 # 00298 # @returns Creates file add_<project>_paths.m in the current binary directory. 00299 # 00300 # @ingroup CMakeUtilities 00301 function (basis_create_addpaths_mfile) 00302 set (MFILE "${CMAKE_CURRENT_BINARY_DIR}/add_${PROJECT_NAME_LOWER}_paths.m") 00303 file (WRITE "${MFILE}" "% DO NOT edit. This file is automatically generated by BASIS.\n") 00304 basis_get_project_property (INCLUDE_DIRS PROPERTY PROJECT_INCLUDE_DIRS) 00305 foreach (P IN LISTS INCLUDE_DIRS) 00306 file (APPEND "${MFILE}" "addpath ('${P}');\n") 00307 endforeach () 00308 endfunction () 00309 00310 # ============================================================================ 00311 # MEX target 00312 # ============================================================================ 00313 00314 # ---------------------------------------------------------------------------- 00315 ## @brief Add MEX target. 00316 # 00317 # This function is used to add a shared library target which is built 00318 # using the MATLAB MEX script (mex). It is invoked by basis_add_library(). 00319 # Thus, it is recommended to use this function instead. 00320 # 00321 # An install command for the added library target is added by this function 00322 # as well. The MEX-file will be installed as part of the @p COMPONENT 00323 # in the directory INSTALL_LIBRARY_DIR on UNIX systems and INSTALL_RUNTIME_DIR 00324 # on Windows. 00325 # 00326 # @note The custom build command is not added yet by this function. 00327 # Only a custom target which stores all the information required to 00328 # setup this build command is added. The custom command is added 00329 # by either basis_project_finalize() or basis_superproject_finalize(). 00330 # This way, the properties such as the OUTPUT_NAME of the custom 00331 # target can be still modified. 00332 # 00333 # @param [in] TARGET_NAME Name of the target. If a source file is given 00334 # as first argument, the build target name is derived 00335 # from the name of this source file. 00336 # @param [in] ARGN Remaining arguments such as in particular the 00337 # input source files. Moreover, the following arguments 00338 # are parsed: 00339 # @par 00340 # <table border="0"> 00341 # <tr> 00342 # @tp @b COMPONENT name @endtp 00343 # <td>Name of the component. Default: @c BASIS_LIBRARY_COMPONENT.</td> 00344 # </tr> 00345 # <tr> 00346 # @tp @b MFILE file @endtp 00347 # <td>MATLAB source file with function prototype and documentation of MEX-file.</td> 00348 # </tr> 00349 # <tr> 00350 # @tp @b NO_EXPORT @endtp 00351 # <td>Do not export the target.</td> 00352 # </tr> 00353 # </table> 00354 # 00355 # @returns Adds custom target to build MEX-file using the MEX script. 00356 # 00357 # @sa basis_add_library() 00358 # 00359 # @ingroup CMakeUtilities 00360 function (basis_add_mex_target TARGET_NAME) 00361 # parse arguments 00362 CMAKE_PARSE_ARGUMENTS ( 00363 ARGN 00364 "NO_EXPORT" 00365 "COMPONENT;MFILE" 00366 "" 00367 ${ARGN} 00368 ) 00369 00370 if (NOT ARGN_NO_EXPORT) 00371 set (ARGN_NO_EXPORT FALSE) 00372 endif () 00373 00374 if (NOT ARGN_COMPONENT) 00375 set (ARGN_COMPONENT "${BASIS_LIBRARY_COMPONENT}") 00376 endif () 00377 if (NOT ARGN_COMPONENT) 00378 set (ARGN_COMPONENT "Unspecified") 00379 endif () 00380 00381 if (ARGN_MFILE) 00382 get_filename_component (ARGN_MFILE "${ARGN_MFILE}" ABSOLUTE) 00383 endif () 00384 00385 set (SOURCES) 00386 get_filename_component (S "${TARGET_NAME}" ABSOLUTE) 00387 if (NOT ARGN_UNPARSED_ARGUMENTS OR EXISTS "${S}") 00388 list (APPEND ARGN_UNPARSED_ARGUMENTS "${TARGET_NAME}") 00389 basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE) 00390 endif () 00391 foreach (SOURCE ${ARGN_UNPARSED_ARGUMENTS}) 00392 get_filename_component (P "${SOURCE}" ABSOLUTE) 00393 list (APPEND SOURCES "${P}") 00394 endforeach () 00395 00396 # check target name 00397 basis_check_target_name ("${TARGET_NAME}") 00398 basis_make_target_uid (TARGET_UID "${TARGET_NAME}") 00399 00400 if (BASIS_VERBOSE) 00401 message (STATUS "Adding MEX-file ${TARGET_UID}...") 00402 endif () 00403 00404 # required commands available ? 00405 if (NOT MATLAB_MEX_EXECUTABLE) 00406 message (FATAL_ERROR "MATLAB MEX script (mex) not found. It is required to build target ${TARGET_UID}." 00407 " Forgot to add MATLAB as dependency? Otherwise, set MATLAB_MEX_EXECUTABLE manually and try again.") 00408 endif () 00409 00410 # MEX flags 00411 basis_mexext (MEXEXT) 00412 00413 # configure .in source files 00414 basis_configure_sources (SOURCES ${SOURCES}) 00415 00416 # add custom target 00417 add_custom_target (${TARGET_UID} ALL SOURCES ${SOURCES}) 00418 00419 # set target properties required by basis_add_mex_target_finalize () 00420 get_directory_property (INCLUDE_DIRS INCLUDE_DIRECTORIES) 00421 get_directory_property (LINK_DIRS LINK_DIRECTORIES) 00422 00423 _set_target_properties ( 00424 ${TARGET_UID} 00425 PROPERTIES 00426 BASIS_TYPE "MEX" 00427 PREFIX "" 00428 SUFFIX ".${MEXEXT}" 00429 VERSION "${PROJECT_VERSION}" 00430 SOVERSION "${PROJECT_SOVERSION}" 00431 SOURCE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 00432 BINARY_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" 00433 RUNTIME_OUTPUT_DIRECTORY "${BINARY_RUNTIME_DIR}" 00434 LIBRARY_OUTPUT_DIRECTORY "${BINARY_LIBRARY_DIR}" 00435 RUNTIME_INSTALL_DIRECTORY "${RUNTIME_INSTALL_DIR}" 00436 LIBRARY_INSTALL_DIRECTORY "${INSTALL_LIBRARY_DIR}" 00437 BASIS_INCLUDE_DIRECTORIES "${INCLUDE_DIRS}" 00438 BASIS_LINK_DIRECTORIES "${LINK_DIRS}" 00439 COMPILE_FLAGS "${BASIS_MEX_FLAGS}" 00440 LINK_FLAGS "" 00441 LINK_DEPENDS "" 00442 LIBRARY_COMPONENT "${ARGN_COMPONENT}" 00443 MFILE "${ARGN_MFILE}" 00444 TEST "0" # MEX-files cannot be used for testing only yet 00445 NO_EXPORT "${ARGN_NO_EXPORT}" 00446 ) 00447 00448 # add target to list of targets 00449 basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET_UID}") 00450 00451 if (BASIS_VERBOSE) 00452 message (STATUS "Adding MEX-file ${TARGET_UID}... - done") 00453 endif () 00454 endfunction () 00455 00456 # ---------------------------------------------------------------------------- 00457 ## @brief Finalize addition of MEX target. 00458 # 00459 # This function uses the properties of the custom MEX-file target added by 00460 # basis_add_mex_target() to create the custom build command and adds this 00461 # build command as dependency of this added target. 00462 # 00463 # @param [in] TARGET_UID "Global" target name. If this function is used 00464 # within the same project as basis_add_mex_target(), 00465 # the "local" target name may be given alternatively. 00466 # 00467 # @returns Adds custom targets corresponding to the custom target added by 00468 # basis_add_mex_target() which actually perform the invocation of 00469 # the MEX script. 00470 # 00471 # @sa basis_add_mex_target() 00472 # 00473 # @ingroup CMakeUtilities 00474 function (basis_add_mex_target_finalize TARGET_UID) 00475 # if used within (sub-)project itself, allow user to specify "local" target name 00476 basis_get_target_uid (TARGET_UID "${TARGET_UID}") 00477 00478 # finalized before ? 00479 if (TARGET "_${TARGET_UID}") 00480 return () 00481 endif () 00482 00483 # does this target exist ? 00484 if (NOT TARGET "${TARGET_UID}") 00485 message (FATAL_ERROR "Unknown target ${TARGET_UID}.") 00486 return () 00487 endif () 00488 00489 # get target properties 00490 basis_get_target_name (TARGET_NAME ${TARGET_UID}) 00491 00492 set ( 00493 PROPERTIES 00494 "BASIS_TYPE" 00495 "SOURCE_DIRECTORY" 00496 "BINARY_DIRECTORY" 00497 "RUNTIME_OUTPUT_DIRECTORY" 00498 "LIBRARY_OUTPUT_DIRECTORY" 00499 "RUNTIME_INSTALL_DIRECTORY" 00500 "LIBRARY_INSTALL_DIRECTORY" 00501 "PREFIX" 00502 "OUTPUT_NAME" 00503 "SUFFIX" 00504 "VERSION" 00505 "SOVERSION" 00506 "BASIS_INCLUDE_DIRECTORIES" 00507 "BASIS_LINK_DIRECTORIES" 00508 "SOURCES" 00509 "COMPILE_FLAGS" 00510 "LINK_DEPENDS" 00511 "LINK_FLAGS" 00512 "LIBRARY_COMPONENT" 00513 "MFILE" 00514 "TEST" 00515 "NO_EXPORT" 00516 ) 00517 00518 foreach (PROPERTY ${PROPERTIES}) 00519 get_target_property (${PROPERTY} ${TARGET_UID} ${PROPERTY}) 00520 endforeach () 00521 00522 if (NOT BASIS_TYPE MATCHES "^MEX$") 00523 message (FATAL_ERROR "Target ${TARGET_UID} has invalid BASIS_TYPE: ${BASIS_TYPE}") 00524 endif () 00525 00526 if (BASIS_VERBOSE) 00527 message (STATUS "Adding build command for MEX-file ${TARGET_UID}...") 00528 endif () 00529 00530 # build directory 00531 list (GET SOURCES 0 BUILD_DIR) 00532 set (BUILD_DIR "${BUILD_DIR}.dir") 00533 00534 list (REMOVE_AT SOURCES 0) 00535 00536 # output name 00537 if (NOT OUTPUT_NAME) 00538 set (OUTPUT_NAME "${TARGET_NAME}") 00539 endif () 00540 if (PREFIX) 00541 set (OUTPUT_NAME "${PREFIX}${OUTPUT_NAME}") 00542 endif () 00543 if (SUFFIX) 00544 set (OUTPUT_NAME "${OUTPUT_NAME}${SUFFIX}") 00545 endif () 00546 00547 # initialize dependencies of custom build command 00548 set (DEPENDS ${SOURCES}) 00549 00550 # get list of libraries to link to 00551 set (LINK_LIBS) 00552 00553 foreach (LIB ${LINK_DEPENDS}) 00554 basis_get_target_uid (UID "${LIB}") 00555 if (TARGET ${UID}) 00556 basis_get_target_location (LIB_FILE ${UID} ABSOLUTE) 00557 list (APPEND DEPENDS ${UID}) 00558 else () 00559 set (LIB_FILE "${LIB}") 00560 endif () 00561 list (APPEND LINK_LIBS "${LIB_FILE}") 00562 endforeach () 00563 00564 get_filename_component (OUTPUT_NAME_WE "${OUTPUT_NAME}" NAME_WE) 00565 00566 # decompose user supplied MEX switches 00567 macro (extract VAR) 00568 string (REGEX REPLACE "${VAR}=\"([^\"]+)\"|${VAR}=([^\" ])*" "" COMPILE_FLAGS "${COMPILE_FLAGS}") 00569 if (CMAKE_MATCH_1) 00570 set (${VAR} "${CMAKE_MATCH_1}") 00571 elseif (CMAKE_MATCH_2) 00572 set (${VAR} "${CMAKE_MATCH_2}") 00573 else () 00574 set (${VAR}) 00575 endif () 00576 endmacro () 00577 00578 extract (CC) 00579 extract (CFLAGS) 00580 extract (CXX) 00581 extract (CXXFLAGS) 00582 extract (CLIBS) 00583 extract (CXXLIBS) 00584 extract (LD) 00585 extract (LDXX) 00586 extract (LDFLAGS) 00587 extract (LDCXXFLAGS) 00588 00589 if (LINK_FLAGS) 00590 set (LDFLAGS "${LDFLAGS} ${LINK_FLAGS}") 00591 endif () 00592 00593 # set defaults for not provided options 00594 if (NOT CC) 00595 set (CC "${CMAKE_C_COMPILER}") 00596 endif () 00597 if (NOT CFLAGS) 00598 set (CFLAGS "${CMAKE_C_FLAGS}") 00599 endif () 00600 if (NOT CFLAGS MATCHES "( |^)-fPIC( |$)") 00601 set (CFLAGS "-fPIC ${CFLAGS}") 00602 endif () 00603 if (NOT CXX) 00604 set (CXX "${CMAKE_CXX_COMPILER}") 00605 endif () 00606 if (NOT CXXFLAGS) 00607 set (CXXFLAGS "${CMAKE_CXX_FLAGS}") 00608 endif () 00609 if (NOT CXXFLAGS MATCHES "( |^)-fPIC( |$)") 00610 set (CXXFLAGS "-fPIC ${CXXFLAGS}") 00611 endif () 00612 if (NOT LD) 00613 set (LD "${CMAKE_CXX_COMPILER}") # do not use CMAKE_LINKER here 00614 endif () 00615 if (NOT LDFLAGS) 00616 set (LDFLAGS "\$LDFLAGS ${CMAKE_SHARED_LINKER_FLAGS}") 00617 endif () 00618 00619 # We chose to use CLIBS and CXXLIBS instead of the -L and -l switches 00620 # to add also link libraries added via basis_target_link_libraries () 00621 # because the MEX script will not use these arguments if CLIBS or CXXLIBS 00622 # is set. Moreover, the -l switch can only be used to link to a shared 00623 # library and not a static one (on UNIX). 00624 #foreach (LIB ${LINK_LIBS}) 00625 # if (LIB MATCHES "[/\\\.]") 00626 # set (CXXLIBS "${CXXLIBS} ${LIB}") 00627 # endif () 00628 #endforeach () 00629 00630 # get remaining switches 00631 basis_string_to_list (MEX_USER_ARGS "${COMPILE_FLAGS}") 00632 00633 # assemble MEX switches 00634 set (MEX_ARGS) 00635 00636 list (APPEND MEX_ARGS "CC=${CC}" "CFLAGS=${CFLAGS}") # C compiler and flags 00637 if (CLIBS) 00638 list (APPEND MEX_ARGS "CLIBS=${CLIBS}") # C link libraries 00639 endif () 00640 list (APPEND MEX_ARGS "CXX=${CXX}" "CXXFLAGS=${CXXFLAGS}") # C++ compiler and flags 00641 if (CXXLIBS) 00642 list (APPEND MEX_ARGS "CXXLIBS=${CXXLIBS}") # C++ link libraries 00643 endif () 00644 if (LD) 00645 list (APPEND MEX_ARGS "LD=${LD}") # C linker 00646 endif () 00647 if (LDFLAGS) 00648 list (APPEND MEX_ARGS "LDFLAGS=${LDFLAGS}") # C link flags 00649 endif () 00650 if (LDCXX) 00651 list (APPEND MEX_ARGS "LDCXX=${LDCXX}") # C++ linker 00652 endif () 00653 if (LDCXXFLAGS) 00654 list (APPEND MEX_ARGS "LDCXXFLAGS=${LDCXXFLAGS}") # C++ link flags 00655 endif () 00656 list (APPEND MEX_ARGS "-outdir" "${BUILD_DIR}") # output directory 00657 list (APPEND MEX_ARGS "-output" "${OUTPUT_NAME_WE}") # output name (w/o extension) 00658 foreach (INCLUDE_PATH ${BASIS_INCLUDE_DIRECTORIES}) # include directories 00659 list (FIND MEX_ARGS "-I${INCLUDE_PATH}" IDX) # as specified via 00660 if (INCLUDE_PATH AND IDX EQUAL -1) # basis_include_directories () 00661 list (APPEND MEX_ARGS "-I${INCLUDE_PATH}") 00662 endif () 00663 endforeach () 00664 foreach (LIBRARY_PATH ${BASIS_LINK_DIRECTORIES}) # link directories 00665 list (FIND MEX_ARGS "-L${LIBRARY_PATH}" IDX) # as specified via 00666 if (LIBRARY_PATH AND IDX EQUAL -1) # basis_link_directories () 00667 list (APPEND MEX_ARGS "-L${LIBRARY_PATH}") 00668 endif () 00669 endforeach () 00670 foreach (LIBRARY ${LINK_LIBS}) # link libraries 00671 get_filename_component (LINK_DIR "${LIBRARY}" PATH) # as specified via 00672 get_filename_component (LINK_LIB "${LIBRARY}" NAME_WE) # basis_target_link_libraries () 00673 string (REGEX REPLACE "^-l" "" LINK_LIB "${LINK_LIB}") 00674 if (UNIX) 00675 string (REGEX REPLACE "^lib" "" LINK_LIB "${LINK_LIB}") 00676 endif () 00677 list (FIND MEX_ARGS "-L${LINK_DIR}" IDX) 00678 if (LINK_DIR AND IDX EQUAL -1) 00679 list (APPEND MEX_ARGS "-L${LINK_DIR}") 00680 endif () 00681 list (FIND MEX_ARGS "-l${LINK_LIB}" IDX) 00682 if (LINK_LIB AND IDX EQUAL -1) 00683 list (APPEND MEX_ARGS "-l${LINK_LIB}") 00684 endif () 00685 endforeach () 00686 list (APPEND MEX_ARGS ${MEX_USER_ARGS}) # other user switches 00687 list (APPEND MEX_ARGS ${SOURCES}) # source files 00688 00689 # build command for invocation of MEX script 00690 set (BUILD_CMD "${MATLAB_MEX_EXECUTABLE}" ${MEX_ARGS}) 00691 set (BUILD_LOG "${BUILD_DIR}/mexBuild.log") 00692 set (BUILD_OUTPUT "${LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT_NAME}") 00693 set (BUILD_OUTPUTS "${BUILD_OUTPUT}") 00694 00695 if (MFILE) 00696 set (BUILD_MFILE "${LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT_NAME_WE}.m") 00697 list (APPEND BUILD_OUTPUTS "${BUILD_MFILE}") 00698 else () 00699 set (BUILD_MFILE) 00700 endif () 00701 00702 # relative paths used for comments of commands 00703 file (RELATIVE_PATH REL "${CMAKE_BINARY_DIR}" "${BUILD_DIR}/${OUTPUT_NAME}") 00704 00705 # add custom command to build executable using MEX script 00706 add_custom_command ( 00707 OUTPUT "${BUILD_OUTPUT}" 00708 # rebuild when input sources were modified 00709 DEPENDS ${DEPENDS} 00710 # invoke MEX script, wrapping the command in CMake execute_process() 00711 # command allows for inspection of command output for error messages 00712 # and specification of timeout 00713 COMMAND "${CMAKE_COMMAND}" 00714 "-DCOMMAND=${BUILD_CMD}" 00715 "-DWORKING_DIRECTORY=${BUILD_DIR}" 00716 "-DTIMEOUT=${BASIS_MEX_TIMEOUT}" 00717 "-DERROR_EXPRESSION=[E|e]rror" 00718 "-DOUTPUT_FILE=${BUILD_LOG}" 00719 "-DERROR_FILE=${BUILD_LOG}" 00720 "-DVERBOSE=OFF" 00721 "-DLOG_ARGS=ON" 00722 "-P" "${BASIS_SCRIPT_EXECUTE_PROCESS}" 00723 # post-build command 00724 COMMAND "${CMAKE_COMMAND}" -E copy "${BUILD_DIR}/${OUTPUT_NAME}" "${BUILD_OUTPUT}" 00725 COMMAND "${CMAKE_COMMAND}" -E remove "${BUILD_DIR}/${OUTPUT_NAME}" 00726 # inform user where build log can be found 00727 COMMAND "${CMAKE_COMMAND}" -E echo "Build log written to ${BUILD_LOG}" 00728 # comment 00729 COMMENT "Building MEX-file ${REL}..." 00730 VERBATIM 00731 ) 00732 00733 if (BUILD_MFILE) 00734 add_custom_command ( 00735 OUTPUT "${BUILD_MFILE}" 00736 DEPENDS "${MFILE}" 00737 COMMAND "${CMAKE_COMMAND}" -E copy "${MFILE}" "${BUILD_MFILE}" 00738 COMMENT "Copying M-file of MEX-file ${REL}..." 00739 ) 00740 endif () 00741 00742 # add custom target 00743 if (TARGET "_${TARGET_UID}") 00744 message (FATAL_ERROR "There is another target named _${TARGET_UID}. " 00745 "BASIS uses target names starting with an underscore " 00746 "for custom targets which are required to build MEX-files. " 00747 "Do not use leading underscores in target names.") 00748 endif () 00749 00750 add_custom_target ( 00751 _${TARGET_UID} 00752 DEPENDS ${BUILD_OUTPUTS} 00753 SOURCES ${SOURCES} 00754 ) 00755 00756 add_dependencies (${TARGET_UID} _${TARGET_UID}) 00757 00758 # cleanup on "make clean" 00759 set_property ( 00760 DIRECTORY 00761 APPEND PROPERTY 00762 ADDITIONAL_MAKE_CLEAN_FILES 00763 "${BUILD_DIR}/${OUTPUT_NAME}" 00764 "${BUILD_OUTPUTS}" 00765 "${BUILD_LOG}" 00766 ) 00767 00768 # install MEX-file 00769 if (NOT NO_EXPORT) 00770 if (TEST) 00771 basis_set_project_property (APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}") 00772 else () 00773 basis_set_project_property (APPEND PROPERTY CUSTOM_EXPORT_TARGETS "${TARGET_UID}") 00774 endif () 00775 endif () 00776 00777 install ( 00778 FILES ${BUILD_OUTPUTS} 00779 DESTINATION "${LIBRARY_INSTALL_DIRECTORY}" 00780 COMPONENT "${LIBRARY_COMPONENT}" 00781 ) 00782 00783 if (BASIS_VERBOSE) 00784 message (STATUS "Adding build command for MEX-file ${TARGET_UID}... - done") 00785 endif () 00786 endfunction () 00787 00788 # ============================================================================ 00789 # MATLAB Compiler target 00790 # ============================================================================ 00791 00792 # ---------------------------------------------------------------------------- 00793 ## @brief Add MATLAB Compiler target. 00794 # 00795 # This function is used to add an executable or library target which is built 00796 # using the MATLAB Compiler (MCC). It is invoked by basis_add_executable() 00797 # or basis_add_library(), respectively, when at least one M-file is given 00798 # as source file. Thus, it is recommended to use these functions instead. 00799 # 00800 # An install command for the added executable or library target is added by 00801 # this function as well. The executable will be installed as part of the 00802 # @p RUNTIME_COMPONENT in the directory @c INSTALL_RUNTIME_DIR. The runtime 00803 # library will be installed as part of the @p RUNTIME_COMPONENT in the directory 00804 # @c INSTALL_LIBRARY_DIR on UNIX systems and @c INSTALL_RUNTIME_DIR on Windows. 00805 # Static/import libraries will be installed as part of the @p LIBRARY_COMPONENT 00806 # in the directory @c INSTALL_ARCHIVE_DIR. 00807 # 00808 # @note The custom build command is not added yet by this function. 00809 # Only a custom target which stores all the information required to 00810 # setup this build command is added. The custom command is added 00811 # by either basis_project_finalize() or basis_superproject_finalize(). 00812 # This way, the properties such as the @c OUTPUT_NAME of the custom 00813 # target can be still modified. 00814 # 00815 # @note If this function is used within the @c PROJECT_TESTING_DIR, the built 00816 # executable is output to the @c BINARY_TESTING_DIR directory tree instead. 00817 # Moreover, no installation rules are added. Test executables are further 00818 # not exported, regardless of whether NO_EXPORT is given or not. 00819 # 00820 # @param [in] TARGET_NAME Name of the target. If a source file is given 00821 # as first argument, the build target name is derived 00822 # from the name of this source file. 00823 # @param [in] ARGN Remaining arguments such as in particular the 00824 # input source files. Moreover, the following arguments 00825 # are parsed: 00826 # @par 00827 # <table border="0"> 00828 # <tr> 00829 # @tp @b TYPE type @endtp 00830 # <td>Type of the target. Either @c EXECUTABLE (default) or @c LIBRARY.</td> 00831 # </tr> 00832 # <tr> 00833 # @tp @b COMPONENT name @endtp 00834 # <td>Name of the component. Default: @c BASIS_RUNTIME_COMPONENT if 00835 # @p TYPE is @c EXECUTABLE or @c BASIS_LIBRARY_COMPONENT, otherwise.</td> 00836 # </tr> 00837 # <tr> 00838 # @tp @b RUNTIME_COMPONENT name @endtp 00839 # <td>Name of runtime component. Default: @p COMPONENT if specified or 00840 # @c BASIS_RUNTIME_COMPONENT, otherwise.</td> 00841 # </tr> 00842 # <tr> 00843 # @tp @b LIBRARY_COMPONENT name @endtp 00844 # <td>Name of library component. Default: @p COMPONENT if specified or 00845 # @c BASIS_LIBRARY_COMPONENT, otherwise.</td> 00846 # </tr> 00847 # <tr> 00848 # @tp @b LIBEXEC @endtp 00849 # <td>Specifies that the built executable is an auxiliary executable 00850 # called by other executables only.</td> 00851 # </tr> 00852 # <tr> 00853 # @tp @b NO_EXPORT @endtp 00854 # <td>Do not export the target.</td> 00855 # </tr> 00856 # </table> 00857 # 00858 # @returns Adds custom target which builds depending on the @p TYPE argument 00859 # either an executable or a shared library using the MATLAB Compiler. 00860 # 00861 # @sa basis_add_executable() 00862 # @sa basis_add_library() 00863 # 00864 # @ingroup CMakeUtilities 00865 function (basis_add_mcc_target TARGET_NAME) 00866 # parse arguments 00867 CMAKE_PARSE_ARGUMENTS ( 00868 ARGN 00869 "LIBEXEC;TEST;NO_EXPORT" 00870 "TYPE;COMPONENT;RUNTIME_COMPONENT;LIBRARY_COMPONENT" 00871 "" 00872 ${ARGN} 00873 ) 00874 00875 basis_sanitize_for_regex (R "${PROJECT_TESTING_DIR}") 00876 if (CMAKE_CURRENT_SOURCE_DIR MATCHES "^${R}") 00877 set (ARGN_TEST TRUE) 00878 else () 00879 if (ARGN_TEST) 00880 message (FATAL_ERROR "Executable ${TARGET_NAME} cannot have TEST property!" 00881 "If it is a test executable, put it in ${PROJECT_TESTING_DIR}.") 00882 endif () 00883 set (ARGN_TEST FALSE) 00884 endif () 00885 00886 if (ARGN_TEST) 00887 set (ARGN_NO_EXPORT TRUE) 00888 endif () 00889 if (NOT ARGN_NO_EXPORT) 00890 set (ARGN_NO_EXPORT FALSE) 00891 endif () 00892 00893 if (NOT ARGN_TYPE) 00894 set (ARGN_TYPE "EXECUTABLE") 00895 else () 00896 string (TOUPPER "${ARGN_TYPE}" ARGN_TYPE) 00897 endif () 00898 00899 if (NOT ARGN_TYPE MATCHES "^EXECUTABLE$|^LIBRARY$") 00900 message (FATAL_ERROR "Invalid type for MCC target ${TARGET_NAME}: ${ARGN_TYPE}") 00901 endif () 00902 00903 if (NOT ARGN_LIBRARY_COMPONENT AND ARGN_COMPONENT) 00904 set (ARGN_LIBRARY_COMPONENT "${ARGN_COMPONENT}") 00905 endif () 00906 if (NOT ARGN_RUNTIME_COMPONENT AND ARGN_COMPONENT) 00907 set (ARGN_RUNTIME_COMPONENT "${ARGN_COMPONENT}") 00908 endif () 00909 00910 if (NOT ARGN_COMPONENT) 00911 if (ARGN_TYPE MATCHES "EXECUTABLE") 00912 set (ARGN_COMPONENT "${BASIS_RUNTIME_COMPONENT}") 00913 else () 00914 set (ARGN_COMPONENT "${BASIS_LIBRARY_COMPONENT}") 00915 endif () 00916 endif () 00917 if (NOT ARGN_COMPONENT) 00918 set (ARGN_COMPONENT "Unspecified") 00919 endif () 00920 00921 if (NOT ARGN_LIBRARY_COMPONENT) 00922 set (ARGN_LIBRARY_COMPONENT "${BASIS_LIBRARY_COMPONENT}") 00923 endif () 00924 if (NOT ARGN_LIBRARY_COMPONENT) 00925 set (ARGN_LIBRARY_COMPONENT "Unspecified") 00926 endif () 00927 00928 if (NOT ARGN_RUNTIME_COMPONENT) 00929 set (ARGN_RUNTIME_COMPONENT "${BASIS_RUNTIME_COMPONENT}") 00930 endif () 00931 if (NOT ARGN_RUNTIME_COMPONENT) 00932 set (ARGN_RUNTIME_COMPONENT "Unspecified") 00933 endif () 00934 00935 set (SOURCES) 00936 get_filename_component (S "${TARGET_NAME}" ABSOLUTE) 00937 if (NOT ARGN_UNPARSED_ARGUMENTS OR EXISTS "${S}") 00938 list (APPEND ARGN_UNPARSED_ARGUMENTS "${TARGET_NAME}") 00939 basis_get_source_target_name (TARGET_NAME "${TARGET_NAME}" NAME_WE) 00940 endif () 00941 foreach (ARG ${ARGN_UNPARSED_ARGUMENTS}) 00942 get_filename_component (SOURCE "${ARG}" ABSOLUTE) 00943 list (APPEND SOURCES "${SOURCE}") 00944 endforeach () 00945 00946 # check target name 00947 basis_check_target_name ("${TARGET_NAME}") 00948 basis_make_target_uid (TARGET_UID "${TARGET_NAME}") 00949 00950 if (BASIS_VERBOSE) 00951 if (ARGN_TYPE MATCHES "LIBRARY") 00952 message (STATUS "Adding MATLAB library ${TARGET_UID}...") 00953 message (FATAL_ERROR "Build of MATLAB library from M-files not yet supported.") 00954 message (STATUS "Adding MATLAB library ${TARGET_UID}... - failed") 00955 else () 00956 message (STATUS "Adding MATLAB executable ${TARGET_UID}...") 00957 endif () 00958 endif () 00959 00960 # required commands available ? 00961 if (NOT MATLAB_MCC_EXECUTABLE) 00962 message (FATAL_ERROR "MATLAB Compiler not found. It is required to build target ${TARGET_UID}." 00963 " Forgot to add MATLAB as dependency? Otherwise, set MATLAB_MCC_EXECUTABLE manually and try again.") 00964 endif () 00965 00966 # MCC flags 00967 set (COMPILE_FLAGS) 00968 00969 if (BASIS_MCC_FLAGS) 00970 string (REPLACE "\\ " " " COMPILE_FLAGS "${BASIS_MCC_FLAGS}") 00971 string (REPLACE " " ";" COMPILE_FLAGS "${COMPILE_FLAGS}") 00972 string (REPLACE " " " " COMPILE_FLAGS "${COMPILE_FLAGS}") 00973 endif () 00974 00975 # configure .in source files 00976 basis_configure_sources (SOURCES ${SOURCES}) 00977 00978 # add custom target 00979 add_custom_target (${TARGET_UID} ALL SOURCES ${SOURCES}) 00980 00981 # set target properties required by basis_add_mcc_target_finalize () 00982 if (ARGN_TYPE MATCHES "LIBRARY") 00983 set (TYPE "MCC_LIBRARY") 00984 else () 00985 set (TYPE "MCC_EXECUTABLE") 00986 if (ARGN_TEST) 00987 set (RUNTIME_INSTALL_DIR "") 00988 set (RUNTIME_OUTPUT_DIR "${TESTING_RUNTIME_DIR}") 00989 elseif (ARGN_LIBEXEC) 00990 set (RUNTIME_INSTALL_DIR "${INSTALL_LIBEXEC_DIR}") 00991 set (RUNTIME_OUTPUT_DIR "${BINARY_LIBEXEC_DIR}") 00992 else () 00993 set (RUNTIME_INSTALL_DIR "${INSTALL_RUNTIME_DIR}") 00994 set (RUNTIME_OUTPUT_DIR "${BINARY_RUNTIME_DIR}") 00995 endif () 00996 endif () 00997 00998 get_directory_property (INCLUDE_DIRS INCLUDE_DIRECTORIES) 00999 get_directory_property (LINK_DIRS LINK_DIRECTORIES) 01000 01001 _set_target_properties ( 01002 ${TARGET_UID} 01003 PROPERTIES 01004 BASIS_TYPE "${TYPE}" 01005 VERSION "${PROJECT_VERSION}" 01006 SOVERSION "${PROJECT_SOVERSION}" 01007 SOURCE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 01008 BINARY_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" 01009 RUNTIME_OUTPUT_DIRECTORY "${RUNTIME_OUTPUT_DIR}" 01010 LIBRARY_OUTPUT_DIRECTORY "${BINARY_LIBRARY_DIR}" 01011 RUNTIME_INSTALL_DIRECTORY "${RUNTIME_INSTALL_DIR}" 01012 LIBRARY_INSTALL_DIRECTORY "${INSTALL_LIBRARY_DIR}" 01013 BASIS_INCLUDE_DIRECTORIES "${INCLUDE_DIRS}" 01014 BASIS_LINK_DIRECTORIES "${LINK_DIRS}" 01015 COMPILE_FLAGS "${COMPILE_FLAGS}" 01016 LINK_DEPENDS "" 01017 RUNTIME_COMPONENT "${ARGN_RUNTIME_COMPONENT}" 01018 LIBRARY_COMPONENT "${ARGN_LIBRARY_COMPONENT}" 01019 NO_EXPORT "${ARGN_NO_EXPORT}" 01020 ) 01021 01022 if (ARGN_LIBEXEC) 01023 _set_target_properties (${TARGET_UID} PROPERTIES LIBEXEC 1) 01024 else () 01025 _set_target_properties (${TARGET_UID} PROPERTIES LIBEXEC 0) 01026 endif () 01027 01028 if (ARGN_TEST) 01029 _set_target_properties (${TARGET_UID} PROPERTIES TEST 1) 01030 else () 01031 _set_target_properties (${TARGET_UID} PROPERTIES TEST 0) 01032 endif () 01033 01034 # add target to list of targets 01035 basis_set_project_property (APPEND PROPERTY TARGETS "${TARGET_UID}") 01036 01037 if (BASIS_VERBOSE) 01038 if (ARGN_TYPE MATCHES "LIBRARY") 01039 message (STATUS "Adding MATLAB library ${TARGET_UID}... - done") 01040 else () 01041 message (STATUS "Adding MATLAB executable ${TARGET_UID}... - done") 01042 endif () 01043 endif () 01044 endfunction () 01045 01046 # ---------------------------------------------------------------------------- 01047 ## @brief Finalize addition of MATLAB Compiler target. 01048 # 01049 # This function uses the properties of the custom MATLAB Compiler target 01050 # added by basis_add_mcc_target() to create the custom build command and 01051 # adds this build command as dependency of this added target. 01052 # 01053 # @param [in] TARGET_UID "Global" target name. If this function is used 01054 # within the same project as basis_add_mcc_target(), 01055 # the "local" target name may be given alternatively. 01056 # 01057 # @returns Adds custom target(s) which actually performs the invocation 01058 # of the MATLAB Compiler using the values of the properties of 01059 # the target with UID @p TARGET_UID. 01060 # 01061 # @sa basis_add_mcc_target() 01062 # 01063 # @ingroup CMakeUtilities 01064 function (basis_add_mcc_target_finalize TARGET_UID) 01065 # if used within (sub-)project itself, allow user to specify "local" target name 01066 basis_get_target_uid (TARGET_UID "${TARGET_UID}") 01067 01068 # finalized before ? 01069 if (TARGET "_${TARGET_UID}") 01070 return () 01071 endif () 01072 01073 # does this target exist ? 01074 if (NOT TARGET "${TARGET_UID}") 01075 message (FATAL_ERROR "Unknown target ${TARGET_UID}.") 01076 return () 01077 endif () 01078 01079 # get target properties 01080 basis_get_target_name (TARGET_NAME ${TARGET_UID}) 01081 01082 set ( 01083 PROPERTIES 01084 "BASIS_TYPE" 01085 "SOURCE_DIRECTORY" 01086 "BINARY_DIRECTORY" 01087 "RUNTIME_OUTPUT_DIRECTORY" 01088 "LIBRARY_OUTPUT_DIRECTORY" 01089 "RUNTIME_INSTALL_DIRECTORY" 01090 "LIBRARY_INSTALL_DIRECTORY" 01091 "PREFIX" 01092 "OUTPUT_NAME" 01093 "SUFFIX" 01094 "VERSION" 01095 "SOVERSION" 01096 "BASIS_INCLUDE_DIRECTORIES" 01097 "BASIS_LINK_DIRECTORIES" 01098 "SOURCES" 01099 "COMPILE_FLAGS" 01100 "LINK_DEPENDS" 01101 "RUNTIME_COMPONENT" 01102 "LIBRARY_COMPONENT" 01103 "LIBEXEC" 01104 "TEST" 01105 "NO_EXPORT" 01106 ) 01107 01108 foreach (PROPERTY ${PROPERTIES}) 01109 get_target_property (${PROPERTY} ${TARGET_UID} ${PROPERTY}) 01110 endforeach () 01111 01112 if (NOT BASIS_TYPE MATCHES "^MCC_") 01113 message (FATAL_ERROR "Target ${TARGET_UID} has invalid BASIS_TYPE: ${BASIS_TYPE}") 01114 endif () 01115 01116 if (BASIS_TYPE MATCHES "MCC_LIBRARY") 01117 set (TYPE "LIBRARY") 01118 else () 01119 set (TYPE "EXECUTABLE") 01120 endif () 01121 01122 if (BASIS_VERBOSE) 01123 if (TYPE MATCHES "LIBRARY") 01124 message (STATUS "Adding build command for MATLAB library ${TARGET_UID}...") 01125 elseif (TYPE MATCHES "EXECUTABLE") 01126 message (STATUS "Adding build command for MATLAB executable ${TARGET_UID}...") 01127 else () 01128 message (FATAL_ERROR "Target ${TARGET_UID} has invalid TYPE: ${TYPE}") 01129 endif () 01130 endif () 01131 01132 # build directory 01133 list (GET SOURCES 0 BUILD_DIR) 01134 set (BUILD_DIR "${BUILD_DIR}.dir") 01135 01136 list (REMOVE_AT SOURCES 0) 01137 01138 # output name 01139 if (NOT OUTPUT_NAME) 01140 set (OUTPUT_NAME "${TARGET_NAME}") 01141 endif () 01142 if (PREFIX) 01143 set (OUTPUT_NAME "${PREFIX}${OUTPUT_NAME}") 01144 endif () 01145 if (SUFFIX) 01146 set (OUTPUT_NAME "${OUTPUT_NAME}${SUFFIX}") 01147 endif () 01148 01149 # initialize dependencies of custom build command 01150 set (DEPENDS ${SOURCES}) 01151 01152 # get list of libraries to link to (e.g., MEX-file) 01153 set (LINK_LIBS) 01154 01155 foreach (LIB ${LINK_DEPENDS}) 01156 basis_get_target_uid (UID "${LIB}") 01157 if (TARGET ${UID}) 01158 basis_get_target_location (LIB_FILE ${UID} ABSOLUTE) 01159 list (APPEND DEPENDS ${UID}) 01160 else () 01161 set (LIB_FILE "${LIB}") 01162 endif () 01163 list (APPEND LINK_LIBS "${LIB_FILE}") 01164 endforeach () 01165 01166 # assemble build command 01167 set (MCC_ARGS ${COMPILE_FLAGS}) # user specified flags 01168 foreach (INCLUDE_PATH ${BASIS_INCLUDE_DIRECTORIES}) # add directories added via 01169 list (FIND MCC_ARGS "${INCLUDE_PATH}" IDX) # basis_include_directories () 01170 if (EXISTS "${INCLUDE_PATH}" AND IDX EQUAL -1) # function to search path 01171 list (APPEND MCC_ARGS "-I" "${INCLUDE_PATH}") 01172 endif () 01173 endforeach () 01174 list (FIND BASIS_INCLUDE_DIRECTORIES "${SOURCE_DIRECTORY}" IDX) 01175 if (IDX EQUAL -1) 01176 # add current source directory to search path, 01177 # needed for build in MATLAB mode as working directory 01178 # differs from the current source directory then 01179 list (APPEND MCC_ARGS "-I" "${SOURCE_DIRECTORY}") 01180 endif () 01181 if (TYPE MATCHES "LIBRARY") 01182 list (APPEND MCC_ARGS "-l") # build library 01183 else () 01184 list (APPEND MCC_ARGS "-m") # build standalone application 01185 endif () 01186 list (APPEND MCC_ARGS "-d" "${BUILD_DIR}") # output directory 01187 list (APPEND MCC_ARGS "-o" "${OUTPUT_NAME}") # output name 01188 list (APPEND MCC_ARGS ${SOURCES}) # source (M-)files 01189 foreach (LIB ${LINK_LIBS}) # link libraries, e.g. MEX-files 01190 list (FIND MCC_ARGS "${LIB}" IDX) 01191 if (LIB AND IDX EQUAL -1) 01192 list (APPEND MCC_ARGS "-a" "${LIB}") 01193 endif () 01194 endforeach () 01195 #list (APPEND MCC_ARGS ${LINK_LIBS}) # link libraries, e.g. MEX-files 01196 01197 # build command for invocation of MATLAB Compiler in standalone mode 01198 set (BUILD_CMD "${MATLAB_MCC_EXECUTABLE}" ${MCC_ARGS}) 01199 set (BUILD_LOG "${BUILD_DIR}/mccBuild.log") 01200 set (WORKING_DIR "${SOURCE_DIRECTORY}") 01201 set (MATLAB_MODE OFF) 01202 01203 # build command for invocation of MATLAB Compiler in MATLAB mode 01204 if (BASIS_MCC_MATLAB_MODE) 01205 set (MATLAB_MODE ON) 01206 01207 if (NOT MATLAB_EXECUTABLE) 01208 message (WARNING "MATLAB executable not found. It is required to build target ${TARGET_UID} in MATLAB mode." 01209 " Forgot to MATLAB as dependency? Otherwise, set MATLAB_EXECUTABLE manually and try again or set BASIS_MCC_MATLAB_MODE to OFF." 01210 " Will build target ${TARGET_UID} in standalone mode instead.") 01211 set (MATLAB_MODE OFF) 01212 endif () 01213 01214 if (MATLAB_MODE) 01215 get_filename_component (WORKING_DIR "${BASIS_SCRIPT_MCC}" PATH) 01216 get_filename_component (MFUNC "${BASIS_SCRIPT_MCC}" NAME_WE) 01217 01218 set (MATLAB_CMD "${MFUNC} -q") # -q option quits MATLAB when build is finished 01219 foreach (MCC_ARG ${MCC_ARGS}) 01220 set (MATLAB_CMD "${MATLAB_CMD} ${MCC_ARG}") 01221 endforeach () 01222 01223 set ( 01224 BUILD_CMD 01225 "${MATLAB_EXECUTABLE}" # run MATLAB 01226 "-nosplash" # do not display splash screen on start up 01227 "-nodesktop" # run in command line mode 01228 #"-nojvm" # we do not need the Java Virtual Machine 01229 "-r" "${MATLAB_CMD}" # MATLAB command which invokes MATLAB Compiler 01230 ) 01231 endif () 01232 endif () 01233 01234 # relative paths used for comments of commands 01235 file (RELATIVE_PATH REL "${CMAKE_BINARY_DIR}" "${BUILD_DIR}/${OUTPUT_NAME}") 01236 01237 # output files of build command 01238 if (TYPE MATCHES "LIBRARY") 01239 set (BUILD_OUTPUT "${LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT_NAME}") 01240 01241 set ( 01242 POST_BUILD_COMMAND 01243 COMMAND "${CMAKE_COMMAND}" -E copy 01244 "${BUILD_DIR}/${OUTPUT_NAME}" 01245 "${LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT_NAME}" 01246 ) 01247 01248 set (BUILD_COMMENT "Building MATLAB library ${REL}...") 01249 else () 01250 set (BUILD_OUTPUT "${RUNTIME_OUTPUT_DIRECTORY}/${OUTPUT_NAME}") 01251 01252 set ( 01253 POST_BUILD_COMMAND 01254 COMMAND "${CMAKE_COMMAND}" -E copy 01255 "${BUILD_DIR}/${OUTPUT_NAME}" 01256 "${RUNTIME_OUTPUT_DIRECTORY}/${OUTPUT_NAME}" 01257 ) 01258 01259 set (BUILD_COMMENT "Building MATLAB executable ${REL}...") 01260 endif () 01261 01262 # add custom command to build executable using MATLAB Compiler 01263 add_custom_command ( 01264 OUTPUT ${BUILD_OUTPUT} 01265 # rebuild when input sources were modified 01266 DEPENDS ${DEPENDS} 01267 # invoke MATLAB Compiler in either MATLAB or standalone mode 01268 # wrapping command in CMake execute_process () command allows for inspection 01269 # parsing of command output for error messages and specification of timeout 01270 COMMAND "${CMAKE_COMMAND}" 01271 "-DCOMMAND=${BUILD_CMD}" 01272 "-DWORKING_DIRECTORY=${WORKING_DIR}" 01273 "-DTIMEOUT=${BASIS_MCC_TIMEOUT}" 01274 "-DRETRY_EXPRESSION=License checkout failed" 01275 "-DRETRY_ATTEMPTS=${BASIS_MCC_RETRY_ATTEMPTS}" 01276 "-DRETRY_DELAY=${BASIS_MCC_RETRY_DELAY}" 01277 "-DERROR_EXPRESSION=[E|e]rror" 01278 "-DOUTPUT_FILE=${BUILD_LOG}" 01279 "-DERROR_FILE=${BUILD_LOG}" 01280 "-DVERBOSE=OFF" 01281 "-DLOG_ARGS=ON" 01282 "-P" "${BASIS_SCRIPT_EXECUTE_PROCESS}" 01283 # post build command(s) 01284 ${POST_BUILD_COMMAND} 01285 # inform user where build log can be found 01286 COMMAND "${CMAKE_COMMAND}" -E echo "Build log written to ${BUILD_LOG}" 01287 # comment 01288 COMMENT "${BUILD_COMMENT}" 01289 VERBATIM 01290 ) 01291 01292 # add custom target 01293 if (TARGET "_${TARGET_UID}") 01294 message (FATAL_ERROR "There is another target named _${TARGET_UID}. " 01295 "BASIS uses target names starting with an underscore " 01296 "for custom targets which are required to build executables or " 01297 "shared libraries from MATLAB source files. " 01298 "Do not use leading underscores in target names.") 01299 endif () 01300 01301 add_custom_target ( 01302 _${TARGET_UID} 01303 DEPENDS ${BUILD_OUTPUT} 01304 SOURCES ${SOURCES} 01305 ) 01306 01307 add_dependencies (${TARGET_UID} _${TARGET_UID}) 01308 01309 # cleanup on "make clean" 01310 set_property ( 01311 DIRECTORY 01312 APPEND PROPERTY 01313 ADDITIONAL_MAKE_CLEAN_FILES 01314 ${BUILD_OUTPUT} 01315 "${BUILD_DIR}/${OUTPUT_NAME}.prj" 01316 "${BUILD_DIR}/mccExcludedFiles.log" 01317 "${BUILD_DIR}/mccBuild.log" 01318 "${BUILD_DIR}/readme.txt" 01319 ) 01320 01321 if (TYPE MATCHES "LIBRARY") 01322 else () 01323 set_property ( 01324 DIRECTORY 01325 APPEND PROPERTY 01326 ADDITIONAL_MAKE_CLEAN_FILES 01327 "${BUILD_DIR}/${OUTPUT_NAME}" 01328 "${BUILD_DIR}/run_${OUTPUT_NAME}.sh" 01329 "${BUILD_DIR}/${OUTPUT_NAME}_main.c" 01330 "${BUILD_DIR}/${OUTPUT_NAME}_mcc_component_data.c" 01331 ) 01332 endif () 01333 01334 # export target 01335 if (NOT NO_EXPORT) 01336 if (TEST) 01337 basis_set_project_property (APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}") 01338 else () 01339 basis_set_project_property (APPEND PROPERTY CUSTOM_EXPORT_TARGETS "${TARGET_UID}") 01340 endif () 01341 endif () 01342 01343 # install executable or library 01344 if (TYPE MATCHES "LIBRARY") 01345 # TODO 01346 else () 01347 if (TEST) 01348 # TODO Install (selected?) test executables 01349 else () 01350 install ( 01351 PROGRAMS ${BUILD_OUTPUT} 01352 DESTINATION "${RUNTIME_INSTALL_DIRECTORY}" 01353 COMPONENT "${RUNTIME_COMPONENT}" 01354 ) 01355 endif () 01356 endif () 01357 01358 if (BASIS_VERBOSE) 01359 if (TYPE MATCHES "LIBRARY") 01360 message (STATUS "Adding build command for MATLAB library ${TARGET_UID}... - done") 01361 else () 01362 message (STATUS "Adding build command for MATLAB executable ${TARGET_UID}... - done") 01363 endif () 01364 endif () 01365 endfunction ()