Partial reorganization of Mac OS bundeling script.
[quassel.git] / scripts / build / macosx_DeployApp.py
index 4be32f7..a7aae57 100755 (executable)
@@ -16,6 +16,8 @@
 import sys
 import os
 
+from subprocess import Popen, PIPE
+
 class InstallQt(object):
     def __init__(self, appdir, bundle = True):
         self.appDir = appdir
@@ -29,23 +31,42 @@ class InstallQt(object):
         else:
             self.frameworkDir = self.executableDir + "/Frameworks"
 
-        self.needFrameworks = []
+        self.installedFrameworks = set()
 
-        executables = [self.executableDir + "/" + executable for executable in os.listdir(self.executableDir)]
+        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)
+
+    def findFrameworkPath(self):
+        qmakeProcess = Popen('qmake -query QT_INSTALL_LIBS', shell=True, stdout=PIPE, stderr=PIPE)
+        self.sourceFrameworkPath = qmakeProcess.stdout.read().strip()
+        qmakeProcess.stdout.close()
+        qmakeProcess.wait()
+
+    def resolveDependancies(self, obj):
+        # obj must be either an application binary or a framework library
+        for framework, lib in self.determineDependancies(obj):
+            self.installFramework(framework)
+            self.changeDylPath(obj, 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:
             pass
 
+        if not framework.startswith('/'):
+            framework = "%s/%s" % (self.sourceFrameworkPath, framework)
+
         # Copy Framework
         os.system('cp -R "%s" "%s"' % (framework, self.frameworkDir))
 
@@ -59,9 +80,14 @@ class InstallQt(object):
         # Install new Lib ID and Change Path to Frameworks for the Dynamic linker
         for lib in os.listdir(localframework + "/Versions/Current"):
             lib = "%s/Versions/Current/%s" % (localframework, lib)
-            otoolpipe = os.popen('otool -D "%s"' % lib)
-            libname = [line for line in otoolpipe][1].strip()
-            otoolpipe.close()
+            otoolProcess = Popen('otool -D "%s"' % lib, shell=True, stdout=PIPE, stderr=PIPE)
+            try:
+                libname = [line for line in otoolProcess.stdout][1].strip()
+            except:
+                libname = ''
+            otoolProcess.stdout.close()
+            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)
@@ -69,27 +95,28 @@ class InstallQt(object):
                 newlibname = "@executable_path/%s%s" % (frameworkname, libpath)
             #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 = os.popen('otool -L "%s"' % 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]
+        libs = [line.split()[0] for line in otoolOutput[1:] if ("Qt" in line
+                                                               or "phonon" in line)
+                                                               and not "@executable_path" in line]
         frameworks = [lib[:lib.find(".framework")+len(".framework")] for lib in libs]
         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)
 
-            #print 'install_name_tool -change "%s" "%s" "%s"' % (lib, newlibname, obj)
-            os.system('install_name_tool -change "%s" "%s" "%s"' % (lib, newlibname, obj))
+    def changeDylPath(self, obj, lib):
+        if self.bundle:
+            newlibname = "@executable_path/../Frameworks/%s" % lib
+        else:
+            newlibname = "@executable_path/Frameworks/%s" % lib
+
+        #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:
@@ -109,5 +136,3 @@ if __name__ == "__main__":
             targetDir += "/Contents"
 
         InstallQt(targetDir, bundle)
-    
-