X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=scripts%2Fbuild%2Fmacosx_DeployApp.py;h=e6cfc1d189ac29f4acc49fbf8133789fb40c81b2;hp=a46b5dca4184d59fe792d782761b121b7f810a48;hb=f89390a2e9ba9a4a64f3a545c147c046fbe07a16;hpb=cf17ae38dd425697d0d8e22d50fb16f2bc821df6 diff --git a/scripts/build/macosx_DeployApp.py b/scripts/build/macosx_DeployApp.py index a46b5dca..e6cfc1d1 100755 --- a/scripts/build/macosx_DeployApp.py +++ b/scripts/build/macosx_DeployApp.py @@ -15,43 +15,145 @@ # ============================== import sys import os +import os.path from subprocess import Popen, PIPE +# ============================== +# Constants +# ============================== +QT_CONFIG = """[Paths] + Plugins = plugins +""" + +QT_CONFIG_NOBUNDLE = """[Paths] + Prefix = ../ + Plugins = plugins +""" + + class InstallQt(object): - def __init__(self, appdir, bundle = True): + def __init__(self, appdir, bundle=True, requestedPlugins=[]): self.appDir = appdir self.bundle = bundle + self.frameworkDir = self.appDir + "/Frameworks" + self.pluginDir = self.appDir + "/plugins" self.executableDir = self.appDir if bundle: self.executableDir += "/MacOS" - if bundle: - self.frameworkDir = self.appDir + "/Frameworks" - else: - self.frameworkDir = self.executableDir + "/Frameworks" - - self.needFrameworks = [] + self.installedFrameworks = set() self.findFrameworkPath() executables = [self.executableDir + "/" + executable for executable in os.listdir(self.executableDir)] - for executable in executables: - for framework,lib in self.determineDependancies(executable): - if framework not in self.needFrameworks: - self.needFrameworks.append(framework) - self.installFramework(framework) - self.changeDylPath(executable) + self.resolveDependancies(executable) + + self.findPluginsPath() + self.installPlugins(requestedPlugins) + self.installQtConf() + + def qtProperty(self, qtProperty): + """ + Query persistent property of Qt via qmake + """ + VALID_PROPERTIES = ['QT_INSTALL_PREFIX', + 'QT_INSTALL_DATA', + 'QT_INSTALL_DOCS', + 'QT_INSTALL_HEADERS', + 'QT_INSTALL_LIBS', + 'QT_INSTALL_BINS', + 'QT_INSTALL_PLUGINS', + 'QT_INSTALL_IMPORTS', + 'QT_INSTALL_TRANSLATIONS', + 'QT_INSTALL_CONFIGURATION', + 'QT_INSTALL_EXAMPLES', + 'QT_INSTALL_DEMOS', + 'QMAKE_MKSPECS', + 'QMAKE_VERSION', + 'QT_VERSION' + ] + if qtProperty not in VALID_PROPERTIES: + return None + + qmakeProcess = Popen('qmake -query %s' % qtProperty, shell=True, stdout=PIPE, stderr=PIPE) + result = qmakeProcess.stdout.read().strip() + qmakeProcess.stdout.close() + qmakeProcess.wait() + return result def findFrameworkPath(self): - otoolProcess = Popen('qmake -query QT_INSTALL_LIBS', shell=True, stdout=PIPE, stderr=PIPE) - self.sourceFrameworkPath = otoolProcess.stdout.read().strip() - otoolProcess.stdout.close() - otoolProcess.wait() + self.sourceFrameworkPath = self.qtProperty('QT_INSTALL_LIBS') + + def findPluginsPath(self): + self.sourcePluginsPath = self.qtProperty('QT_INSTALL_PLUGINS') + def findPlugin(self, pluginname): + qmakeProcess = Popen('find %s -name %s' % (self.sourcePluginsPath, pluginname), shell=True, stdout=PIPE, stderr=PIPE) + result = qmakeProcess.stdout.read().strip() + qmakeProcess.stdout.close() + qmakeProcess.wait() + if not result: + raise OSError + return result + + def installPlugins(self, requestedPlugins): + try: + os.mkdir(self.pluginDir) + except: + pass + + for plugin in requestedPlugins: + if not plugin.isalnum(): + print "Skipping library '%s'..." % plugin + continue + + pluginName = "lib%s.dylib" % plugin + pluginSource = '' + try: + pluginSource = self.findPlugin(pluginName) + except OSError: + print "WARNING: Requested library does not exist: '%s'" % plugin + continue + + pluginSubDir = os.path.dirname(pluginSource) + pluginSubDir = pluginSubDir.replace(self.sourcePluginsPath, '').strip('/') + try: + os.mkdir("%s/%s" % (self.pluginDir, pluginSubDir)) + except OSError: + pass + + os.system('cp "%s" "%s/%s"' % (pluginSource, self.pluginDir, pluginSubDir)) + + self.resolveDependancies("%s/%s/%s" % (self.pluginDir, pluginSubDir, pluginName)) + + def installQtConf(self): + qtConfName = self.appDir + "/qt.conf" + qtConfContent = QT_CONFIG_NOBUNDLE + if self.bundle: + qtConfContent = QT_CONFIG + qtConfName = self.appDir + "/Resources/qt.conf" + + qtConf = open(qtConfName, 'w') + qtConf.write(qtConfContent) + qtConf.close() + + def resolveDependancies(self, obj): + # obj must be either an application binary or a framework library + # print "resolving deps for:", obj + for framework, lib in self.determineDependancies(obj): + self.installFramework(framework) + self.changeDylPath(obj, framework, lib) def installFramework(self, framework): + # skip if framework is already installed. + if framework in self.installedFrameworks: + return + + self.installedFrameworks.add(framework) + + # ensure that the framework directory exists try: os.mkdir(self.frameworkDir) except: @@ -79,54 +181,57 @@ class InstallQt(object): except: libname = '' otoolProcess.stdout.close() - if otoolProcess.wait() == 1: # we found some Resource dir or similar -> skip + if otoolProcess.wait() == 1: # we found some Resource dir or similar -> skip continue frameworkpath, libpath = libname.split(frameworkname) if self.bundle: newlibname = "@executable_path/../%s%s" % (frameworkname, libpath) else: newlibname = "@executable_path/%s%s" % (frameworkname, libpath) - #print 'install_name_tool -id "%s" "%s"' % (newlibname, lib) + # print 'install_name_tool -id "%s" "%s"' % (newlibname, lib) os.system('install_name_tool -id "%s" "%s"' % (newlibname, lib)) - self.changeDylPath(lib) - + + self.resolveDependancies(lib) + def determineDependancies(self, app): otoolPipe = Popen('otool -L "%s"' % app, shell=True, stdout=PIPE).stdout otoolOutput = [line for line in otoolPipe] otoolPipe.close() - libs = [line.split()[0] for line in otoolOutput[1:] if "Qt" in line and not "@executable_path" in line] - frameworks = [lib[:lib.find(".framework")+len(".framework")] for lib in libs] + libs = [line.split()[0] for line in otoolOutput[1:] if ("Qt" in line or "phonon" in line) and "@executable_path" not in line] + frameworks = [lib[:lib.find(".framework") + len(".framework")] for lib in libs] + frameworks = [framework[framework.rfind('/') + 1:] for framework in frameworks] return zip(frameworks, libs) - def changeDylPath(self, obj): - for framework, lib in self.determineDependancies(obj): - frameworkname = framework.split('/')[-1] - frameworkpath, libpath = lib.split(frameworkname) - if self.bundle: - newlibname = "@executable_path/../Frameworks/%s%s" % (frameworkname, libpath) - else: - newlibname = "@executable_path/Frameworks/%s%s" % (frameworkname, libpath) + def changeDylPath(self, obj, framework, lib): + newlibname = framework + lib.split(framework)[1] + if self.bundle: + newlibname = "@executable_path/../Frameworks/%s" % newlibname + else: + newlibname = "@executable_path/Frameworks/%s" % newlibname - #print 'install_name_tool -change "%s" "%s" "%s"' % (lib, newlibname, obj) - os.system('install_name_tool -change "%s" "%s" "%s"' % (lib, newlibname, obj)) + # print 'install_name_tool -change "%s" "%s" "%s"' % (lib, newlibname, obj) + os.system('install_name_tool -change "%s" "%s" "%s"' % (lib, newlibname, obj)) if __name__ == "__main__": if len(sys.argv) < 2: - print "Wrong Argument Count (Syntax: %s [--nobundle] $TARGET_APP)" % sys.argv[0] + print "Wrong Argument Count (Syntax: %s [--nobundle] [--plugins=plugin1,plugin2,...] $TARGET_APP)" % sys.argv[0] sys.exit(1) else: bundle = True + plugins = [] offset = 1 - if sys.argv[1].startswith("--"): - offset = 2 - if sys.argv[1] == "--nobundle": + while offset < len(sys.argv) and sys.argv[offset].startswith("--"): + if sys.argv[offset] == "--nobundle": bundle = False + if sys.argv[offset].startswith("--plugins="): + plugins = sys.argv[offset].split('=')[1].split(',') + + offset += 1 + targetDir = sys.argv[offset] if bundle: targetDir += "/Contents" - InstallQt(targetDir, bundle) - - + InstallQt(targetDir, bundle, plugins)