2 # -*- coding: iso-8859-1 -*-
4 ################################################################################
6 # 2008 June 27th by Marcus 'EgS' Eggenberger <egs@quassel-irc.org> #
8 # The author disclaims copyright to this source code. #
9 # This Python Script is in the PUBLIC DOMAIN. #
11 ################################################################################
13 # ==============================
15 # ==============================
19 from subprocess import Popen, PIPE
21 class InstallQt(object):
22 def __init__(self, appdir, bundle = True):
25 self.executableDir = self.appDir
27 self.executableDir += "/MacOS"
30 self.frameworkDir = self.appDir + "/Frameworks"
32 self.frameworkDir = self.executableDir + "/Frameworks"
34 self.installedFrameworks = set()
36 self.findFrameworkPath()
38 executables = [self.executableDir + "/" + executable for executable in os.listdir(self.executableDir)]
39 for executable in executables:
40 self.resolveDependancies(executable)
42 def findFrameworkPath(self):
43 qmakeProcess = Popen('qmake -query QT_INSTALL_LIBS', shell=True, stdout=PIPE, stderr=PIPE)
44 self.sourceFrameworkPath = qmakeProcess.stdout.read().strip()
45 qmakeProcess.stdout.close()
48 def resolveDependancies(self, obj):
49 # obj must be either an application binary or a framework library
50 for framework, lib in self.determineDependancies(obj):
51 self.installFramework(framework)
52 self.changeDylPath(obj, lib)
54 def installFramework(self, framework):
55 # skip if framework is already installed.
56 if framework in self.installedFrameworks:
59 self.installedFrameworks.add(framework)
61 # ensure that the framework directory exists
63 os.mkdir(self.frameworkDir)
67 if not framework.startswith('/'):
68 framework = "%s/%s" % (self.sourceFrameworkPath, framework)
71 os.system('cp -R "%s" "%s"' % (framework, self.frameworkDir))
73 frameworkname = framework.split('/')[-1]
74 localframework = self.frameworkDir + "/" + frameworkname
77 os.system('find "%s" -name *debug* -exec rm -f {} \;' % localframework)
78 os.system('find "%s" -name Headers -exec rm -rf {} \; 2>/dev/null' % localframework)
80 # Install new Lib ID and Change Path to Frameworks for the Dynamic linker
81 for lib in os.listdir(localframework + "/Versions/Current"):
82 lib = "%s/Versions/Current/%s" % (localframework, lib)
83 otoolProcess = Popen('otool -D "%s"' % lib, shell=True, stdout=PIPE, stderr=PIPE)
85 libname = [line for line in otoolProcess.stdout][1].strip()
88 otoolProcess.stdout.close()
89 if otoolProcess.wait() == 1: # we found some Resource dir or similar -> skip
91 frameworkpath, libpath = libname.split(frameworkname)
93 newlibname = "@executable_path/../%s%s" % (frameworkname, libpath)
95 newlibname = "@executable_path/%s%s" % (frameworkname, libpath)
96 #print 'install_name_tool -id "%s" "%s"' % (newlibname, lib)
97 os.system('install_name_tool -id "%s" "%s"' % (newlibname, lib))
99 self.resolveDependancies(lib)
101 def determineDependancies(self, app):
102 otoolPipe = Popen('otool -L "%s"' % app, shell=True, stdout=PIPE).stdout
103 otoolOutput = [line for line in otoolPipe]
105 libs = [line.split()[0] for line in otoolOutput[1:] if ("Qt" in line
107 and not "@executable_path" in line]
108 frameworks = [lib[:lib.find(".framework")+len(".framework")] for lib in libs]
109 return zip(frameworks, libs)
112 def changeDylPath(self, obj, lib):
114 newlibname = "@executable_path/../Frameworks/%s" % lib
116 newlibname = "@executable_path/Frameworks/%s" % lib
118 #print 'install_name_tool -change "%s" "%s" "%s"' % (lib, newlibname, obj)
119 os.system('install_name_tool -change "%s" "%s" "%s"' % (lib, newlibname, obj))
121 if __name__ == "__main__":
122 if len(sys.argv) < 2:
123 print "Wrong Argument Count (Syntax: %s [--nobundle] $TARGET_APP)" % sys.argv[0]
129 if sys.argv[1].startswith("--"):
131 if sys.argv[1] == "--nobundle":
134 targetDir = sys.argv[offset]
136 targetDir += "/Contents"
138 InstallQt(targetDir, bundle)