DeployQt4.cmake 14.7 KB
Newer Older
1 2 3 4 5 6 7 8
#.rst:
# DeployQt4
# ---------
#
# Functions to help assemble a standalone Qt4 executable.
#
# A collection of CMake utility functions useful for deploying Qt4
# executables.
Mike McQuaid's avatar
Mike McQuaid committed
9 10
#
# The following functions are provided by this module:
11 12 13 14 15 16 17 18 19 20
#
# ::
#
#    write_qt4_conf
#    resolve_qt4_paths
#    fixup_qt4_executable
#    install_qt4_plugin_path
#    install_qt4_plugin
#    install_qt4_executable
#
Mike McQuaid's avatar
Mike McQuaid committed
21
# Requires CMake 2.6 or greater because it uses function and
22 23 24 25 26
# PARENT_SCOPE.  Also depends on BundleUtilities.cmake.
#
# ::
#
#   WRITE_QT4_CONF(<qt_conf_dir> <qt_conf_contents>)
Mike McQuaid's avatar
Mike McQuaid committed
27 28 29
#
# Writes a qt.conf file with the <qt_conf_contents> into <qt_conf_dir>.
#
30 31 32 33
# ::
#
#   RESOLVE_QT4_PATHS(<paths_var> [<executable_path>])
#
Mike McQuaid's avatar
Mike McQuaid committed
34
# Loop through <paths_var> list and if any don't exist resolve them
35 36 37 38
# relative to the <executable_path> (if supplied) or the
# CMAKE_INSTALL_PREFIX.
#
# ::
Mike McQuaid's avatar
Mike McQuaid committed
39
#
40 41
#   FIXUP_QT4_EXECUTABLE(<executable>
#     [<qtplugins> <libs> <dirs> <plugins_dir> <request_qt_conf>])
42 43 44 45 46
#
# 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.
Mike McQuaid's avatar
Mike McQuaid committed
47 48 49
#
# <executable> should point to the executable to be fixed-up.
#
50 51
# <qtplugins> should contain a list of the names or paths of any Qt
# plugins to be installed.
Mike McQuaid's avatar
Mike McQuaid committed
52
#
53 54 55
# <libs> will be passed to BundleUtilities and should be a list of any
# already installed plugins, libraries or executables to also be
# fixed-up.
Mike McQuaid's avatar
Mike McQuaid committed
56
#
57 58
# <dirs> will be passed to BundleUtilities and should contain and
# directories to be searched to find library dependencies.
Mike McQuaid's avatar
Mike McQuaid committed
59 60 61
#
# <plugins_dir> allows an custom plugins directory to be used.
#
62 63 64 65 66
# <request_qt_conf> will force a qt.conf file to be written even if not
# needed.
#
# ::
#
67 68
#   INSTALL_QT4_PLUGIN_PATH(plugin executable copy installed_plugin_path_var
#                           <plugins_dir> <component> <configurations>)
Mike McQuaid's avatar
Mike McQuaid committed
69 70 71 72 73 74
#
# 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
75 76
# installed.  This is to allow this module to be used at CMake time
# rather than install time.
Mike McQuaid's avatar
Mike McQuaid committed
77 78 79
#
# If <component> is set then anything installed will use this COMPONENT.
#
80 81
# ::
#
82 83
#   INSTALL_QT4_PLUGIN(plugin executable copy installed_plugin_path_var
#                      <plugins_dir> <component>)
84 85 86 87 88 89 90 91
#
# 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.
#
# ::
#
92 93
#   INSTALL_QT4_EXECUTABLE(<executable>
#     [<qtplugins> <libs> <dirs> <plugins_dir> <request_qt_conf> <component>])
94 95 96 97 98 99 100
#
# 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.  <component> is the COMPONENT used for bundle fixup
# and plugin installation.  See documentation of FIXUP_QT4_BUNDLE.
Mike McQuaid's avatar
Mike McQuaid committed
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117

#=============================================================================
# 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

118
include("${CMAKE_CURRENT_LIST_DIR}/BundleUtilities.cmake")
Mike McQuaid's avatar
Mike McQuaid committed
119
set(DeployQt4_cmake_dir "${CMAKE_CURRENT_LIST_DIR}")
Mike McQuaid's avatar
Mike McQuaid committed
120
set(DeployQt4_apple_plugins_dir "PlugIns")
Mike McQuaid's avatar
Mike McQuaid committed
121 122 123 124 125 126 127 128

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)
129 130 131 132
        unset(executable_path)
        if(ARGC GREATER 1)
                set(executable_path ${ARGV1})
        endif()
Mike McQuaid's avatar
Mike McQuaid committed
133 134 135 136 137 138 139 140 141

        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()
142
                                list(APPEND paths_resolved "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${path}")
Mike McQuaid's avatar
Mike McQuaid committed
143 144 145 146 147 148
                        endif()
                endif()
        endforeach()
        set(${paths_var} ${paths_resolved} PARENT_SCOPE)
endfunction()

149
function(fixup_qt4_executable executable)
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
        unset(qtplugins)
        if(ARGC GREATER 1)
                set(qtplugins ${ARGV1})
        endif()
        unset(libs)
        if(ARGC GREATER 2)
                set(libs ${ARGV2})
        endif()
        unset(dirs)
        if(ARGC GREATER 3)
                set(dirs ${ARGV3})
        endif()
        unset(plugins_dir)
        if(ARGC GREATER 4)
                set(plugins_dir ${ARGV4})
        endif()
        unset(request_qt_conf)
        if(ARGC GREATER 5)
                set(request_qt_conf ${ARGV5})
        endif()
Mike McQuaid's avatar
Mike McQuaid committed
170 171 172 173 174 175 176 177 178 179 180 181

        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()
182 183 184
        if(QT_BINARY_DIR)
                list(APPEND dirs "${QT_BINARY_DIR}")
        endif()
Mike McQuaid's avatar
Mike McQuaid committed
185 186 187 188 189

        if(APPLE)
                set(qt_conf_dir "${executable}/Contents/Resources")
                set(executable_path "${executable}")
                set(write_qt_conf TRUE)
190
                if(NOT DEFINED plugins_dir)
Mike McQuaid's avatar
Mike McQuaid committed
191 192
                        set(plugins_dir "${DeployQt4_apple_plugins_dir}")
                endif()
Mike McQuaid's avatar
Mike McQuaid committed
193 194 195 196 197 198 199 200 201 202 203
        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
204
                install_qt4_plugin("${plugin}" "${executable}" 1 installed_plugin_path)
Mike McQuaid's avatar
Mike McQuaid committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
                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)
225 226 227 228 229 230 231 232 233 234 235 236 237
        unset(plugins_dir)
        if(ARGC GREATER 4)
                set(plugins_dir ${ARGV4})
        endif()
        unset(component)
        if(ARGC GREATER 5)
                set(component ${ARGV5})
        endif()
        unset(configurations)
        if(ARGC GREATER 6)
                set(configurations ${ARGV6})
        endif()

Mike McQuaid's avatar
Mike McQuaid committed
238 239
        if(EXISTS "${plugin}")
                if(APPLE)
Mike McQuaid's avatar
Mike McQuaid committed
240 241 242
                        if(NOT plugins_dir)
                                set(plugins_dir "${DeployQt4_apple_plugins_dir}")
                        endif()
Mike McQuaid's avatar
Mike McQuaid committed
243 244
                        set(plugins_path "${executable}/Contents/${plugins_dir}")
                else()
Mike McQuaid's avatar
Mike McQuaid committed
245 246 247 248 249 250
                        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
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
                        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})
274 275
                        else()
                                unset(configurations)
Mike McQuaid's avatar
Mike McQuaid committed
276 277 278
                        endif()
                        install(FILES "${plugin}" DESTINATION "${plugins_path}" ${configurations} ${component})
                endif()
279
                set(${installed_plugin_path_var} "${plugins_path}/${plugin_name}" PARENT_SCOPE)
Mike McQuaid's avatar
Mike McQuaid committed
280 281 282 283
        endif()
endfunction()

function(install_qt4_plugin plugin executable copy installed_plugin_path_var)
284 285 286 287 288 289 290 291 292
        unset(plugins_dir)
        if(ARGC GREATER 4)
                set(plugins_dir ${ARGV4})
        endif()
        unset(component)
        if(ARGC GREATER 5)
                set(component ${ARGV5})
        endif()

Mike McQuaid's avatar
Mike McQuaid committed
293 294 295
        if(EXISTS "${plugin}")
                install_qt4_plugin_path("${plugin}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}")
        else()
296
                string(TOUPPER "QT_${plugin}_PLUGIN" plugin_var)
297 298 299 300 301
                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
302 303
                        message(WARNING "Qt plugin \"${plugin}\" not recognized or found.")
                endif()
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
                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
320
        endif()
321
        set(${installed_plugin_path_var} ${${installed_plugin_path_var}} PARENT_SCOPE)
Mike McQuaid's avatar
Mike McQuaid committed
322 323 324
endfunction()

function(install_qt4_executable executable)
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
        unset(qtplugins)
        if(ARGC GREATER 1)
                set(qtplugins ${ARGV1})
        endif()
        unset(libs)
        if(ARGC GREATER 2)
                set(libs ${ARGV2})
        endif()
        unset(dirs)
        if(ARGC GREATER 3)
                set(dirs ${ARGV3})
        endif()
        unset(plugins_dir)
        if(ARGC GREATER 4)
                set(plugins_dir ${ARGV4})
        endif()
        unset(request_qt_conf)
        if(ARGC GREATER 5)
                set(request_qt_conf ${ARGV5})
        endif()
        unset(component)
        if(ARGC GREATER 6)
                set(component ${ARGV6})
        endif()

Mike McQuaid's avatar
Mike McQuaid committed
350 351 352
        if(QT_LIBRARY_DIR)
                list(APPEND dirs "${QT_LIBRARY_DIR}")
        endif()
353 354 355
        if(QT_BINARY_DIR)
                list(APPEND dirs "${QT_BINARY_DIR}")
        endif()
356 357 358 359 360
        if(component)
                set(component COMPONENT ${component})
        else()
                unset(component)
        endif()
Mike McQuaid's avatar
Mike McQuaid committed
361 362

        get_filename_component(executable_absolute "${executable}" ABSOLUTE)
Mike McQuaid's avatar
Mike McQuaid committed
363 364 365 366 367
        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
368 369 370 371
        if(qtcore_type STREQUAL "system")
                set(qt_plugins_dir "")
        endif()

372 373 374 375 376 377 378 379 380
        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
381

382
        resolve_qt4_paths(libs "")
Mike McQuaid's avatar
Mike McQuaid committed
383 384

        install(CODE
385 386
  "include(\"${DeployQt4_cmake_dir}/DeployQt4.cmake\")
  set(BU_CHMOD_BUNDLE_ITEMS TRUE)
387
  FIXUP_QT4_EXECUTABLE(\"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${executable}\" \"\" \"${libs}\" \"${dirs}\" \"${plugins_dir}\" \"${request_qt_conf}\")"
388
                ${component}
Mike McQuaid's avatar
Mike McQuaid committed
389 390
        )
endfunction()