DeployQt4.cmake 13.2 KB
Newer Older
Mike McQuaid's avatar
Mike McQuaid committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
# - Functions to help assemble a standalone Qt4 executable.
# A collection of CMake utility functions useful for deploying
# Qt4 executables.
#
# The following functions are provided by this module:
#   write_qt4_conf
#   resolve_qt4_paths
#   fixup_qt4_executable
#   install_qt4_plugin_path
#   install_qt4_plugin
#   install_qt4_executable
# Requires CMake 2.6 or greater because it uses function and
# PARENT_SCOPE. Also depends on BundleUtilities.cmake.
#
#  WRITE_QT4_CONF(<qt_conf_dir> <qt_conf_contents>)
# Writes a qt.conf file with the <qt_conf_contents> into <qt_conf_dir>.
#
#  RESOLVE_QT4_PATHS(<paths_var> [<executable_path>])
# Loop through <paths_var> list and if any don't exist resolve them
# relative to the <executable_path> (if supplied) or the CMAKE_INSTALL_PREFIX.
#
#  FIXUP_QT4_EXECUTABLE(<executable> [<qtplugins> <libs> <dirs> <plugins_dir> <request_qt_conf>])
# Copies Qt plugins, writes a Qt configuration file (if needed) and fixes up a
# Qt4 executable using BundleUtilities so it is standalone and can be
# drag-and-drop copied to another machine as long as all of the system
# libraries are compatible.
#
# <executable> should point to the executable to be fixed-up.
#
# <qtplugins> should contain a list of the names or paths of any Qt plugins
# to be installed.
#
# <libs> will be passed to BundleUtilities and should be a list of any already
# installed plugins, libraries or executables to also be fixed-up.
#
# <dirs> will be passed to BundleUtilities and should contain and directories
# to be searched to find library dependencies.
#
# <plugins_dir> allows an custom plugins directory to be used.
#
# <request_qt_conf> will force a qt.conf file to be written even if not needed.
#
#  INSTALL_QT4_PLUGIN_PATH(plugin executable copy installed_plugin_path_var <plugins_dir> <component> <configurations>)
# Install (or copy) a resolved <plugin> to the default plugins directory
# (or <plugins_dir>) relative to <executable> and store the result in
# <installed_plugin_path_var>.
#
# If <copy> is set to TRUE then the plugins will be copied rather than
# installed. This is to allow this module to be used at CMake time rather than
# install time.
#
# If <component> is set then anything installed will use this COMPONENT.
#
#  INSTALL_QT4_PLUGIN(plugin executable copy installed_plugin_path_var <plugins_dir> <component>)
# Install (or copy) an unresolved <plugin> to the default plugins directory
# (or <plugins_dir>) relative to <executable> and store the result in
# <installed_plugin_path_var>. See documentation of INSTALL_QT4_PLUGIN_PATH.
#
59
#  INSTALL_QT4_EXECUTABLE(<executable> [<qtplugins> <libs> <dirs> <plugins_dir> <request_qt_conf> <component>])
Mike McQuaid's avatar
Mike McQuaid committed
60 61 62 63
# Installs Qt plugins, writes a Qt configuration file (if needed) and fixes up
# a Qt4 executable using BundleUtilities so it is standalone and can be
# drag-and-drop copied to another machine as long as all of the system
# libraries are compatible. The executable will be fixed-up at install time.
64
# <component> is the COMPONENT used for bundle fixup and plugin installation.
Mike McQuaid's avatar
Mike McQuaid committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
# See documentation of FIXUP_QT4_BUNDLE.

#=============================================================================
# Copyright 2011 Mike McQuaid <mike@mikemcquaid.com>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
#  License text for the above reference.)

# The functions defined in this file depend on the fixup_bundle function
# (and others) found in BundleUtilities.cmake

83
include("${CMAKE_CURRENT_LIST_DIR}/BundleUtilities.cmake")
Mike McQuaid's avatar
Mike McQuaid committed
84
set(DeployQt4_cmake_dir "${CMAKE_CURRENT_LIST_DIR}")
Mike McQuaid's avatar
Mike McQuaid committed
85
set(DeployQt4_apple_plugins_dir "PlugIns")
Mike McQuaid's avatar
Mike McQuaid committed
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103

function(write_qt4_conf qt_conf_dir qt_conf_contents)
        set(qt_conf_path "${qt_conf_dir}/qt.conf")
        message(STATUS "Writing ${qt_conf_path}")
        file(WRITE "${qt_conf_path}" "${qt_conf_contents}")
endfunction()

function(resolve_qt4_paths paths_var)
        set(executable_path ${ARGV1})

        set(paths_resolved)
        foreach(path ${${paths_var}})
                if(EXISTS "${path}")
                        list(APPEND paths_resolved "${path}")
                else()
                        if(${executable_path})
                                list(APPEND paths_resolved "${executable_path}/${path}")
                        else()
104
                                list(APPEND paths_resolved "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${path}")
Mike McQuaid's avatar
Mike McQuaid committed
105 106 107 108 109 110
                        endif()
                endif()
        endforeach()
        set(${paths_var} ${paths_resolved} PARENT_SCOPE)
endfunction()

111 112
function(fixup_qt4_executable executable)
        set(qtplugins ${ARGV1})
Mike McQuaid's avatar
Mike McQuaid committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
        set(libs ${ARGV2})
        set(dirs ${ARGV3})
        set(plugins_dir ${ARGV4})
        set(request_qt_conf ${ARGV5})

        message(STATUS "fixup_qt4_executable")
        message(STATUS "  executable='${executable}'")
        message(STATUS "  qtplugins='${qtplugins}'")
        message(STATUS "  libs='${libs}'")
        message(STATUS "  dirs='${dirs}'")
        message(STATUS "  plugins_dir='${plugins_dir}'")
        message(STATUS "  request_qt_conf='${request_qt_conf}'")

        if(QT_LIBRARY_DIR)
                list(APPEND dirs "${QT_LIBRARY_DIR}")
        endif()
129 130 131
        if(QT_BINARY_DIR)
                list(APPEND dirs "${QT_BINARY_DIR}")
        endif()
Mike McQuaid's avatar
Mike McQuaid committed
132 133 134 135 136

        if(APPLE)
                set(qt_conf_dir "${executable}/Contents/Resources")
                set(executable_path "${executable}")
                set(write_qt_conf TRUE)
Mike McQuaid's avatar
Mike McQuaid committed
137 138 139
                if(NOT plugins_dir)
                        set(plugins_dir "${DeployQt4_apple_plugins_dir}")
                endif()
Mike McQuaid's avatar
Mike McQuaid committed
140 141 142 143 144 145 146 147 148 149 150
        else()
                get_filename_component(executable_path "${executable}" PATH)
                if(NOT executable_path)
                        set(executable_path ".")
                endif()
                set(qt_conf_dir "${executable_path}")
                set(write_qt_conf ${request_qt_conf})
        endif()

        foreach(plugin ${qtplugins})
                set(installed_plugin_path "")
Mike McQuaid's avatar
Mike McQuaid committed
151
                install_qt4_plugin("${plugin}" "${executable}" 1 installed_plugin_path)
Mike McQuaid's avatar
Mike McQuaid committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
                list(APPEND libs ${installed_plugin_path})
        endforeach()

        foreach(lib ${libs})
                if(NOT EXISTS "${lib}")
                        message(FATAL_ERROR "Library does not exist: ${lib}")
                endif()
        endforeach()

        resolve_qt4_paths(libs "${executable_path}")

        if(write_qt_conf)
                set(qt_conf_contents "[Paths]\nPlugins = ${plugins_dir}")
                write_qt4_conf("${qt_conf_dir}" "${qt_conf_contents}")
        endif()

        fixup_bundle("${executable}" "${libs}" "${dirs}")
endfunction()

function(install_qt4_plugin_path plugin executable copy installed_plugin_path_var)
        set(plugins_dir ${ARGV4})
        set(component ${ARGV5})
        set(configurations ${ARGV6})
        if(EXISTS "${plugin}")
                if(APPLE)
Mike McQuaid's avatar
Mike McQuaid committed
177 178 179
                        if(NOT plugins_dir)
                                set(plugins_dir "${DeployQt4_apple_plugins_dir}")
                        endif()
Mike McQuaid's avatar
Mike McQuaid committed
180 181
                        set(plugins_path "${executable}/Contents/${plugins_dir}")
                else()
Mike McQuaid's avatar
Mike McQuaid committed
182 183 184 185 186 187
                        get_filename_component(plugins_path "${executable}" PATH)
                        if(NOT plugins_path)
                                set(plugins_path ".")
                        endif()
                        if(plugins_dir)
                                set(plugins_path "${plugins_path}/${plugins_dir}")
Mike McQuaid's avatar
Mike McQuaid committed
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
                        endif()
                endif()

                set(plugin_group "")

                get_filename_component(plugin_path "${plugin}" PATH)
                get_filename_component(plugin_parent_path "${plugin_path}" PATH)
                get_filename_component(plugin_parent_dir_name "${plugin_parent_path}" NAME)
                get_filename_component(plugin_name "${plugin}" NAME)
                string(TOLOWER "${plugin_parent_dir_name}" plugin_parent_dir_name)

                if("${plugin_parent_dir_name}" STREQUAL "plugins")
                        get_filename_component(plugin_group "${plugin_path}" NAME)
                        set(${plugin_group_var} "${plugin_group}")
                endif()
                set(plugins_path "${plugins_path}/${plugin_group}")

                if(${copy})
                        file(MAKE_DIRECTORY "${plugins_path}")
                        file(COPY "${plugin}" DESTINATION "${plugins_path}")
                else()
                        if(configurations AND (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE))
                                set(configurations CONFIGURATIONS ${configurations})
211 212
                        else()
                                unset(configurations)
Mike McQuaid's avatar
Mike McQuaid committed
213 214 215
                        endif()
                        install(FILES "${plugin}" DESTINATION "${plugins_path}" ${configurations} ${component})
                endif()
216
                set(${installed_plugin_path_var} "${plugins_path}/${plugin_name}" PARENT_SCOPE)
Mike McQuaid's avatar
Mike McQuaid committed
217 218 219 220 221 222 223 224 225
        endif()
endfunction()

function(install_qt4_plugin plugin executable copy installed_plugin_path_var)
        set(plugins_dir ${ARGV4})
        set(component ${ARGV5})
        if(EXISTS "${plugin}")
                install_qt4_plugin_path("${plugin}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}")
        else()
226
                string(TOUPPER "QT_${plugin}_PLUGIN" plugin_var)
227 228 229 230 231
                set(plugin_release_var "${plugin_var}_RELEASE")
                set(plugin_debug_var "${plugin_var}_DEBUG")
                set(plugin_release "${${plugin_release_var}}")
                set(plugin_debug "${${plugin_debug_var}}")
                if(DEFINED "${plugin_release_var}" AND DEFINED "${plugin_debug_var}" AND NOT EXISTS "${plugin_release}" AND NOT EXISTS "${plugin_debug}")
Mike McQuaid's avatar
Mike McQuaid committed
232 233
                        message(WARNING "Qt plugin \"${plugin}\" not recognized or found.")
                endif()
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
                if(NOT EXISTS "${${plugin_debug_var}}")
                        set(plugin_debug "${plugin_release}")
                endif()

                if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
                        install_qt4_plugin_path("${plugin_release}" "${executable}" "${copy}" "${installed_plugin_path_var}_release" "${plugins_dir}" "${component}" "Release|RelWithDebInfo|MinSizeRel")
                        install_qt4_plugin_path("${plugin_debug}" "${executable}" "${copy}" "${installed_plugin_path_var}_debug" "${plugins_dir}" "${component}" "Debug")

                        if(CMAKE_BUILD_TYPE MATCHES "^Debug$")
                                set(${installed_plugin_path_var} ${${installed_plugin_path_var}_debug})
                        else()
                                set(${installed_plugin_path_var} ${${installed_plugin_path_var}_release})
                        endif()
                else()
                        install_qt4_plugin_path("${plugin_release}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}")
                endif()
Mike McQuaid's avatar
Mike McQuaid committed
250
        endif()
251
        set(${installed_plugin_path_var} ${${installed_plugin_path_var}} PARENT_SCOPE)
Mike McQuaid's avatar
Mike McQuaid committed
252 253 254 255 256 257 258 259
endfunction()

function(install_qt4_executable executable)
        set(qtplugins ${ARGV1})
        set(libs ${ARGV2})
        set(dirs ${ARGV3})
        set(plugins_dir ${ARGV4})
        set(request_qt_conf ${ARGV5})
260
        set(component ${ARGV6})
Mike McQuaid's avatar
Mike McQuaid committed
261 262 263
        if(QT_LIBRARY_DIR)
                list(APPEND dirs "${QT_LIBRARY_DIR}")
        endif()
264 265 266
        if(QT_BINARY_DIR)
                list(APPEND dirs "${QT_BINARY_DIR}")
        endif()
267 268 269 270 271
        if(component)
                set(component COMPONENT ${component})
        else()
                unset(component)
        endif()
Mike McQuaid's avatar
Mike McQuaid committed
272 273

        get_filename_component(executable_absolute "${executable}" ABSOLUTE)
274 275 276 277 278
        if(EXISTS "${QT_QTCORE_LIBRARY_RELEASE}")
            gp_file_type("${executable_absolute}" "${QT_QTCORE_LIBRARY_RELEASE}" qtcore_type)
        elseif(EXISTS "${QT_QTCORE_LIBRARY_DEBUG}")
            gp_file_type("${executable_absolute}" "${QT_QTCORE_LIBRARY_DEBUG}" qtcore_type)
        endif()
Mike McQuaid's avatar
Mike McQuaid committed
279 280 281 282
        if(qtcore_type STREQUAL "system")
                set(qt_plugins_dir "")
        endif()

283 284 285 286 287 288 289 290 291
        if(QT_IS_STATIC)
                message(WARNING "Qt built statically: not installing plugins.")
        else()
                foreach(plugin ${qtplugins})
                        set(installed_plugin_paths "")
                        install_qt4_plugin("${plugin}" "${executable}" 0 installed_plugin_paths "${plugins_dir}" "${component}")
                        list(APPEND libs ${installed_plugin_paths})
                endforeach()
        endif()
Mike McQuaid's avatar
Mike McQuaid committed
292

293
        resolve_qt4_paths(libs "")
Mike McQuaid's avatar
Mike McQuaid committed
294 295

        install(CODE
296 297
  "include(\"${DeployQt4_cmake_dir}/DeployQt4.cmake\")
  set(BU_CHMOD_BUNDLE_ITEMS TRUE)
298
  FIXUP_QT4_EXECUTABLE(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${executable}\" \"\" \"${libs}\" \"${dirs}\" \"${plugins_dir}\" \"${request_qt_conf}\")"
299
                ${component}
Mike McQuaid's avatar
Mike McQuaid committed
300 301
        )
endfunction()