Script to create .app bundles. Largely untested.
diff --git a/Mac/scripts/buildappbundle.py b/Mac/scripts/buildappbundle.py
new file mode 100755
index 0000000..93ef14b
--- /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 = """
+			<key>NSMainNibFile</key>
+			<string>%s</string>
+			<key>NSPrincipalClass</key>
+			<string>NSApplication</string>""" % nibname
+		else:
+			cocoainfo = ""
+		plistdata = \
+"""<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+        <key>CFBundleDevelopmentRegion</key>
+        <string>English</string>
+        <key>CFBundleExecutable</key>
+        <string>%s</string>
+        <key>CFBundleInfoDictionaryVersion</key>
+        <string>6.0</string>
+        <key>CFBundlePackageType</key>
+        <string>APPL</string>
+        <key>CFBundleSignature</key>
+        <string>%s</string>
+        <key>CFBundleVersion</key>
+        <string>0.1</string>
+        %s
+</dict>
+</plist>
+""" % (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