diff --git a/Mac/scripts/buildappbundle.py b/Mac/scripts/buildappbundle.py
new file mode 100755
index 00000000000..93ef14b4831
--- /dev/null
+++ b/Mac/scripts/buildappbundle.py
@@ -0,0 +1,160 @@
+import sys
+import os
+import shutil
+import getopt
+
+def buildappbundle(executable, output=None, copyfunc=None, creator=None,
+ plist=None, nib=None, resources=None):
+ if not output:
+ output = os.path.split(executable)[1] + '.app'
+ if not copyfunc:
+ copyfunc = shutil.copy2
+ if not creator:
+ creator='????'
+ if not resources:
+ resources = []
+ if nib:
+ resources = resources + [nib]
+ #
+ # Create the main directory structure
+ #
+ if not os.path.isdir(output):
+ os.mkdir(output)
+ contents = os.path.join(output, 'Contents')
+ if not os.path.isdir(contents):
+ os.mkdir(contents)
+ macos = os.path.join(contents, 'MacOS')
+ if not os.path.isdir(macos):
+ os.mkdir(macos)
+ #
+ # Create the executable
+ #
+ shortname = os.path.split(executable)[1]
+ execname = os.path.join(macos, shortname)
+ try:
+ os.remove(execname)
+ except OSError:
+ pass
+ copyfunc(executable, execname)
+ #
+ # Create the PkgInfo file
+ #
+ pkginfo = os.path.join(contents, 'PkgInfo')
+ open(pkginfo, 'wb').write('APPL'+creator)
+ if plist:
+ # A plist file is specified. Read it.
+ plistdata = open(plist).read()
+ else:
+ #
+ # If we have a main NIB we create the extra Cocoa specific info for the plist file
+ #
+ if not nib:
+ nibname = ""
+ else:
+ nibname, ext = os.path.splitext(os.path.split(nib)[1])
+ if ext == '.lproj':
+ # Special case: if the main nib is a .lproj we assum a directory
+ # and use the first nib from there
+ files = os.listdir(nib)
+ for f in files:
+ if f[-4:] == '.nib':
+ nibname = os.path.split(f)[1][:-4]
+ break
+ else:
+ nibname = ""
+ if nibname:
+ cocoainfo = """
+ NSMainNibFile
+ %s
+ NSPrincipalClass
+ NSApplication""" % nibname
+ else:
+ cocoainfo = ""
+ plistdata = \
+"""
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ %s
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ APPL
+ CFBundleSignature
+ %s
+ CFBundleVersion
+ 0.1
+ %s
+
+
+""" % (shortname, creator, cocoainfo)
+ #
+ # Next, we create the plist file
+ #
+ infoplist = os.path.join(contents, 'Info.plist')
+ open(infoplist, 'w').write(plistdata)
+ #
+ # Finally, if there are nibs or other resources to copy we do so.
+ #
+ if resources:
+ resdir = os.path.join(contents, 'Resources')
+ for src in resources:
+ dst = os.path.join(resdir, os.path.split(src)[1])
+ if os.path.isdir(src):
+ shutil.copytree(src, dst)
+ else:
+ shutil.copy2(src, dst)
+
+def usage():
+ print "buildappbundle creates an application bundle"
+ print "Usage:"
+ print " buildappbundle [options] executable"
+ print "Options:"
+ print " --output o Output file; default executable with .app appended, short -o"
+ print " --link Symlink the executable (default: copy), short -l"
+ print " --plist file Plist file (default: generate one), short -p"
+ print " --nib file Main nib file or lproj folder for Cocoa program, short -n"
+ print " --resource r Extra resource file to be copied to Resources, short -r"
+ print " --creator c 4-char creator code (default: ????), short -c"
+ print " --help This message, short -?"
+ sys.exit(1)
+
+def main():
+ output=None
+ copyfunc=None
+ creator=None
+ plist=None
+ nib=None
+ resources=[]
+ SHORTOPTS = "o:ln:r:p:c:?"
+ LONGOPTS=("output=", "link", "nib=", "resource=", "plist=", "creator=", "help")
+ try:
+ options, args = getopt.getopt(sys.argv[1:], SHORTOPTS, LONGOPTS)
+ except getopt.error:
+ usage()
+ if len(args) != 1:
+ usage()
+ for opt, arg in options:
+ if opt in ('-o', '--output'):
+ output = arg
+ elif opt in ('-l', '--link'):
+ copyfunc = os.symlink
+ elif opt in ('-n', '--nib'):
+ nib = arg
+ elif opt in ('-r', '--resource'):
+ resources.append(arg)
+ elif opt in ('-c', '--creator'):
+ creator = arg
+ elif opt in ('-p', '--plist'):
+ plist = arg
+ elif opt in ('-?', '--help'):
+ usage()
+ buildappbundle(args[0], output=output, copyfunc=copyfunc, creator=creator,
+ plist=plist, resources=resources)
+
+if __name__ == '__main__':
+ main()
+
\ No newline at end of file