diff options
author | Tobias Markmann <tm@ayena.de> | 2015-02-05 10:18:47 (GMT) |
---|---|---|
committer | Swift Review <review@swift.im> | 2015-02-06 13:38:42 (GMT) |
commit | 9f6d02730918faa041afc39ec51b57675b4c5c1d (patch) | |
tree | 69292bfe21abe04541e0f6eccc31d59fc97763fd /BuildTools | |
parent | 8421b895f5697ebf680c124f84a68dcdea029c62 (diff) | |
download | swift-9f6d02730918faa041afc39ec51b57675b4c5c1d.zip swift-9f6d02730918faa041afc39ec51b57675b4c5c1d.tar.bz2 |
Use windeployqt.exe if available and Win distribution documentation fix
If windeployqt.exe is available for Qt5, it will be used to detect
which Qt DLLs to put in the Windows distribution and its dependencies
correctly.
Added a note to our Windows building documentation about the VS
redistributable.
Test-Information:
Tested building a MSI package on Windows 8.1 Pro with Qt 5.3.2 32-bit
msvc2013_opengl which successfully installs and runs.
Change-Id: I786da40d6467f1de8e64bfae275f8363ac1d5ba8
Diffstat (limited to 'BuildTools')
-rw-r--r-- | BuildTools/SCons/Tools/WindowsBundle.py | 100 |
1 files changed, 93 insertions, 7 deletions
diff --git a/BuildTools/SCons/Tools/WindowsBundle.py b/BuildTools/SCons/Tools/WindowsBundle.py index 2915141..33ace7f 100644 --- a/BuildTools/SCons/Tools/WindowsBundle.py +++ b/BuildTools/SCons/Tools/WindowsBundle.py @@ -1,7 +1,41 @@ import SCons.Util, os +import subprocess +import re +import shutil + +def which(program_name): + if hasattr(shutil, "which"): + return shutil.which(program_name) + else: + path = os.getenv('PATH') + for p in path.split(os.path.pathsep): + p = os.path.join(p,program_name) + if os.path.exists(p) and os.access(p,os.X_OK): + return p def generate(env) : - def createWindowsBundle(env, bundle, resources = {}, qtplugins = {}, qtlibs = [], qtversion = '4') : + def captureWinDeployQtMapping(release = True): + p = False + if release: + p = subprocess.Popen(['windeployqt', '--release', '--dry-run', '--list', 'mapping', 'Swift.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + else: + p = subprocess.Popen(['windeployqt', '--debug', '--dry-run', '--list', 'mapping', 'Swift.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + if p: + stdout, stderr = p.communicate() + + mappings = [] + + p = re.compile(ur'"([^\"]*)" "([^\"]*)"') + + matches = re.findall(p, stdout) + for match in matches: + mappings.append(match) + return mappings + else: + return False + + def createWindowsBundleManual(env, bundle, resources = {}, qtplugins = {}, qtlibs = [], qtversion = '4') : all_files = [] all_files += env.Install(bundle, bundle + ".exe") for lib in qtlibs : @@ -11,17 +45,69 @@ def generate(env) : plugins_suffix = '' for plugin_type in qtplugins: all_files += env.Install(os.path.join(bundle, plugin_type), [os.path.join(env["QTDIR"], "plugins", plugin_type, "q" + plugin + plugins_suffix + ".dll") for plugin in qtplugins[plugin_type]]) + for dir, resourceFiles in resources.items() : + for resource in resourceFiles : + e = env.Entry(resource) + if e.isdir() : + for subresource in env.Glob(str(e) + "/*") : + all_files += env.Install(os.path.join(bundle, dir, e.name), subresource) + else : + all_files += env.Install(os.path.join(bundle, dir), resource) + return all_files + # This version of uses windeployqt tool + def createWindowsBundleWithWinDeployQt(env, bundle, resources = {}, qtplugins = {}, qtlibs = [], qtversion = '4') : + assert(qtversion == '5') + all_files = [] + + # add swift executable + all_files += env.Install(bundle, bundle + ".exe") + + # adding resources (swift sounds/images/translations) for dir, resourceFiles in resources.items() : for resource in resourceFiles : - e = env.Entry(resource) - if e.isdir() : - for subresource in env.Glob(str(e) + "/*") : - all_files += env.Install(os.path.join(bundle, dir, e.name), subresource) - else : - all_files += env.Install(os.path.join(bundle, dir), resource) + e = env.Entry(resource) + if e.isdir() : + for subresource in env.Glob(str(e) + "/*") : + all_files += env.Install(os.path.join(bundle, dir, e.name), subresource) + else : + all_files += env.Install(os.path.join(bundle, dir), resource) + + qtmappings = captureWinDeployQtMapping() + assert(qtmappings) + + # handle core DLLs + qt_corelib_regex = re.compile(ur".*bin.*\\(.*)\.dll") + + for qtlib in qtlibs: + if qtlib.startswith("Qt5"): + (src_path, target_path) = next(((src_path, target_path) for (src_path, target_path) in qtmappings if qt_corelib_regex.match(src_path) and qt_corelib_regex.match(src_path).group(1) == qtlib), (None, None)) + if src_path != None: + env.Install(bundle, src_path) + + # handle core dependencies + for (src_path, target_path) in qtmappings: + if qt_corelib_regex.match(src_path) and not qt_corelib_regex.match(src_path).group(1).startswith("Qt5"): + env.Install(bundle, src_path) + + # handle plugins + qt_plugin_regex = re.compile(ur".*plugins.*\\(.*)\\(.*)\.dll") + for (src_path, target_path) in qtmappings: + if qt_plugin_regex.match(src_path): + plugin_folder, filename = qt_plugin_regex.match(src_path).groups() + try: + if filename[1:] in qtplugins[plugin_folder]: + env.Install(os.path.join(bundle, plugin_folder), src_path) + except: + pass return all_files + def createWindowsBundle(env, bundle, resources = {}, qtplugins = {}, qtlibs = [], qtversion = '4'): + if which("windeployqt.exe"): + return createWindowsBundleWithWinDeployQt(env, bundle, resources, qtplugins, qtlibs, qtversion) + else: + return createWindowsBundleManual(env, bundle, resources, qtplugins, qtlibs, qtversion) + env.AddMethod(createWindowsBundle, "WindowsBundle") def exists(env) : |