1# ============================================================================== 2# Medical Image Registration ToolKit (MIRTK) 3# 4# Copyright 2013-2015 Imperial College London 5# Copyright 2013-2015 Andreas Schuh 6# 7# Licensed under the Apache License, Version 2.0 (the "License"); 8# you may not use this file except in compliance with the License. 9# You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, software 14# distributed under the License is distributed on an "AS IS" BASIS, 15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16# See the License for the specific language governing permissions and 17# limitations under the License. 18# ============================================================================== 19 20if (COMMAND mirtk_add_executable) 21 return() 22endif () 23 24# Name of subdirectory of MIRTK command executables. 25# This variable is also used by the Applications module and therefore global. 26if (WIN32) 27 set(MIRTK_TOOLS_SUBDIR "Tools") 28else () 29 set(MIRTK_TOOLS_SUBDIR "tools") 30endif () 31 32# ------------------------------------------------------------------------------ 33## Add build target for executable MIRTK command 34function(mirtk_add_executable target_name) 35 # Parse arguments 36 if (NOT PROJECT_NAME) 37 message(FATAL_ERROR "mirtk_add_executable called outside project scope!") 38 endif () 39 if (NOT COMMAND cmake_parse_arguments) 40 include("${CMAKE_ROOT}/Modules/CMakeParseArguments.cmake") 41 endif () 42 cmake_parse_arguments(TARGET "" "" "SOURCES;DEPENDS;OPTIONAL" ${ARGN}) 43 if (TARGET_UNPARSED_ARGUMENTS) 44 message(FATAL_ERROR "mirtk_add_executable called with unrecognized arguments: ${TARGET_UNPARSED_ARGUMENTS}!") 45 endif () 46 if (target_name MATCHES "^(commands|commands-help)$") 47 message(FATAL_ERROR "Internally used target name cannot be used for command: ${target_name}") 48 endif () 49 # Add executable target 50 set(LANGUAGE CXX) 51 set(BINARY_LIBEXEC_DIR "${BINARY_LIBEXEC_DIR}/${MIRTK_TOOLS_SUBDIR}") 52 if (MIRTK_TOOLS_DIR) 53 set(INSTALL_LIBEXEC_DIR "${MIRTK_TOOLS_DIR}") 54 else () 55 set(INSTALL_LIBEXEC_DIR "${INSTALL_LIBEXEC_DIR}/${MIRTK_TOOLS_SUBDIR}") 56 endif () 57 if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${target_name}.cc") 58 basis_add_executable(${target_name}.cc ${TARGET_SOURCES} LIBEXEC) 59 elseif (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${target_name}.cxx") 60 basis_add_executable(${target_name}.cxx ${TARGET_SOURCES} LIBEXEC) 61 elseif (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${target_name}.cpp") 62 basis_add_executable(${target_name}.cpp ${TARGET_SOURCES} LIBEXEC) 63 elseif (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${target_name}.py" OR 64 EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${target_name}.py.in") 65 basis_add_executable(${target_name}.py ${TARGET_SOURCES} LIBEXEC FINAL) 66 set(LANGUAGE PYTHON) 67 elseif (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${target_name}.sh" OR 68 EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${target_name}.sh.in") 69 basis_add_executable(${target_name}.sh ${TARGET_SOURCES} LIBEXEC FINAL) 70 set(LANGUAGE BASH) 71 else () 72 message(FATAL_ERROR "Source file for MIRTK command ${target_name} not found!" 73 " Must have extension '.cc', '.cxx', '.cpp', '.sh', or '.py'." 74 " Exclude extension from mirtk_add_executable argument.") 75 endif () 76 set_property(GLOBAL APPEND PROPERTY MIRTK_COMMANDS ${target_name}) 77 if (LANGUAGE STREQUAL CXX) 78 basis_get_target_uid(target_uid "${target_name}") 79 # Add target dependencies 80 if (TARGET_DEPENDS OR TARGET_OPTIONAL) 81 if (NOT COMMAND mirtk_target_dependencies) 82 include("${MIRTK_MODULE_PATH}/mirtkTargetDependencies.cmake") 83 endif () 84 mirtk_target_dependencies(${target_name} ${TARGET_DEPENDS}) 85 mirtk_target_dependencies(${target_name} ${TARGET_OPTIONAL} OPTIONAL) 86 endif () 87 # Set RPATH of installed binary 88 # 89 # Would be set automatically by basis_project_end/mirtk_project_end when 90 # BASIS_INSTALL_RPATH is set to TRUE/ON in mirtk_project_begin instead. 91 # This requires, however, the use of basis_target_link_libraries instead of 92 # the CMake target_link_libraries command for basis_get_target_link_libraries 93 # used by basis_set_target_install_rpath to work. This function is very 94 # costly. Hence, as we know what RPATH we want without inspecting the list 95 # of all link dependencies, we rather set the INSTALL_RPATH ourselves. 96 if (CMAKE_HOST_APPLE) 97 set(ORIGIN "@loader_path") 98 else () 99 set(ORIGIN "\$ORIGIN") 100 endif () 101 basis_get_relative_path(rpath 102 "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBEXEC_DIR}" 103 "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBRARY_DIR}" 104 ) 105 string(REGEX REPLACE "/+$" "" rpath "${rpath}") 106 set_target_properties(${target_uid} PROPERTIES INSTALL_RPATH "${ORIGIN}/${rpath}") 107 endif () 108endfunction() 109