BASIS  r3148
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|MEX")
00099       if (BASIS_TYPE MATCHES "MEX|MCC")
00100         set (TYPE SHARED)
00101       elseif (BASIS_TYPE MATCHES "SCRIPT")
00102         set (TYPE UNKNOWN)
00103       else ()
00104         string (REGEX REPLACE "_LIBRARY" "" TYPE "${BASIS_TYPE}")
00105       endif ()
00106       set (C "${C}add_library (${UID} ${TYPE} IMPORTED)\n")
00107     else ()
00108       message (FATAL_ERROR "Cannot export target ${T} of type ${BASIS_TYPE}! Use NOEXPORT option.")
00109     endif ()
00110     set (C "${C}set_target_properties (${UID} PROPERTIES BASIS_TYPE \"${BASIS_TYPE}\")\n")
00111   endforeach ()
00112   set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
00113 endfunction ()
00114 
00115 # ----------------------------------------------------------------------------
00116 ## @brief Add code to set properties of imported targets for build tree.
00117 function (basis_export_build_properties CODE)
00118   set (C)
00119   if (CMAKE_BUILD_TYPE)
00120     set (CONFIG "${CMAKE_BUILD_TYPE}")
00121   else ()
00122     set (CONFIG "noconfig")
00123   endif ()
00124   string (TOUPPER "${CONFIG}" CONFIG_U)
00125   foreach (T IN LISTS ARGN)
00126     basis_get_fully_qualified_target_uid (UID "${T}")
00127     get_target_property (BASIS_TYPE ${T} BASIS_TYPE)
00128     set (C "${C}\n# Import target \"${UID}\" for configuration \"${CONFIG}\"\n")
00129     set (C "${C}set_property (TARGET ${UID} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${CONFIG_U})\n")
00130     set (C "${C}set_target_properties (${UID} PROPERTIES\n")
00131     if (BASIS_TYPE MATCHES "SCRIPT|LIBRARY|MEX")
00132       get_target_property (LANGUAGE ${T} LANGUAGE)
00133       if (LANGUAGE)
00134         set (C "${C}  IMPORTED_LINK_INTERFACE_LANGUAGES_${CONFIG_U} \"${LANGUAGE}\"\n")
00135       endif ()
00136       get_target_property (LINK_DEPENDS ${T} LINK_DEPENDS)
00137       set (LINK_UIDS)
00138       foreach (LINK_DEPEND IN LISTS LINK_DEPENDS)
00139         basis_get_fully_qualified_target_uid (LINK_UID ${LINK_DEPEND})
00140         list (APPEND LINK_UIDS "${LINK_UID}")
00141       endforeach ()
00142       set (C "${C}  IMPORTED_LINK_INTERFACE_LIBRARIES_${CONFIG_U} \"${LINK_UIDS}\"\n")
00143     endif ()
00144     basis_get_target_location (LOCATION ${T} ABSOLUTE)
00145     set (C "${C}  IMPORTED_LOCATION_${CONFIG_U} \"${LOCATION}\"\n")
00146     set (C "${C}  )\n")
00147   endforeach ()
00148   set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
00149 endfunction ()
00150 
00151 # ----------------------------------------------------------------------------
00152 ## @brief Add code to set properties of imported targets for installation.
00153 function (basis_export_install_properties CODE)
00154   set (C)
00155   if (CMAKE_BUILD_TYPE)
00156     set (CONFIG "${CMAKE_BUILD_TYPE}")
00157   else ()
00158     set (CONFIG "noconfig")
00159   endif ()
00160   string (TOUPPER "${CONFIG}" CONFIG_U)
00161   foreach (T IN LISTS ARGN)
00162     basis_get_fully_qualified_target_uid (UID "${T}")
00163     get_target_property (BASIS_TYPE ${T} BASIS_TYPE)
00164     set (C "${C}\n# Import target \"${UID}\" for configuration \"${CONFIG}\"\n")
00165     set (C "${C}set_property (TARGET ${UID} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${CONFIG_U})\n")
00166     set (C "${C}set_target_properties (${UID} PROPERTIES\n")
00167     basis_get_target_location (LOCATION ${T} POST_INSTALL_RELATIVE)
00168     set (C "${C}  IMPORTED_LOCATION_${CONFIG_U} \"\${_IMPORT_PREFIX}/${LOCATION}\"\n")
00169     if (BASIS_TYPE MATCHES "SCRIPT|LIBRARY|MEX")
00170       get_target_property (LANGUAGE ${T} LANGUAGE)
00171       if (LANGUAGE)
00172         set (C "${C}  IMPORTED_LINK_INTERFACE_LANGUAGES_${CONFIG_U} \"${LANGUAGE}\"\n")
00173       endif ()
00174       get_target_property (LINK_DEPENDS ${T} LINK_DEPENDS)
00175       set (LINK_UIDS)
00176       foreach (LINK_DEPEND IN LISTS LINK_DEPENDS)
00177         basis_get_fully_qualified_target_uid (LINK_UID ${LINK_DEPEND})
00178         list (APPEND LINK_UIDS "${LINK_UID}")
00179       endforeach ()
00180       set (C "${C}  IMPORTED_LINK_INTERFACE_LIBRARIES_${CONFIG_U} \"${LINK_UIDS}\"\n")
00181     endif ()
00182     set (C "${C}  )\n")
00183   endforeach ()
00184   set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
00185 endfunction ()
00186 
00187 # ----------------------------------------------------------------------------
00188 ## @brief Add footer of exports file.
00189 function (basis_export_footer CODE)
00190   set (C "\n# Cleanup temporary variables.\n")
00191   set (C "${C}set (_IMPORT_PREFIX)\n")
00192   set (C "${C}\n# Commands beyond this point should not need to know the version.\n")
00193   set (C "${C}set (CMAKE_IMPORT_FILE_VERSION)\n")
00194   set (C "${C}cmake_policy (POP)\n")
00195   set (${CODE} "${${CODE}}${C}" PARENT_SCOPE)
00196 endfunction ()
00197 
00198 # ----------------------------------------------------------------------------
00199 ## @brief Export all targets added by basis_add_* commands.
00200 function (basis_export_targets)
00201   # parse arguments
00202   CMAKE_PARSE_ARGUMENTS (ARGN "" "FILE;CUSTOM_FILE" "" ${ARGN})
00203 
00204   if (NOT ARGN_FILE)
00205     message (FATAL_ERROR "basis_export_targets(): FILE option is required!")
00206   endif ()
00207   if (NOT ARGN_CUSTOM_FILE)
00208     message (FATAL_ERROR "basis_export_targets(): CUSTOM_FILE option is required!")
00209   endif ()
00210 
00211   if (IS_ABSOLUTE ARGN_FILE)
00212     message (FATAL_ERROR "basis_export_targets(): FILE option argument must be a relative path!")
00213   endif ()
00214   if (IS_ABSOLUTE ARGN_CUSTOM_FILE)
00215     message (FATAL_ERROR "basis_export_targets(): CUSTOM_FILE option argument must be a relative path!")
00216   endif ()
00217 
00218   # --------------------------------------------------------------------------
00219   # export non-custom targets
00220   basis_get_project_property (EXPORT_TARGETS)
00221   if (EXPORT_TARGETS)
00222     if (BASIS_USE_FULLY_QUALIFIED_UIDS)
00223       set (NAMESPACE_OPT)
00224     elseif (BASIS_PROJECT_NAMESPACE_CMAKE)
00225       set (NAMESPACE_OPT NAMESPACE "${BASIS_PROJECT_NAMESPACE_CMAKE}.")
00226     endif ()
00227     export (
00228       TARGETS   ${EXPORT_TARGETS}
00229       FILE      "${PROJECT_BINARY_DIR}/${ARGN_FILE}"
00230       ${NAMESPACE_OPT}
00231     )
00232     basis_get_project_property (INSTALL_EXPORT_TARGETS)
00233     if (INSTALL_EXPORT_TARGETS)
00234       foreach (COMPONENT "${BASIS_RUNTIME_COMPONENT}" "${BASIS_LIBRARY_COMPONENT}")
00235         install (
00236           EXPORT      "${PROJECT_NAME}"
00237           DESTINATION "${INSTALL_CONFIG_DIR}"
00238           FILE        "${ARGN_FILE}"
00239           COMPONENT   "${COMPONENT}"
00240           ${NAMESPACE_OPT}
00241         )
00242       endforeach ()
00243     endif ()
00244   endif ()
00245 
00246   # --------------------------------------------------------------------------
00247   # export custom targets and/or test targets
00248   basis_get_project_property (CUSTOM_EXPORT_TARGETS)
00249   basis_get_project_property (TEST_EXPORT_TARGETS)
00250 
00251   if (CUSTOM_EXPORT_TARGETS OR TEST_EXPORT_TARGETS)
00252 
00253     # write exports for build tree
00254     basis_export_header (CONTENT)
00255     basis_export_import_targets (CONTENT ${CUSTOM_EXPORT_TARGETS} ${TEST_EXPORT_TARGETS})
00256     basis_export_build_properties (CONTENT ${CUSTOM_EXPORT_TARGETS}  ${TEST_EXPORT_TARGETS})
00257     basis_export_footer (CONTENT)
00258 
00259     file (WRITE "${PROJECT_BINARY_DIR}/${ARGN_CUSTOM_FILE}" "${CONTENT}")
00260     unset (CONTENT)
00261 
00262     # write exports for installation - excluding test targets
00263     if (CUSTOM_EXPORT_TARGETS)
00264       set (INSTALL_EXPORT_FILE "${PROJECT_BINARY_DIR}/CMakeFiles/Export/${INSTALL_CONFIG_DIR}/${ARGN_CUSTOM_FILE}")
00265 
00266       basis_export_header (CONTENT)
00267       basis_export_prefix (CONTENT)
00268       basis_export_import_targets (CONTENT ${CUSTOM_EXPORT_TARGETS})
00269       basis_export_install_properties (CONTENT ${CUSTOM_EXPORT_TARGETS})
00270       basis_export_footer (CONTENT)
00271 
00272       file (WRITE "${INSTALL_EXPORT_FILE}" "${CONTENT}")
00273       unset (CONTENT)
00274 
00275       install (
00276         FILES       "${INSTALL_EXPORT_FILE}"
00277         DESTINATION "${INSTALL_CONFIG_DIR}"
00278       )
00279     endif ()
00280 
00281   endif ()
00282 endfunction ()
00283 
00284 
00285 ## @}
00286 # end of Doxygen group