其實這個問題在網上能搜到大把的解決方案。大家的統一答案都是
otool -L yourapp.app/Contents/MacOS/yourapp
根據輸出信息在運行 install_name_tool
install_name_tool的使用方法在這里
比較復雜的是當依賴了很多第三方庫,尤其是向QT這樣的庫的時候。打包那叫一個麻煩啊。
QT有個官方的文檔告訴你如何手動一步步打包程序,還提供了一個macdepotqt這么個程序。幫你進行打包。
可是啊,macdepotqt不支持其他第三方庫,也不靈活,按照官方文檔的方式手動打包,坑爹啊。
說他坑爹一點都不假,當你遇到了成片的符號需要你敲命令的話,想死的心情油然而生。
那么好了。自己動手吧。這里我給出一個我寫的打包的Python腳本半成品,思想跟手動敲命令是一樣的,只不過用腳本實現自動化了同時遞歸檢查並將缺少的庫考到bundle目錄中。腳本中針對QT的庫進行打包了,如果希望把其他的依賴庫也打包的話在keywordList里邊添加相應的關鍵字就好了。希望對大家能有幫助。
- import os
- import sys
- import commands
- binaryName = "yourapp"
- bundleName = "yourapp.app"
- bundleFrameworkDir = "Contents/Frameworks/"
- bundleBinaryDir = "Contents/MacOS/"
- bundleLibraryList = [];
- systemFrameworkDir = "/Library/Frameworks/"
- keyWordList = ["Qt"]
- #add more keywords to work better
- def hasKeyWord(word):
- for it in keyWordList:
- if word.find(it) != -1:
- return True
- return False
- def findApp(name):
- return name+bundleBinaryDir+binaryName
- def getBundleDependsInfo(app):
- dependList = commands.getoutput("otool -L " + app).replace("\t","").split("\n");
- del(dependList[0])
- dependList = [item.split(" ")[0] for item in dependList if hasKeyWord(item)];
- return dependList
- def copyLibrary(base, src, dst):
- systemFullPath = src
- print "library %s depend %s" % (os.path.basename(base), os.path.basename(dst))
- if not os.path.exists(dst):
- bundleFullPath = os.path.dirname(dst)
- os.system("mkdir -p %s" % (bundleFullPath))
- os.system("cp %s %s" % (systemFullPath, bundleFullPath))
- infoList = getBundleDependsInfo(dst)
- copyDependFiles(dst, infoList)
- os.system("install_name_tool -id @executable_path/../Frameworks/%s %s" % (src, dst))
- os.system("install_name_tool -change %s @executable_path/../Frameworks/%s %s" % (src, src, base))
- def getFrameworkName(dirname):
- if dirname.find("framework") == -1:
- return
- while not dirname.endswith("framework"):
- dirname = os.path.dirname(dirname)
- return dirname
- def copyFrameworkExtDir(src):
- sysPath = systemFrameworkDir + src
- destPath = ""
- if not os.path.exists(sysPath):
- return
- frameworkPath = getFrameworkName(sysPath)
- frameWorkName = getFrameworkName(src)
- bundlePath = bundleName + "/" + bundleFrameworkDir + frameWorkName + "/"
- for it in bundleFrameworkExtDir:
- destPath = bundlePath + it
- srcPath = frameworkPath + "/" + it
- if not os.path.exists(destPath) and os.path.exists(srcPath):
- print "copying %s %s" % (frameWorkName, it)
- os.system("cp -r %s %s" % (srcPath, destPath))
- def copyFramework(base, src, dst):
- print "framework %s depend %s" % (os.path.basename(base), os.path.basename(dst))
- systemFullPath = systemFrameworkDir+src
- if not os.path.exists(dst):
- bundleFullPath = os.path.dirname(dst)
- os.system("mkdir -p %s" % (bundleFullPath))
- os.system("cp %s %s" % (systemFullPath, bundleFullPath))
- copyFrameworkExtDir(src)
- infoList = getBundleDependsInfo(dst)
- copyDependFiles(dst, infoList)
- ("install_name_tool -id @executable_path/../Frameworks/%s %s" % (src, dst))
- os.system("install_name_tool -id @executable_path/../Frameworks/%s %s" % (src, dst))
- os.system("install_name_tool -change %s @executable_path/../Frameworks/%s %s" % (src, src, base))
- def copyDependFiles(base, infoList):
- targetDir = ""
- for it in infoList:
- targetDir = bundleName + "/" + bundleFrameworkDir + it
- if it.find("framework") != -1:
- copyFramework(base, it, targetDir)
- else:
- copyLibrary(base, it, targetDir)
- def makeBundleDirs():
- os.system("mkdir -p " + bundleName + "/" + bundleFrameworkDir)
- if __name__ == "__main__":
- target = findApp(bundleName + "/")
- makeBundleDirs()
- infoList = getBundleDependsInfo(target)
- copyDependFiles(target, infoList)
http://blog.csdn.net/livemylife/article/details/7294778