1# 2# 3import shutil 4import re 5import subprocess 6import os 7home=os.getenv("HOME") 8api_version=os.getenv("API_VERSION") 9print "Preparing independant bundle, home="+home+"..., version ) "+str(api_version) 10rootFolder=home+"/Avidemux"+str(api_version)+".app/Contents/Resources" 11libFolder=rootFolder+"/lib" 12binFolder=rootFolder+"/bin" 13frameWorkFolder=rootFolder+"/../Frameworks" 14qtPluginFolder=rootFolder+"/../plugins" 15qts = ['QtCore', 'QtGui', 'QtOpenGL','QtScript','QtWidgets','QtPrintSupport','QtNetwork'] 16 17# 18# 19allSymbols=[] 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') and not line.startswith('/usr/local/opt') and not line.startswith('/usr/local/Cellar/qt5/') and not line.startswith('@rpath')): 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# 69def getRpathDepsOnly(target): 70 q= [] 71 p = getGlobalDeps(target) 72 for line in p: 73 if getShortName(line).startswith('@rpath'): 74 q.append(line) 75 return q 76# 77# Returns the list of libs as dependencies to local installation folder ( 78# 79def getLocalDeps(target): 80 cmd = ["/usr/bin/otool","-L", target] 81 log(cmd) 82 q = [] 83 cmd = subprocess.Popen(" ".join(cmd), shell=True, stdout=subprocess.PIPE) 84 for line in cmd.stdout: 85 line = re.sub('[ \t\r\n]*', '', line) 86 line = re.sub('\(.*$', '', line) 87 if(not line.startswith(libFolder)): 88 continue 89 if(":" in line): 90 continue 91 log(line) 92 q.append(line) 93 log(str(q)) 94 return q; 95# 96# 97# Copy used library coming from /opt/local 98# 99def copyFiles(folder,libFolder): 100 copied=0 101 log("Copy files"+folder) 102 for dirname, dirnames, filenames in os.walk(folder): 103 for filename in filenames: 104 absPath=os.path.join(dirname, filename) 105 deps=getGlobalDepsNoQt(absPath) 106 for dep in deps: 107 shortName=re.sub('^.*\/','',dep) 108 if(os.path.exists(libFolder+'/'+shortName)): 109 log(shortName+" already copied") 110 else: 111 log("Copying"+shortName) 112 myCopy(dep,libFolder) 113 copied+=1 114 return copied 115# 116# 117# Copy used library coming from /opt/local 118# 119def copyQtDeps(components,libFolder): 120 copied=0 121 for modul in components: 122 absPath='/usr/local/opt/qt5/lib/'+modul+'.framework/Versions/5/'+modul 123 print("Copy deps for "+modul+" ("+absPath+")") 124 deps=getGlobalDepsNoQt(absPath) 125 for dep in deps: 126 shortName=re.sub('^.*\/','',dep) 127 if(os.path.exists(libFolder+'/'+shortName)): 128 print(shortName+" already copied") 129 else: 130 print("Copying:"+shortName) 131 myCopy(dep,libFolder) 132 copied+=1 133 # copy plugins deps too 134 copyFiles(qtPluginFolder+'/imageformats',libFolder) 135 return copied 136## 137def changeSymbol(target,oldName,newName): 138 cmd="/usr/bin/install_name_tool -change "+oldName+" "+newName+" "+target 139 log(cmd) 140 subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) 141# 142def changeId(target,newId): 143 cmd="/usr/bin/install_name_tool -id "+newId+" "+target 144 log(cmd) 145 subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) 146# 147# 148def renameSymbols(libs): 149 for qt in libs: 150 print "Processing "+qt 151 # Change binding 152 for otherQt in allSymbols: 153 newname=re.sub(r'^.*\/',r'@executable_path/../lib/',otherQt) 154 exc="install_name_tool -change "+otherQt+" "+newname+" libToProcess" 155 print(exc) 156# 157# 158# 159def changeGlobalLinkPathForOne(f): 160 deps=getGlobalDepsNoQt(f) 161 for d in deps: 162 shortName=getShortName(d) 163 shortName="@executable_path/../lib/"+shortName 164 changeSymbol(f,d,shortName) 165def changeLocalLinkPathForOne(f): 166 deps=getLocalDeps(f) 167 for d in deps: 168 shortName="@executable_path/../lib/"+re.sub("^.*\/","",d) 169 changeSymbol(f,d,shortName) 170def changeLibLinkPath(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/../lib/"+re.sub("^.*\/","",absPath) 178 changeId(absPath,shortName) 179# 180def changeQtPlatformLinkPath(folder): 181 for dirname, dirnames, filenames in os.walk(folder): 182 for filename in filenames: 183 absPath=os.path.join(dirname, filename) 184 changeGlobalLinkPathForOne(absPath) 185 changeLocalLinkPathForOne(absPath) 186 changeQtLinkPathForOne(absPath) 187 shortName="@executable_path/../../plugins/platforms/"+re.sub("^.*\/","",absPath) 188 changeId(absPath,shortName) 189def changeQtPluginLinkPath(folder): 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 changeLocalLinkPathForOne(absPath) 195 changeQtLinkPathForOne(absPath) 196 shortName="@executable_path/../../plugins/imageformats/"+re.sub("^.*\/","",absPath) 197 changeId(absPath,shortName) 198def changeBinLinkPath(folder): 199 for dirname, dirnames, filenames in os.walk(folder): 200 for filename in filenames: 201 absPath=os.path.join(dirname, filename) 202 changeGlobalLinkPathForOne(absPath) 203 changeLocalLinkPathForOne(absPath) 204 changeQtLinkPathForOne(absPath) 205 shortName="@executable_path/bin/"+re.sub("^.*\/","",absPath) 206 changeId(absPath,shortName) 207 208def changePluginLinkPath(folder,relFolder): 209 for dirname, dirnames, filenames in os.walk(folder): 210 for filename in filenames: 211 absPath=os.path.join(dirname, filename) 212 changeGlobalLinkPathForOne(absPath) 213 changeQtLinkPathForOne(absPath) 214 shortName="@executable_path/lib/"+relFolder+re.sub("^.*\/","",absPath) 215 changeId(absPath,shortName) 216# 217# 218# 219def myChmod(dst): 220 log("chmod <"+dst+">") 221 cmd="/bin/chmod" + " -R 755 "+dst 222 log("Exec <"+cmd+">") 223 subprocess.call(cmd, shell=True) 224 225# 226def myCopy(src,dst): 227 shutil.copy(src,dst) 228 myChmod(dst) 229 230# 231def changeQtFileSelfLinkPath(fl,modu): 232 shortName="@executable_path/../../Frameworks/"+modu+".framework/Versions/5/"+modu 233 cmd="/usr/bin/install_name_tool -id "+shortName+" "+fl 234 log(cmd) 235 subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) 236def changeQtLinkPathForOne(f): 237 deps=getGlobalDepsQtOnly(f) 238 for d in deps: 239 shortName=getShortName(d) 240 shortName="@executable_path/../../Frameworks/"+shortName+".framework/Versions/5/"+shortName 241 changeSymbol(f,d,shortName) 242 deps2=getRpathDepsOnly(f) 243 for d in deps2: 244 shortName2=re.sub('@rpath','@executable_path/../../Frameworks/') 245 changeSymbol(f,d,shortName2) 246 247# 248def myMkDir(target): 249 if(os.path.exists(target)): 250 return 251 os.makedirs(target) 252# 253def myCopyTree(src,dst): 254 log(src+"->"+dst) 255 if(not os.path.exists(src)): 256 return 257 shutil.copytree(src,dst) 258 myChmod(dst) 259def myCopyFile(src,dst): 260 if(not os.path.exists(src)): 261 return 262 myCopy(src,dst) 263## 264def copyQtFiles(targetFolder): 265 myMkDir(targetFolder) 266 for q in qts: 267 print q 268 if(os.path.exists(targetFolder+'/'+q+'.framework')): 269 log(q+" already copied") 270 else: 271 log("Copying"+q+' to '+targetFolder) 272 src='/usr/local/opt/qt5/lib/'+q+'.framework' 273 dst=targetFolder+'/'+q+'.framework' 274 myMkDir(dst) 275 src=src+'/Versions/5/' 276 dst=dst+'/Versions/' 277 myMkDir(dst) 278 dst=dst+'/5/' 279 myMkDir(dst) 280 print "Copying "+dst+'Resources' 281 myCopyTree(src+'Resources',dst+'Resources') 282 print "Copying "+dst+q 283 myCopyFile(src+q,dst+q) 284 changeQtFileSelfLinkPath(dst+q,q) 285 changeQtLinkPathForOne(dst+q) 286 changeGlobalLinkPathForOne(dst+q) 287 # Also copy plugins 288 myMkDir(qtPluginFolder) 289 myCopyTree('/usr/local/opt/qt5/plugins/imageformats',qtPluginFolder+'/imageformats') 290 myCopyTree('/usr/local/opt/qt5/plugins/platforms',qtPluginFolder+'/platforms') 291################################################################ 292# Step 2 : Change link name so that they are all executable_path 293# relative 294################################################################# 295print "Adjusting dependencies" 296changeBinLinkPath(binFolder) 297changeLibLinkPath(libFolder) 298changeQtPluginLinkPath(qtPluginFolder+"/platforms") 299changeQtPluginLinkPath(qtPluginFolder+"/imageformats") 300subFolders=["audioDecoder", "audioEncoders", "autoScripts", "demuxers", "muxers", "scriptEngines", "videoEncoders", "videoFilters"] 301for s in subFolders: 302 relFolder="ADM_plugins6/"+s 303 changePluginLinkPath(libFolder+"/"+relFolder,relFolder) 304changeQtPlatformLinkPath(binFolder+'/platforms') 305 306 307