1#
2#
3import shutil
4import re
5import subprocess
6import os
7home=os.getenv("HOME")
8print "Preparing independant bundle, home="+home+"..."
9rootFolder=home+"/Avidemux2.6.app/Contents/Resources"
10libFolder=rootFolder+"/lib"
11binFolder=rootFolder+"/bin"
12frameWorkFolder=rootFolder+"/../Frameworks"
13qtPluginFolder=rootFolder+"/../plugins"
14qts = ['QtCore', 'QtGui', 'QtOpenGL','QtScript']
15
16#
17#
18allSymbols=[]
19#
20#
21#
22def log(s):
23    #print "Log:<"+str(s)+">"
24    pass
25#
26#
27#
28def getShortName(fl):
29    shortName=re.sub('^.*\/','',fl)
30    return shortName
31#
32# Returns the list of libs as dependencies in /opt (macport)
33#
34def getGlobalDeps(target):
35    cmd = ["/usr/bin/otool","-L", target]
36    log(cmd)
37    q = []
38    cmd = subprocess.Popen(" ".join(cmd), shell=True, stdout=subprocess.PIPE)
39    for line in cmd.stdout:
40       line = re.sub('[ \t\r\n]*', '', line)
41       line = re.sub('\(.*$', '', line)
42       if(not line.startswith('/opt/local')):
43              continue
44       if(":" in line):
45              continue
46       log(line)
47       q.append(line)
48    log(str(q))
49    return q;
50#
51#
52#
53def getGlobalDepsNoQt(target):
54    q= []
55    p = getGlobalDeps(target)
56    for line in p:
57       if not getShortName(line).startswith('Qt'):
58          q.append(line)
59    return q;
60#
61def getGlobalDepsQtOnly(target):
62    q= []
63    p = getGlobalDeps(target)
64    for line in p:
65       if getShortName(line).startswith('Qt'):
66          q.append(line)
67    return q;
68#
69# Returns the list of libs as dependencies  to local installation folder (
70#
71def getLocalDeps(target):
72    cmd = ["/usr/bin/otool","-L", target]
73    log(cmd)
74    q = []
75    cmd = subprocess.Popen(" ".join(cmd), shell=True, stdout=subprocess.PIPE)
76    for line in cmd.stdout:
77       line = re.sub('[ \t\r\n]*', '', line)
78       line = re.sub('\(.*$', '', line)
79       if(not line.startswith(libFolder)):
80              continue
81       if(":" in line):
82              continue
83       log(line)
84       q.append(line)
85    log(str(q))
86    return q;
87#
88#
89# Copy used library coming from /opt/local
90#
91def copyFiles(folder,libFolder):
92    copied=0
93    log("Copy files"+folder)
94    for dirname, dirnames, filenames in os.walk(folder):
95       for filename in filenames:
96           absPath=os.path.join(dirname, filename)
97           deps=getGlobalDepsNoQt(absPath)
98           for dep in deps:
99               shortName=re.sub('^.*\/','',dep)
100               if(os.path.exists(libFolder+'/'+shortName)):
101                               log(shortName+" already copied")
102               else:
103                   log("Copying"+shortName)
104                   shutil.copy(dep,libFolder)
105                   copied+=1
106    return copied
107#
108#
109# Copy used library coming from /opt/local
110#
111def copyQtDeps(components,libFolder):
112    copied=0
113    for modul in components:
114        absPath='/opt/local/Library/Frameworks/'+modul+'.framework/Versions/4/'+modul
115        print("Copy deps for "+modul+" ("+absPath+")")
116        deps=getGlobalDepsNoQt(absPath)
117        for dep in deps:
118                   shortName=re.sub('^.*\/','',dep)
119                   if(os.path.exists(libFolder+'/'+shortName)):
120                               print(shortName+" already copied")
121                   else:
122                       print("Copying:"+shortName)
123                       shutil.copy(dep,libFolder)
124                       copied+=1
125    # copy plugins deps too
126    copyFiles(qtPluginFolder+'/imageformats',libFolder)
127    return copied
128##
129def changeSymbol(target,oldName,newName):
130        cmd="/usr/bin/install_name_tool -change "+oldName+" "+newName+" "+target
131        log(cmd)
132        subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
133def changeId(target,newId):
134           cmd="/usr/bin/install_name_tool -id "+newId+" "+target
135           log(cmd)
136           subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
137#
138#
139def renameSymbols(libs):
140   for qt in libs:
141      print "Processing "+qt
142      # Change binding
143      for otherQt in allSymbols:
144          newname=re.sub(r'^.*\/',r'@executable_path/../lib/',otherQt)
145          exc="install_name_tool -change "+otherQt+" "+newname+" libToProcess"
146          print(exc)
147#
148#
149#
150def changeGlobalLinkPathForOne(f):
151    deps=getGlobalDepsNoQt(f)
152    for d in deps:
153        shortName=getShortName(d)
154        shortName="@executable_path/../lib/"+shortName
155        changeSymbol(f,d,shortName)
156def changeLocalLinkPathForOne(f):
157    deps=getLocalDeps(f)
158    for d in deps:
159        shortName="@executable_path/../lib/"+re.sub("^.*\/","",d)
160        changeSymbol(f,d,shortName)
161def changeLibLinkPath(folder):
162    for dirname, dirnames, filenames in os.walk(folder):
163       for filename in filenames:
164           absPath=os.path.join(dirname, filename)
165           changeGlobalLinkPathForOne(absPath)
166           changeLocalLinkPathForOne(absPath)
167           changeQtLinkPathForOne(absPath)
168           shortName="@executable_path/../lib/"+re.sub("^.*\/","",absPath)
169           changeId(absPath,shortName)
170def changeQtPluginLinkPath(folder):
171    for dirname, dirnames, filenames in os.walk(folder):
172       for filename in filenames:
173           absPath=os.path.join(dirname, filename)
174           changeGlobalLinkPathForOne(absPath)
175           changeLocalLinkPathForOne(absPath)
176           changeQtLinkPathForOne(absPath)
177           shortName="@executable_path/../../plugins/imageformats/"+re.sub("^.*\/","",absPath)
178           changeId(absPath,shortName)
179def changeBinLinkPath(folder):
180    for dirname, dirnames, filenames in os.walk(folder):
181       for filename in filenames:
182           absPath=os.path.join(dirname, filename)
183           changeGlobalLinkPathForOne(absPath)
184           changeLocalLinkPathForOne(absPath)
185           changeQtLinkPathForOne(absPath)
186           shortName="@executable_path/bin/"+re.sub("^.*\/","",absPath)
187           changeId(absPath,shortName)
188
189def changePluginLinkPath(folder,relFolder):
190    for dirname, dirnames, filenames in os.walk(folder):
191       for filename in filenames:
192           absPath=os.path.join(dirname, filename)
193           changeGlobalLinkPathForOne(absPath)
194           changeQtLinkPathForOne(absPath)
195           shortName="@executable_path/lib/"+relFolder+re.sub("^.*\/","",absPath)
196           changeId(absPath,shortName)
197#
198#
199#
200def changeQtFileSelfLinkPath(fl,modu):
201           shortName="@executable_path/../../Frameworks/"+modu+".framework/Versions/4/"+modu
202           cmd="/usr/bin/install_name_tool -id "+shortName+" "+fl
203           log(cmd)
204           subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
205def changeQtLinkPathForOne(f):
206    deps=getGlobalDepsQtOnly(f)
207    for d in deps:
208        shortName=getShortName(d)
209        shortName="@executable_path/../../Frameworks/"+shortName+".framework/Versions/4/"+shortName
210        changeSymbol(f,d,shortName)
211
212#
213def myMkDir(target):
214        if(os.path.exists(target)):
215                return
216        os.makedirs(target)
217#
218def myCopyTree(src,dst):
219        if(not os.path.exists(src)):
220                return
221        shutil.copytree(src,dst)
222def myCopyFile(src,dst):
223        if(not os.path.exists(src)):
224                return
225        shutil.copy(src,dst)
226##
227def copyQtFiles(targetFolder):
228        myMkDir(targetFolder)
229        for q in qts:
230               print q
231               if(os.path.exists(targetFolder+'/'+q+'.framework')):
232                               log(q+" already copied")
233               else:
234                   log("Copying"+q+' to '+targetFolder)
235                   src='/opt/local/Library/Frameworks/'+q+'.framework'
236                   dst=targetFolder+'/'+q+'.framework'
237                   myMkDir(dst)
238                   src=src+'/Versions/4/'
239                   dst=dst+'/Versions/'
240                   myMkDir(dst)
241                   dst=dst+'/4/'
242                   myMkDir(dst)
243                   print "Copying "+dst+'Resources'
244                   myCopyTree(src+'Resources',dst+'Resources')
245                   print "Copying "+dst+q
246                   myCopyFile(src+q,dst+q)
247                   changeQtFileSelfLinkPath(dst+q,q)
248                   changeQtLinkPathForOne(dst+q)
249                   changeGlobalLinkPathForOne(dst+q)
250        # Also copy plugins
251        myMkDir(qtPluginFolder)
252        myCopyTree('/opt/local/share/qt4/plugins/imageformats',qtPluginFolder+'/imageformats')
253#################################################################
254# Step 1 : Copy system files so we have a standalone package
255#
256#################################################################
257print "Copying Qt framework"
258copyQtFiles(frameWorkFolder)
259print "Copying Qt framework dependencies"
260copyQtDeps(qts,libFolder)
261print "Copying system files"
262#copyFiles(binFolder,libFolder)
263processed=1
264# Copy file until all of them are there
265while not processed == 0:
266        processed=copyFiles(libFolder,libFolder)
267#################################################################
268# Step 2 :  Change link name so that they are all executable_path
269#               relative
270#################################################################
271print "Adjusting dependencies"
272changeBinLinkPath(binFolder)
273changeLibLinkPath(libFolder)
274changeQtPluginLinkPath(qtPluginFolder)
275subFolders=["audioDecoder",    "audioEncoders",   "autoScripts",     "demuxers",        "muxers",          "scriptEngines",   "videoEncoders",   "videoFilters"]
276for s in subFolders:
277        relFolder="ADM_plugins6/"+s
278        changePluginLinkPath(libFolder+"/"+relFolder,relFolder)
279
280
281