# # # delete "osx_bundle.sh" # # patch "wscript" # from [103fd8daa6556d0d830f1538b64ab081478a1411] # to [a62adeaeb1930bf390ac1a9b1f7500817eed1989] # ============================================================ --- wscript 103fd8daa6556d0d830f1538b64ab081478a1411 +++ wscript a62adeaeb1930bf390ac1a9b1f7500817eed1989 @@ -8,17 +8,24 @@ blddir = '_build_' srcdir = '.' blddir = '_build_' -# path to an *.icns file created with the Icon Composer app +# path to an *.icns file created with the OSX Icon Composer app iconsfile = 'guitone/res/osx/guitone.icns' -# array of languages (ISO 639 code) for a localized application menu -languages = (['de']) +# array of languages (ISO 639 code) for a localized OSX application menu +languages = ['de'] +# array of needed Qt4 libraries for OSX +qt4libs = ['QtCore', 'QtGui'] +# array of files and/or directories to copy to any created OSX disk image +dmgfiles = ['README', 'NEWS', 'COPYING'] import os import sys import shutil +import traceback +import tempfile import Params import Runner import Utils +import Qt4 Utils.waf_version(mini="1.0.0", maxi="1.4.9") @@ -27,14 +34,14 @@ app_info = ''' - CFBundlePackageType - APPL - CFBundleGetInfoString - Created by waf - CFBundleSignature - ???? - NOTE - Do not change this file, it will be overwritten by waf. + CFBundlePackageType + APPL + CFBundleGetInfoString + Created by waf + CFBundleSignature + ???? + NOTE + Do not change this file, it will be overwritten by waf. ''' app_info_foot = ''' @@ -60,7 +67,7 @@ def build(bld): ''' def build(bld): - bld.add_subdirs("guitone") + bld.add_subdirs("guitone") def configure(conf): Runner.set_exec("noredir") @@ -71,11 +78,12 @@ def set_options(opt): opt.add_option('--exe', action='store_true', default=False, help='execute the application') if sys.platform == "darwin": opt.add_option('--bundle', action='store_true', default=False, help='create a MacOS X application bundle') - + opt.add_option('--monolithic', action='store_true', default=False, help='make the MacOS X application bundle monolithic (requires --bundle)') + opt.add_option('--dmg', action='store_true', default=False, help='create a MacOS X disk image containing the created bundle (requires --bundle)') def shutdown(): - global APPNAME,blddir,app_info,app_info_foot,iconsfile,locversion,languages + global APPNAME,blddir,app_info,app_info_foot,iconsfile,locversion,languages,qt4libs,dmgfiles - app_bundle = blddir + '/default/bundle/' + APPNAME + '.app' + app_bundle = blddir + '/default/' + APPNAME + '.app' prog_bin = blddir + '/default/' + APPNAME + '/' + APPNAME if Params.g_options.exe: @@ -93,7 +101,7 @@ def shutdown(): os.makedirs(app_bundle + '/Contents/MacOS') # create the semi-useful PkgInfo file - f = file(app_bundle + '/Contents/PkgInfo', 'w') + f = open(app_bundle + '/Contents/PkgInfo', 'w') f.write('APPL????') f.close() @@ -101,7 +109,7 @@ def shutdown(): shutil.copy(prog_bin, app_bundle + '/Contents/MacOS/' + os.path.basename(prog_bin)) # write Info.plist - f = file(os.path.join(app_bundle, "Contents", "Info.plist"), "w") + f = open(os.path.join(app_bundle, "Contents", "Info.plist"), "w") f.write(app_info) f.write("\tCFBundleExecutable\n\t%s\n" % os.path.basename(prog_bin)) @@ -118,10 +126,145 @@ def shutdown(): for lang in languages: langdir = app_bundle + '/Contents/Resources/' + lang + '.lproj' os.makedirs(langdir) - f = file(os.path.join(langdir, "locversion.plist"), "w") + f = open(os.path.join(langdir, "locversion.plist"), "w") f.write(locversion % lang) f.close() except IOError, arg: print "IOError", arg + sys.exit(1) + + print "created bundle " + app_bundle + if Params.g_options.monolithic: + if not Params.g_options.bundle: + print "--monolithic requires --bundle" + sys.exit(1) + + fwdir = app_bundle + "/Contents/Frameworks" + + try: + # remove any old frameworks + if os.path.exists(fwdir): + shutil.rmtree(fwdir) + os.makedirs(fwdir) + + # define Qt libraries which are needed by other Qt libraries + lib_depends = {} + lib_depends['QtGui'] = (['QtCore']) + lib_depends['QtXml'] = (['QtCore']) + lib_depends['QtSql'] = (['QtCore']) + lib_depends['QtTest'] = (['QtCore']) + lib_depends['QtNetwork'] = (['QtCore']) + lib_depends['QtOpenGL'] = (['QtCore'], ['QtGui']) + lib_depends['QtDesigner'] = (['QtCore'], ['QtGui'], ['QtXml']) + lib_depends['QtDesignerComponents'] = (['QtCore'], ['QtGui'], ['QtXml'], ['QtDesigner']) + lib_depends['QtSvg'] = (['QtCore'], ['QtGui'], ['QtXml']) + lib_depends['QtAssistantClient'] = (['QtCore'], ['QtGui'], ['QtNetwork']) + lib_depends['Qt3Support'] = (['QtCore'], ['QtGui'], ['QtXml'], ['QtSql'], ['QtNetwork']) + + qtdir=detect_qt4_dir() + + for lib in qt4libs: + print ">>> Processing " + lib + + if not os.path.isdir(qtdir + "/lib/" + lib + ".framework"): + print "Couldn't find " + lib + ".framework in "+qtdir + sys.exit(1) + + shutil.copytree(qtdir + "/lib/" + lib + ".framework", fwdir + "/" + lib + ".framework", True) + print lib + " copied." + + print "Changing identifier of lib..." + os.popen('install_name_tool -id "@executable_path/../Frameworks/'+lib+'.framework/Versions/4/'+lib+'" "'+fwdir+'/'+lib+'.framework/Versions/4/'+lib+'"') + + if lib_depends.has_key(lib): + print "Changing identifiers for dependent libs..." + for deplib in lib_depends[lib]: + os.popen('install_name_tool -change "'+qtdir+'/lib/'+deplib+'.framework/Versions/4/'+deplib+'" "@executable_path/../Frameworks/'+deplib+'.framework/Versions/4/'+deplib+'" "'+fwdir+'/'+lib+'.framework/Versions/Current/'+lib+'"') + + print "Changing identifier in binary..." + os.popen('install_name_tool -change "'+qtdir+'/lib/'+lib+'.framework/Versions/4/'+lib+'" "@executable_path/../Frameworks/'+lib+'.framework/Versions/4/'+lib+'" "'+app_bundle+'/Contents/MacOS/'+APPNAME+'"') + + print "Removing any debug libraries and headers..." + os.popen('find "'+fwdir+'" | egrep "debug|Headers" | xargs rm -rf') + + except: + print "An error occured", sys.exc_info() + traceback.print_tb(sys.exc_info()[2]) + sys.exit(1) + print "All dependencies processed." + + if Params.g_options.dmg: + if not Params.g_options.bundle: + print "--dmg requires --bundle" + sys.exit(1) + + try: + print ">>> Preparing files..." + tempdir = tempfile.mkdtemp(); + shutil.copytree(app_bundle, tempdir + "/" + os.path.basename(app_bundle), True) + + for file in dmgfiles: + if not os.path.exists(file): + print "Skipping " + file +", not found." + continue + target = tempdir + "/" + os.path.basename(file) + if os.path.isdir(file): + shutil.copytree(file, target, True) + else: + shutil.copy(file, target) + + dmgpath = blddir + "/default/" + APPNAME + ".dmg" + + print ">>> Creating disk image..." + if os.path.exists(dmgpath): + os.remove(dmgpath) + # format UDBZ: bzip2 compressed (10.4+), UDZ0: zlib compressed (default) + print "".join(os.popen('hdiutil create -srcfolder "'+tempdir+'" -format UDBZ -volname "'+APPNAME+'" "'+dmgpath+'"').readlines()).strip() + + print ">>> Removing temporary directory..." + shutil.rmtree(tempdir) + + except: + print "An error occured", sys.exc_info() + traceback.print_tb(sys.exc_info()[2]) + sys.exit(1) + +def detect_qt4_dir(): + qtdir = os.environ.get('QT4_ROOT', '') + + if not qtdir: + qtdir = os.environ.get('QTDIR', '') + + qtdir = os.path.realpath(qtdir) + + if not qtdir: + try: + lst = os.listdir('/usr/local/Trolltech/') + lst.sort() + lst.reverse() + qtdir = '/usr/local/Trolltech/%s/' % lst[0] + + except OSError: + pass + + if not qtdir: + try: + path = os.environ['PATH'].split(':') + for qmk in ['qmake-qt4', 'qmake4', 'qmake']: + qmake = conf.find_program(qmk, path) + if qmake: + version = os.popen(qmake+" -query QT_VERSION").read().strip().split('.') + if version[0] == "4": + qtdir = os.popen(qmake + " -query QT_INSTALL_PREFIX").read().strip() + break; + except OSError: + pass + + if not qtdir: + print "Could not determine Qt installation directory." + sys.exit(1) + + return qtdir +