BASIS  version 1.2.3 (revision 2104)
ExportTools.cmake
Go to the documentation of this file.
00001 ##############################################################################
00002 # @file  ExportTools.cmake
00003 # @brief Functions and macros for the export of targets.
00004 #
00005 # Copyright (c) 2011, 2012 University of Pennsylvania. All rights reserved.<br />
00006 # See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file.
00007 #
00008 # Contact: SBIA Group <sbia-software at uphs.upenn.edu>
00009 #
00010 # @ingroup CMakeTools
00011 ##############################################################################
00012 
00013 if (__BASIS_EXPORTIMPORTTOOLS_INCLUDED)
00014   return ()
00015 else ()
00016   set (__BASIS_EXPORTIMPORTTOOLS_INCLUDED TRUE)
00017 endif ()
00018 
00019 
00020 ## @addtogroup CMakeUtilities
00021 #  @{
00022 
00023 
00024 # ----------------------------------------------------------------------------
00025 ## @brief Get soname of object file.
00026 #
00027 # This function extracts the soname from object files in the ELF format on
00028 # systems where the objdump command is available. On all other systems,
00029 # an empty string is returned.
00030 #
00031 # @param [out] SONAME  The soname of the object file.
00032 # @param [in]  OBJFILE Object file in ELF format.
00033 function (basis_get_soname SONAME OBJFILE)
00034   # get absolute path of object file
00035   basis_get_target_uid (TARGET_UID ${OBJFILE})
00036   if (TARGET TARGET_UID)
00037     basis_get_target_location (OBJFILE ${TARGET_UID} ABSOLUTE)
00038   else ()
00039     get_filename_component (OBJFILE "${OBJFILE}" ABSOLUTE)
00040   endif ()
00041   # usually CMake did this already
00042   find_program (CMAKE_OBJDUMP NAMES objdump DOC "The objdump command")
00043   # run objdump and extract soname
00044   execute_process (
00045     COMMAND ${CMAKE_OBJDUMP} -p "${OBJFILE}"
00046     COMMAND sed -n "-e's/^[[:space:]]*SONAME[[:space:]]*//p'"
00047     RESULT_VARIABLE STATUS
00048     OUTPUT_VARIABLE SONAME_OUT
00049     ERROR_QUIET
00050   )
00051   # return
00052   if (STATUS EQUAL 0)
00053     set (${SONAME} "${SONAME_OUT}" PARENT_SCOPE)
00054   else ()
00055     set (${SONAME} "" PARENT_SCOPE)
00056   endif ()
00057 endfunction ()
00058 
00059 # ----------------------------------------------------------------------------
00060 ## @brief Generate header of exports file.
00061 function (basis_export_header CODE)
00062   set (C "# Generated by BASIS\n\n")
00063   set (C "${C}if (\"\${CMAKE_MAJOR_VERSION}.\${CMAKE_MINOR_VERSION}\" LESS 2.8)\n")
00064   set (C "${C}  message (FATAL_ERROR \"CMake >= 2.8.4 required\")\n")
00065   set (C "${C}endif ()\n")
00066   set (C "${C}cmake_policy (PUSH)\n")
00067   set (C "${C}cmake_policy (VERSION 2.8.4)\n")
00068   set (C "${C}#----------------------------------------------------------------\n")
00069   set (C "${C}# Generated CMake target import file.\n")
00070   set (C "${C}#----------------------------------------------------------------\n")
00071   set (C "${C}\n# Commands may need to know the format version.\n")
00072   set (C "${C}set (CMAKE_IMPORT_FILE_VERSION 1)\n")
00073   set (${CODE} "${C}" PARENT_SCOPE)
00074 endfunction ()
00075 
00076 # ----------------------------------------------------------------------------
00077 ## @brief Add code to compute prefix relative to @c INSTALL_CONFIG_DIR.
00078 function (basis_export_prefix CODE)
00079   set (C "\n# Compute the installation prefix relative to this file.\n")
00080   set (C "${C}get_filename_component (_IMPORT_PREFIX \"\${CMAKE_CURRENT_LIST_FILE}\" PATH)\n")
00081   string (REGEX REPLACE "[/\\]" ";" DIRS "${INSTALL_CONFIG_DIR}")
00082   foreach (D IN LISTS DIRS)
00083     set (C "${C}get_filename_component (_IMPORT_PREFIX \"\${_IMPORT_PREFIX}\" PATH)\n")
00084   endforeach ()
00085   set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
00086 endfunction ()
00087 
00088 # ----------------------------------------------------------------------------
00089 ## @brief Add code to add import targets.
00090 function (basis_export_import_targets CODE)
00091   set (C)
00092   foreach (T IN LISTS ARGN)
00093     basis_get_fully_qualified_target_uid (UID "${T}")
00094     set (C "${C}\n# Create import target \"${UID}\"\n")
00095     get_target_property (BASIS_TYPE ${T} "BASIS_TYPE")
00096     if (BASIS_TYPE MATCHES "EXECUTABLE")
00097       set (C "${C}add_executable (${UID} IMPORTED)\n")
00098     elseif (BASIS_TYPE MATCHES "LIBRARY|MODULE_SCRIPT|MEX")
00099       string (REGEX REPLACE "_LIBRARY" "" TYPE "${BASIS_TYPE}")
00100       if (TYPE MATCHES "MEX|MCC")
00101         set (TYPE "SHARED")
00102       elseif (TYPE MATCHES "^MODULE_SCRIPT$")
00103         set (TYPE "UNKNOWN")
00104       endif ()
00105       set (C "${C}add_library (${UID} ${TYPE} IMPORTED)\n")
00106     else ()
00107       message (FATAL_ERROR "Cannot export target ${T} of type ${BASIS_TYPE}! Use NO_EXPORT option.")
00108     endif ()
00109     set (C "${C}set_target_properties (${UID} PROPERTIES BASIS_TYPE \"${BASIS_TYPE}\")\n")
00110   endforeach ()
00111   set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
00112 endfunction ()
00113 
00114 # ----------------------------------------------------------------------------
00115 ## @brief Add code to set properties of imported targets for build tree.
00116 function (basis_export_build_properties CODE)
00117   set (C)
00118   if (CMAKE_BUILD_TYPE)
00119     set (CONFIG "${CMAKE_BUILD_TYPE}")
00120   else ()
00121     set (CONFIG "noconfig")
00122   endif ()
00123   string (TOUPPER "${CONFIG}" CONFIG_UPPER)
00124   foreach (T IN LISTS ARGN)
00125     basis_get_fully_qualified_target_uid (UID "${T}")
00126     set (C "${C}\n# Import target \"${UID}\" for configuration \"${CONFIG}\"\n")
00127     set (C "${C}set_property (TARGET ${UID} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${CONFIG})\n")
00128     set (C "${C}set_target_properties (${UID} PROPERTIES\n")
00129     basis_get_target_location (LOCATION ${T} ABSOLUTE)
00130     set (C "${C}  IMPORTED_LOCATION_${CONFIG_UPPER} \"${LOCATION}\"\n")
00131     if (BASIS_TYPE MATCHES "LIBRARY|MEX")
00132       set (C "${C}  IMPORTED_LINK_INTERFACE_LANGUAGES_${CONFIG_UPPER} \"CXX\"\n")
00133     endif ()
00134     set (C "${C}  )\n")
00135   endforeach ()
00136   set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
00137 endfunction ()
00138 
00139 # ----------------------------------------------------------------------------
00140 ## @brief Add code to set properties of imported targets for installation.
00141 function (basis_export_install_properties CODE)
00142   set (C)
00143   if (CMAKE_BUILD_TYPE)
00144     set (CONFIG "${CMAKE_BUILD_TYPE}")
00145   else ()
00146     set (CONFIG "noconfig")
00147   endif ()
00148   string (TOUPPER "${CONFIG}" CONFIG_UPPER)
00149   foreach (T IN LISTS ARGN)
00150     basis_get_fully_qualified_target_uid (UID "${T}")
00151     set (C "${C}\n# Import target \"${UID}\" for configuration \"${CONFIG}\"\n")
00152     set (C "${C}set_property (TARGET ${UID} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${CONFIG})\n")
00153     set (C "${C}set_target_properties (${UID} PROPERTIES\n")
00154     basis_get_target_location (LOCATION ${T} POST_INSTALL_RELATIVE)
00155     set (C "${C}  IMPORTED_LOCATION_${CONFIG_UPPER} \"\${_IMPORT_PREFIX}/${LOCATION}\"\n")
00156     if (BASIS_TYPE MATCHES "LIBRARY|MEX")
00157       set (C "${C}  IMPORTED_LINK_INTERFACE_LANGUAGES_${CONFIG_UPPER} \"CXX\"\n")
00158     endif ()
00159     set (C "${C}  )\n")
00160   endforeach ()
00161   set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
00162 endfunction ()
00163 
00164 # ----------------------------------------------------------------------------
00165 ## @brief Add footer of exports file.
00166 function (basis_export_footer CODE)
00167   set (C "\n# Cleanup temporary variables.\n")
00168   set (C "${C}set (_IMPORT_PREFIX)\n")
00169   set (C "${C}\n# Commands beyond this point should not need to know the version.\n")
00170   set (C "${C}set (CMAKE_IMPORT_FILE_VERSION)\n")
00171   set (C "${C}cmake_policy (POP)\n")
00172   set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
00173 endfunction ()
00174 
00175 # ----------------------------------------------------------------------------
00176 ## @brief Export all targets added by basis_add_* commands.
00177 function (basis_export_targets)
00178   # parse arguments
00179   CMAKE_PARSE_ARGUMENTS (ARGN "" "FILE;CUSTOM_FILE" "" ${ARGN})
00180 
00181   if (NOT ARGN_FILE)
00182     message (FATAL_ERROR "basis_export_targets(): FILE option is required!")
00183   endif ()
00184   if (NOT ARGN_CUSTOM_FILE)
00185     message (FATAL_ERROR "basis_export_targets(): CUSTOM_FILE option is required!")
00186   endif ()
00187 
00188   if (IS_ABSOLUTE ARGN_FILE)
00189     message (FATAL_ERROR "basis_export_targets(): FILE option argument must be a relative path!")
00190   endif ()
00191   if (IS_ABSOLUTE ARGN_CUSTOM_FILE)
00192     message (FATAL_ERROR "basis_export_targets(): CUSTOM_FILE option argument must be a relative path!")
00193   endif ()
00194 
00195   # --------------------------------------------------------------------------
00196   # export non-custom targets
00197   basis_get_project_property (EXPORT_TARGETS PROPERTY EXPORT_TARGETS)
00198 
00199   if (EXPORT_TARGETS)
00200     if (BASIS_USE_FULLY_QUALIFIED_UIDS)
00201       set (NAMESPACE_OPT)
00202     else ()
00203       set (NAMESPACE_OPT NAMESPACE "${BASIS_PROJECT_NAMESPACE_CMAKE}.")
00204     endif ()
00205 
00206     export (
00207       TARGETS   ${EXPORT_TARGETS}
00208       FILE      "${PROJECT_BINARY_DIR}/${ARGN_FILE}"
00209       ${NAMESPACE_OPT}
00210     )
00211     foreach (COMPONENT "${BASIS_RUNTIME_COMPONENT}" "${BASIS_LIBRARY_COMPONENT}")
00212       install (
00213         EXPORT      "${PROJECT_NAME}"
00214         DESTINATION "${INSTALL_CONFIG_DIR}"
00215         FILE        "${ARGN_FILE}"
00216         COMPONENT   "${COMPONENT}"
00217         ${NAMESPACE_OPT}
00218       )
00219     endforeach ()
00220   endif ()
00221 
00222   # --------------------------------------------------------------------------
00223   # export custom targets and/or test targets
00224   basis_get_project_property (CUSTOM_EXPORT_TARGETS)
00225   basis_get_project_property (TEST_EXPORT_TARGETS)
00226 
00227   if (CUSTOM_EXPORT_TARGETS OR TEST_EXPORT_TARGETS)
00228 
00229     # write exports for build tree
00230     basis_export_header (CONTENT)
00231     basis_export_import_targets (CONTENT ${CUSTOM_EXPORT_TARGETS} ${TEST_EXPORT_TARGETS})
00232     basis_export_build_properties (CONTENT ${CUSTOM_EXPORT_TARGETS}  ${TEST_EXPORT_TARGETS})
00233     basis_export_footer (CONTENT)
00234 
00235     file (WRITE "${PROJECT_BINARY_DIR}/${ARGN_CUSTOM_FILE}" "${CONTENT}")
00236     unset (CONTENT)
00237 
00238     # write exports for installation - excluding test targets
00239     if (CUSTOM_EXPORT_TARGETS)
00240       basis_export_header (CONTENT)
00241       basis_export_prefix (CONTENT)
00242       basis_export_import_targets (CONTENT ${CUSTOM_EXPORT_TARGETS})
00243       basis_export_install_properties (CONTENT ${CUSTOM_EXPORT_TARGETS})
00244       basis_export_footer (CONTENT)
00245 
00246       # DO NOT use '-' in the filename prefix for the custom exports.
00247       # Otherwise, it is automatically included by the exports file written
00248       # by CMake for the installation tree. This is, however, not the case
00249       # for the build tree. Therefore, we have to include the custom exports
00250       # file our selves in the use file.
00251       get_filename_component (TMP_FILE "${ARGN_CUSTOM_FILE}" NAME_WE)
00252 
00253       set (TMP_FILE "${TMP_FILE}.install")
00254       file (WRITE "${PROJECT_BINARY_DIR}/${TMP_FILE}" "${CONTENT}")
00255       unset (CONTENT)
00256 
00257       install (
00258         FILES       "${PROJECT_BINARY_DIR}/${TMP_FILE}"
00259         DESTINATION "${INSTALL_CONFIG_DIR}"
00260         RENAME      "${ARGN_CUSTOM_FILE}"
00261       )
00262     endif ()
00263 
00264   endif ()
00265 endfunction ()
00266 
00267 
00268 ## @}
00269 # end of Doxygen group