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