summaryrefslogtreecommitdiffstats
blob: 33ace7ff0bc7ae6ec4de97b768095e584700491a (plain)
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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 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 :
      all_files += env.Install(bundle, os.path.join(env["QTDIR"], "bin", lib + ".dll"))
    plugins_suffix = '4'
    if qtversion == '5' :
      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)

    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) :
  return env["PLATFORM"] == "win32"