BASIS  r3148
InstallationTools.cmake
Go to the documentation of this file.
00001 ##############################################################################
00002 # @file  InstallationTools.cmake
00003 # @brief CMake functions used for installation.
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 ## @addtogroup CMakeUtilities
00014 # @{
00015 
00016 
00017 # ============================================================================
00018 # Installation
00019 # ============================================================================
00020 
00021 # ----------------------------------------------------------------------------
00022 ## @brief Specify rules to run at install time.
00023 #
00024 # This function replaces CMake's
00025 # <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:install">
00026 # install()</a> command.
00027 #
00028 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:install
00029 #
00030 # @ingroup CMakeAPI
00031 function (basis_install)
00032   install (${ARGN})
00033 endfunction ()
00034 
00035 # ----------------------------------------------------------------------------
00036 ## @brief Install content of source directory excluding typical files.
00037 #
00038 # Files which are excluded are typical backup files, system files, files
00039 # from revision control systems, and CMakeLists.txt files.
00040 #
00041 # Example:
00042 # @code
00043 # basis_install_directory("${INSTALL_DATA_DIR}")
00044 # basis_install_directory(. "${INSTALL_DATA_DIR}")
00045 # basis_install_directory("${CMAKE_CURRENT_SOURCE_DIR}" "${INSTALL_DATA_DIR}")
00046 # basis_install_directory(images "${INSTALL_DATA_DIR}/images")
00047 # @endcode
00048 #
00049 # @param [in] ARGN The first two arguments are extracted from the beginning
00050 #                  of this list in the named order (without option name),
00051 #                  and the remaining arguments are passed on to CMake's
00052 #                  <a href="http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:install">
00053 #                  <tt>install(DIRECTORY)</tt></a> command.
00054 # @par
00055 # <table border="0">
00056 #   <tr>
00057 #     @tp @b SOURCE @endtp
00058 #     <td>Source directory. Defaults to current source directory
00059 #         if only one argument, the @p DESTINATION, is given./td>
00060 #   </tr>
00061 #   <tr>
00062 #     @tp @b DESTINATION @endtp
00063 #     <td>Destination directory.</td>
00064 #   </tr>
00065 # </table>
00066 #
00067 # @sa http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:install
00068 #
00069 # @ingroup CMakeAPI
00070 function (basis_install_directory)
00071   if (ARGC EQUAL 1)
00072     set (SOURCE      "${CMAKE_CURRENT_SOURCE_DIR}")
00073     set (DESTINATION "${ARGV0}")
00074     set (OPTIONS     "${ARGV}")
00075     list (REMOVE_AT OPTIONS 0)
00076   elseif (ARGC GREATER 1)
00077     set (SOURCE      "${ARGV0}")
00078     set (DESTINATION "${ARGV1}")
00079     set (OPTIONS     "${ARGV}")
00080     list (REMOVE_AT OPTIONS 0 1)
00081   else ()
00082     message (FATAL_ERROR "Too few arguments given!")
00083   endif ()
00084   # check arguments
00085   if (NOT IS_ABSOLUTE "${SOURCE}")
00086     get_filename_component (SOURCE "${SOURCE}" ABSOLUTE)
00087   endif ()
00088   string (REGEX REPLACE "/+$" "" SOURCE "${SOURCE}")
00089   if (NOT IS_ABSOLUTE "${DESTINATION}")
00090     set (DESTINATION "${CMAKE_INSTALL_PREFIX}/${DESTINATION}")
00091   endif ()
00092   basis_sanitize_for_regex (PROJECT_SOURCE_DIR_RE "${PROJECT_SOURCE_DIR}")
00093   if ("${DESTINATION}" MATCHES "^${PROJECT_SOURCE_DIR_RE}")
00094     message (FATAL_ERROR "Installation directory ${DESTINATION} is inside the project source tree!")
00095   endif ()
00096   # parse options
00097   set (MATCH)
00098   set (EXCLUDE)
00099   set (COMPONENT)
00100   set (CONFIGURATIONS)
00101   set (RE)
00102   set (OPT)
00103   set (NUM)
00104   foreach (O IN LISTS OPTIONS)
00105     if (O MATCHES "^(FILES_MATCHING|.*PERMISSIONS|OPTIONAL|DESTINATION|DIRECTORY)$")
00106       message (FATAL_ERROR "Option ${O} not supported by basis_install_directory()!")
00107     endif ()
00108     if (OPT MATCHES "^(PATTERN|REGEX)$")
00109       if (NUM EQUAL 1)
00110         if (O MATCHES "^EXCLUDE$")
00111           list (APPEND EXCLUDE "${RE}")
00112         else ()
00113           list (APPEND MATCH   "${RE}")
00114         endif ()
00115         set (OPT)
00116         set (RE)
00117       else ()
00118         if (OPT MATCHES "PATTERN")
00119           string (REGEX REPLACE "(^|[^\\])\\*" "&#9734" O "${O}")
00120           basis_sanitize_for_regex (O "${O}")
00121           string (REPLACE "&#9734" ".*" O "${O}")
00122         endif ()
00123         set (RE  "${O}")
00124         set (NUM 1)
00125       endif ()
00126     elseif (OPT MATCHES "^COMPONENT$")
00127       set (COMPONENT "${O}")
00128       set (OPT)
00129     elseif (OPT MATCHES "^CONFIGURATIONS$")
00130       if (O MATCHES "^(PATTERN|REGEX|COMPONENT|CONFIGURATIONS)$")
00131         set (OPT)
00132       else ()
00133         list (APPEND CONFIGURATIONS "${O}")
00134         math (EXPR NUM "${NUM} + 1")
00135       endif ()
00136     endif ()
00137     if (O MATCHES "^(PATTERN|REGEX|COMPONENT|CONFIGURATIONS)$")
00138       if (OPT)
00139         message (FATAL_ERROR "basis_install_directory(): Option ${OPT} is missing an argument!")
00140       endif ()
00141       set (OPT ${O})
00142       set (NUM 0)
00143     endif ()
00144   endforeach ()
00145   if (OPT MATCHES "CONFIGURATIONS" AND NOT NUM GREATER 0)
00146     message (FATAL_ERROR "basis_install_directory(): Missing argument(s) for ${OPT} option!")
00147   elseif (OPT MATCHES "PATTERN|REGEX")
00148     if (NUM EQUAL 1)
00149       list (APPEND MATCH "${RE}")
00150     else ()
00151       message (FATAL_ERROR "basis_install_directory(): Missing argument(s) for ${OPT} option!")
00152     endif ()
00153   elseif (OPT MATCHES "COMPONENT")
00154     message (FATAL_ERROR "basis_install_directory(): Missing argument for ${OPT} option!")
00155   endif ()
00156   list (APPEND EXCLUDE "CMakeLists.txt$" "/.svn/" "/.git/" ".DS_Store$" ".*~$") # default excludes
00157   basis_list_to_delimited_string (MATCH   "|" NOAUTOQUOTE ${MATCH})
00158   basis_list_to_delimited_string (EXCLUDE "|" NOAUTOQUOTE ${EXCLUDE})
00159   string (REPLACE "\\" "\\\\" MATCH   "${MATCH}")
00160   string (REPLACE "\"" "\\\"" MATCH   "${MATCH}")
00161   string (REPLACE "\\" "\\\\" EXCLUDE "${EXCLUDE}")
00162   string (REPLACE "\"" "\\\"" EXCLUDE "${EXCLUDE}")
00163   # Add installation instructions. Note that install(DIRECTORY) is here not
00164   # used to avoid the generation of empty directories
00165   set (OPTIONS)
00166   if (CONFIGURATIONS)
00167     list (APPEND OPTIONS CONFIGURATIONS ${CONFIGURATIONS})
00168   endif ()
00169   if (COMPONENT)
00170     list (APPEND OPTIONS COMPONENT ${COMPONENT})
00171   endif ()
00172   install (CODE
00173  "# -----------------------------------------------------------------------
00174   # basis_install_directory(): ${SOURCE}
00175   set (BASIS_INSTALL_DIRECTORY_FILES)
00176   set (BASIS_INSTALL_DIRECTORY_SOURCE      \"${SOURCE}\")
00177   set (BASIS_INSTALL_DIRECTORY_DESTINATION \"\$ENV{DESTDIR}${DESTINATION}\")
00178   set (BASIS_INSTALL_DIRECTORY_MATCH       \"${MATCH}\")
00179   set (BASIS_INSTALL_DIRECTORY_EXCLUDE     \"${EXCLUDE}\")
00180   file (GLOB_RECURSE BASIS_INSTALL_DIRECTORY_ALL_FILES \"\${BASIS_INSTALL_DIRECTORY_SOURCE}/*\")
00181   foreach (BASIS_INSTALL_DIRECTORY_FILE IN LISTS BASIS_INSTALL_DIRECTORY_ALL_FILES)
00182     if (NOT BASIS_INSTALL_DIRECTORY_MATCH                                            OR
00183             BASIS_INSTALL_DIRECTORY_FILE MATCHES \"\${BASIS_INSTALL_DIRECTORY_MATCH}\" AND
00184         NOT BASIS_INSTALL_DIRECTORY_FILE MATCHES \"\${BASIS_INSTALL_DIRECTORY_EXCLUDE}\")
00185       list (APPEND BASIS_INSTALL_DIRECTORY_FILES \"\${BASIS_INSTALL_DIRECTORY_FILE}\")
00186    endif ()
00187   endforeach ()
00188   foreach (BASIS_INSTALL_DIRECTORY_FILE IN LISTS BASIS_INSTALL_DIRECTORY_FILES)
00189     file (RELATIVE_PATH BASIS_INSTALL_DIRECTORY_FILE \"\${BASIS_INSTALL_DIRECTORY_SOURCE}\" \"\${BASIS_INSTALL_DIRECTORY_FILE}\")
00190     execute_process (
00191       COMMAND \"${CMAKE_COMMAND}\" -E compare_files
00192                   \"\${BASIS_INSTALL_DIRECTORY_SOURCE}/\${BASIS_INSTALL_DIRECTORY_FILE}\"
00193                   \"\${BASIS_INSTALL_DIRECTORY_DESTINATION}/\${BASIS_INSTALL_DIRECTORY_FILE}\"
00194       RESULT_VARIABLE RC
00195       OUTPUT_QUIET
00196       ERROR_QUIET
00197     )
00198     if (RC EQUAL 0)
00199       message (STATUS \"Up-to-date: \${BASIS_INSTALL_DIRECTORY_DESTINATION}/\${BASIS_INSTALL_DIRECTORY_FILE}\")
00200     else ()
00201       message (STATUS \"Installing: \${BASIS_INSTALL_DIRECTORY_DESTINATION}/\${BASIS_INSTALL_DIRECTORY_FILE}\")
00202       execute_process (
00203         COMMAND \"${CMAKE_COMMAND}\" -E copy_if_different
00204             \"\${BASIS_INSTALL_DIRECTORY_SOURCE}/\${BASIS_INSTALL_DIRECTORY_FILE}\"
00205             \"\${BASIS_INSTALL_DIRECTORY_DESTINATION}/\${BASIS_INSTALL_DIRECTORY_FILE}\"
00206         RESULT_VARIABLE RC
00207         OUTPUT_QUIET
00208         ERROR_QUIET
00209       )
00210       if (RC EQUAL 0)
00211         list (APPEND CMAKE_INSTALL_MANIFEST_FILES \"\${BASIS_INSTALL_DIRECTORY_DESTINATION}/\${BASIS_INSTALL_DIRECTORY_FILE}\")
00212       else ()
00213         message (STATUS \"Failed to install \${BASIS_INSTALL_DIRECTORY_DESTINATION}/\${BASIS_INSTALL_DIRECTORY_FILE}\")
00214       endif ()
00215     endif ()
00216   endforeach ()
00217   # -----------------------------------------------------------------------"
00218     ${OPTIONS}
00219   )
00220 endfunction ()
00221 
00222 # ----------------------------------------------------------------------------
00223 ## @brief Add installation rule to create a symbolic link.
00224 #
00225 # Note that the installation rule will only be effective on a Unix-like
00226 # system, i.e., one which supports the creation of a symbolic link.
00227 #
00228 # @param [in] OLD  The value of the symbolic link.
00229 # @param [in] NEW  The name of the symbolic link.
00230 #
00231 # @returns Adds installation rule to create the symbolic link @p NEW.
00232 #
00233 # @ingroup CMakeAPI
00234 function (basis_install_link OLD NEW)
00235   # Attention: CMAKE_INSTALL_PREFIX must be used instead of CMAKE_INSTALL_PREFIX.
00236   set (CMD_IN
00237     "
00238     set (OLD \"@OLD@\")
00239     set (NEW \"@NEW@\")
00240 
00241     if (NOT IS_ABSOLUTE \"\${OLD}\")
00242       set (OLD \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${OLD}\")
00243     endif ()
00244     if (NOT IS_ABSOLUTE \"\${NEW}\")
00245       set (NEW \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${NEW}\")
00246     endif ()
00247 
00248     if (IS_SYMLINK \"\${NEW}\")
00249       file (REMOVE \"\${NEW}\")
00250     endif ()
00251 
00252     if (EXISTS \"\${NEW}\")
00253       message (STATUS \"Skipping: \${NEW} -> \${OLD}\")
00254     else ()
00255       message (STATUS \"Installing: \${NEW} -> \${OLD}\")
00256 
00257       get_filename_component (SYMDIR \"\${NEW}\" PATH)
00258 
00259       file (RELATIVE_PATH OLD \"\${SYMDIR}\" \"\${OLD}\")
00260 
00261       if (NOT EXISTS \${SYMDIR})
00262         file (MAKE_DIRECTORY \"\${SYMDIR}\")
00263       endif ()
00264 
00265       execute_process (
00266         COMMAND \"${CMAKE_COMMAND}\" -E create_symlink \"\${OLD}\" \"\${NEW}\"
00267         RESULT_VARIABLE RETVAL
00268       )
00269 
00270       if (NOT RETVAL EQUAL 0)
00271         message (ERROR \"Failed to create (symbolic) link \${NEW} -> \${OLD}\")
00272       else ()
00273         list (APPEND CMAKE_INSTALL_MANIFEST_FILES \"\${NEW}\")
00274       endif ()
00275     endif ()
00276     "
00277   )
00278 
00279   string (CONFIGURE "${CMD_IN}" CMD @ONLY)
00280   install (CODE "${CMD}")
00281 endfunction ()
00282 
00283 # ----------------------------------------------------------------------------
00284 ## @brief Adds installation rules to create default symbolic links.
00285 #
00286 # This function creates for each main executable a symbolic link directly
00287 # in the directory @c INSTALL_PREFIX/bin if @c INSTALL_SINFIX is TRUE and the
00288 # software is installed on a Unix-like system, i.e., one which
00289 # supports the creation of symbolic links.
00290 #
00291 # @returns Adds installation command for creation of symbolic links in the
00292 #          installation tree.
00293 function (basis_install_links)
00294   if (NOT UNIX)
00295     return ()
00296   endif ()
00297 
00298   # main executables
00299   basis_get_project_property (TARGETS PROPERTY TARGETS)
00300   foreach (TARGET_UID ${TARGETS})
00301     get_target_property (IMPORTED ${TARGET_UID} "IMPORTED")
00302 
00303     if (NOT IMPORTED)
00304       get_target_property (BASIS_TYPE ${TARGET_UID} "BASIS_TYPE")
00305       get_target_property (LIBEXEC    ${TARGET_UID} "LIBEXEC")
00306       get_target_property (TEST       ${TARGET_UID} "TEST")
00307 
00308       if (BASIS_TYPE MATCHES "EXECUTABLE" AND NOT LIBEXEC AND NOT TEST)
00309         get_target_property (SYMLINK_NAME ${TARGET_UID} "SYMLINK_NAME")
00310         if (NOT "${SYMLINK_NAME}" MATCHES "^none$|^None$|^NONE$")
00311           get_target_property (SYMLINK_PREFIX ${TARGET_UID} "SYMLINK_PREFIX")
00312           get_target_property (SYMLINK_SUFFIX ${TARGET_UID} "SYMLINK_SUFFIX")
00313           get_target_property (INSTALL_DIR    ${TARGET_UID} "RUNTIME_INSTALL_DIRECTORY")
00314           if (NOT INSTALL_DIR)
00315             get_target_property (INSTALL_DIR  ${TARGET_UID} "INSTALL_DIRECTORY")
00316           endif ()
00317 
00318           basis_get_target_location (OUTPUT_NAME ${TARGET_UID} NAME)
00319 
00320           if (NOT SYMLINK_NAME)
00321             set (SYMLINK_NAME "${OUTPUT_NAME}")
00322           endif ()
00323           if (SYMLINK_PREFIX)
00324             set (SYMLINK_NAME "${SYMLINK_PREFIX}${SYMLINK_NAME}")
00325           endif ()
00326           if (SYMLINK_SUFFIX)
00327             set (SYMLINK_NAME "${SYMLINK_NAME}${SYMLINK_SUFFIX}")
00328           endif ()
00329 
00330           # avoid creation of symbolic link if there would be a conflict with
00331           # the subdirectory in bin/ where the actual executables are installed
00332           if (INSTALL_SINFIX AND "${SYMLINK_NAME}" STREQUAL "${BASIS_INSALL_SINFIX}")
00333             message (STATUS \"Skipping: ${INSTALL_DIR}/${OUTPUT_NAME} -> ${INSTALL_PREFIX}/bin/${SYMLINK_NAME}\")
00334           else ()
00335             basis_install_link (
00336               "${INSTALL_DIR}/${OUTPUT_NAME}"
00337               "bin/${SYMLINK_NAME}"
00338             )
00339           endif ()
00340         endif ()
00341       endif ()
00342     endif ()
00343   endforeach ()
00344 endfunction ()
00345 
00346 # ============================================================================
00347 # Package registration
00348 # ============================================================================
00349 
00350 # ----------------------------------------------------------------------------
00351 ## @brief Register installed package with CMake.
00352 #
00353 # This function adds an entry to the CMake registry for packages with the
00354 # path of the directory where the package configuration file is located in
00355 # order to help CMake find the package.
00356 #
00357 # The uninstaller whose template can be found in cmake_uninstaller.cmake.in
00358 # is responsible for removing the registry entry again.
00359 function (basis_register_package)
00360   set (PKGDIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CONFIG_DIR}")
00361   set (PKGUID "${BASIS_PROJECT_PACKAGE_UID}")
00362   if (WIN32)
00363     install (CODE
00364       "execute_process (
00365          COMMAND reg add \"HKCU\\\\Software\\\\Kitware\\\\CMake\\\\Packages\\\\${PROJECT_PACKAGE_CONFIG_PREFIX}\" /v \"${PKGUID}\" /d \"${PKGDIR}\" /t REG_SZ /f
00366          RESULT_VARIABLE RT
00367          ERROR_VARIABLE  ERR
00368          OUTPUT_QUIET
00369        )
00370        if (RT EQUAL 0)
00371          message (STATUS \"Register:   Added HKEY_CURRENT_USER\\\\Software\\\\Kitware\\\\CMake\\\\Packages\\\\${PROJECT_PACKAGE_CONFIG_PREFIX}\\\\${PKGUID}\")
00372        else ()
00373          string (STRIP \"\${ERR}\" ERR)
00374          message (STATUS \"Register:   Failed to add registry entry: \${ERR}\")
00375        endif ()"
00376     )
00377   elseif (IS_DIRECTORY "$ENV{HOME}")
00378     file (WRITE "${PROJECT_BINARY_DIR}/${PROJECT_PACKAGE_CONFIG_PREFIX}RegistryFile" "${PKGDIR}")
00379     install (
00380       FILES       "${PROJECT_BINARY_DIR}/${PROJECT_PACKAGE_CONFIG_PREFIX}RegistryFile"
00381       DESTINATION "$ENV{HOME}/.cmake/packages/${PROJECT_PACKAGE_CONFIG_PREFIX}"
00382       RENAME      "${PKGUID}"
00383     )
00384   endif ()
00385 endfunction ()
00386 
00387 # ============================================================================
00388 # Deinstallation
00389 # ============================================================================
00390 
00391 # ----------------------------------------------------------------------------
00392 ## @brief Add uninstall target.
00393 #
00394 # @returns Adds the custom target @c uninstall and code to
00395 #          <tt>cmake_install.cmake</tt> to install an uninstaller.
00396 function (basis_add_uninstall)
00397   # add uninstall target
00398   configure_file (
00399     ${BASIS_MODULE_PATH}/cmake_uninstall.cmake.in
00400     ${PROJECT_BINARY_DIR}/cmake_uninstall.cmake
00401     @ONLY
00402   )
00403   add_custom_target (
00404     uninstall
00405     COMMAND ${CMAKE_COMMAND} -P "${PROJECT_BINARY_DIR}/cmake_uninstall.cmake"
00406     COMMENT "Uninstalling..."
00407   )
00408 endfunction ()
00409 
00410 
00411 ## @}
00412 # end of Doxygen group