Updated bundlebuilder to version in Python 2.3a2 + my --libs patch

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@19650 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2003-03-21 03:31:14 +00:00
parent 3416be29f9
commit 78e5c4e9b5

View File

@@ -37,7 +37,6 @@ import getopt
from plistlib import Plist
from types import FunctionType as function
class BundleBuilderError(Exception): pass
@@ -84,7 +83,7 @@ class BundleBuilder(Defaults):
CFBundleInfoDictionaryVersion = "6.0")
# The type of the bundle.
type = "APPL"
type = "BNDL"
# The creator code of the bundle.
creator = None
@@ -102,9 +101,6 @@ class BundleBuilder(Defaults):
# Directory where the bundle will be assembled.
builddir = "build"
# platform, name of the subfolder of Contents that contains the executable.
platform = "MacOS"
# Make symlinks instead copying files. This is handy during debugging, but
# makes the bundle non-distributable.
symlink = 0
@@ -120,7 +116,6 @@ class BundleBuilder(Defaults):
bundleextension = ext
# misc (derived) attributes
self.bundlepath = pathjoin(self.builddir, self.name + bundleextension)
self.execdir = pathjoin("Contents", self.platform)
plist = self.plist
plist.CFBundleName = self.name
@@ -216,7 +211,7 @@ else:
PYC_EXT = ".pyo"
MAGIC = imp.get_magic()
USE_ZIPIMPORT = 0 ## "zipimport" in sys.builtin_module_names
USE_ZIPIMPORT = "zipimport" in sys.builtin_module_names
# For standalone apps, we have our own minimal site.py. We don't need
# all the cruft of the real site.py.
@@ -236,6 +231,10 @@ if USE_ZIPIMPORT:
SITE_CO = compile(SITE_PY, "<-bundlebuilder.py->", "exec")
#
# Extension modules can't be in the modules zip archive, so a placeholder
# is added instead, that loads the extension from a specified location.
#
EXT_LOADER = """\
def __load():
import imp, sys, os
@@ -258,23 +257,55 @@ MAYMISS_MODULES = ['mac', 'os2', 'nt', 'ntpath', 'dos', 'dospath',
STRIP_EXEC = "/usr/bin/strip"
#
# We're using a stock interpreter to run the app, yet we need
# a way to pass the Python main program to the interpreter. The
# bootstrapping script fires up the interpreter with the right
# arguments. os.execve() is used as OSX doesn't like us to
# start a real new process. Also, the executable name must match
# the CFBundleExecutable value in the Info.plist, so we lie
# deliberately with argv[0]. The actual Python executable is
# passed in an environment variable so we can "repair"
# sys.executable later.
#
BOOTSTRAP_SCRIPT = """\
#!/bin/sh
#!%(hashbang)s
execdir=$(dirname "${0}")
DYLD_LIBRARY_PATH=$(dirname "${execdir}")/Frameworks
export DYLD_LIBRARY_PATH
executable=${execdir}/%(executable)s
resdir=$(dirname "${execdir}")/Resources
main=${resdir}/%(mainprogram)s
PYTHONPATH=$resdir
export PYTHONPATH
exec "${executable}" "${main}" "${1}"
import sys, os
execdir = os.path.dirname(sys.argv[0])
executable = os.path.join(execdir, "%(executable)s")
resdir = os.path.join(os.path.dirname(execdir), "Resources")
libdir = os.path.join(os.path.dirname(execdir), "Frameworks")
mainprogram = os.path.join(resdir, "%(mainprogram)s")
sys.argv.insert(1, mainprogram)
os.environ["PYTHONPATH"] = resdir
os.environ["PYTHONHOME"] = resdir
os.environ["PYTHONEXECUTABLE"] = executable
os.environ["DYLD_LIBRARY_PATH"] = libdir
os.execve(executable, sys.argv, os.environ)
"""
#
# Optional wrapper that converts "dropped files" into sys.argv values.
#
ARGV_EMULATOR = """\
import argvemulator, os
argvemulator.ArgvCollector().mainloop()
execfile(os.path.join(os.path.split(__file__)[0], "%(realmainprogram)s"))
"""
class AppBuilder(BundleBuilder):
# Override type of the bundle.
type = "APPL"
# platform, name of the subfolder of Contents that contains the executable.
platform = "MacOS"
# A Python main program. If this argument is given, the main
# executable in the bundle will be a small wrapper that invokes
# the main program. (XXX Discuss why.)
@@ -299,6 +330,10 @@ class AppBuilder(BundleBuilder):
# If True, build standalone app.
standalone = 0
# If True, add a real main program that emulates sys.argv before calling
# mainprogram
argv_emulation = 0
# The following attributes are only used when building a standalone app.
@@ -332,6 +367,8 @@ class AppBuilder(BundleBuilder):
raise BundleBuilderError, ("must specify either or both of "
"'executable' and 'mainprogram'")
self.execdir = pathjoin("Contents", self.platform)
if self.name is not None:
pass
elif self.mainprogram is not None:
@@ -374,11 +411,40 @@ class AppBuilder(BundleBuilder):
if self.mainprogram is not None:
mainprogram = os.path.basename(self.mainprogram)
self.files.append((self.mainprogram, pathjoin(resdir, mainprogram)))
if self.argv_emulation:
# Change the main program, and create the helper main program (which
# does argv collection and then calls the real main).
# Also update the included modules (if we're creating a standalone
# program) and the plist
realmainprogram = mainprogram
mainprogram = '__argvemulator_' + mainprogram
resdirpath = pathjoin(self.bundlepath, resdir)
mainprogrampath = pathjoin(resdirpath, mainprogram)
makedirs(resdirpath)
open(mainprogrampath, "w").write(ARGV_EMULATOR % locals())
if self.standalone:
self.includeModules.append("argvemulator")
self.includeModules.append("os")
if not self.plist.has_key("CFBundleDocumentTypes"):
self.plist["CFBundleDocumentTypes"] = [
{ "CFBundleTypeOSTypes" : [
"****",
"fold",
"disk"],
"CFBundleTypeRole": "Viewer"}]
# Write bootstrap script
executable = os.path.basename(self.executable)
execdir = pathjoin(self.bundlepath, self.execdir)
bootstrappath = pathjoin(execdir, self.name)
makedirs(execdir)
if self.standalone:
# XXX we're screwed when the end user has deleted
# /usr/bin/python
hashbang = "/usr/bin/python"
else:
hashbang = sys.executable
while os.path.islink(hashbang):
hashbang = os.readlink(hashbang)
open(bootstrappath, "w").write(BOOTSTRAP_SCRIPT % locals())
os.chmod(bootstrappath, 0775)
@@ -462,6 +528,9 @@ class AppBuilder(BundleBuilder):
site.__code__ = SITE_CO
mf.scan_code(SITE_CO, site)
# warnings.py gets imported implicitly from C
mf.import_hook("warnings")
includeModules = self.includeModules[:]
for name in self.includePackages:
includeModules.extend(findPackageContents(name).keys())
@@ -623,8 +692,11 @@ Options:
-b, --builddir=DIR the build directory; defaults to "build"
-n, --name=NAME application name
-r, --resource=FILE extra file or folder to be copied to Resources
-f, --file=SRC:DST extra file or folder to be copied into the bundle;
DST must be a path relative to the bundle root
-e, --executable=FILE the executable to be used
-m, --mainprogram=FILE the Python main program
-a, --argv add a wrapper main program to create sys.argv
-p, --plist=FILE .plist file (default: generate one)
--nib=NAME main nib name
-c, --creator=CCCC 4-char creator code (default: '????')
@@ -634,8 +706,8 @@ Options:
--link-exec symlink the executable instead of copying it
--standalone build a standalone application, which is fully
independent of a Python installation
--lib=FILE shared library or framework to be copied into
the bundle
--lib=FILE shared library or framework to be copied into
the bundle
-x, --exclude=MODULE exclude module (with --standalone)
-i, --include=MODULE include module (with --standalone)
--package=PACKAGE include a whole package (with --standalone)
@@ -655,10 +727,10 @@ def main(builder=None):
if builder is None:
builder = AppBuilder(verbosity=1)
shortopts = "b:n:r:e:m:c:p:lx:i:hvq"
longopts = ("builddir=", "name=", "resource=", "executable=",
shortopts = "b:n:r:f:e:m:c:p:lx:i:hvqa"
longopts = ("builddir=", "name=", "resource=", "file=", "executable=",
"mainprogram=", "creator=", "nib=", "plist=", "link",
"link-exec", "help", "verbose", "quiet", "standalone",
"link-exec", "help", "verbose", "quiet", "argv", "standalone",
"exclude=", "include=", "package=", "strip", "iconfile=",
"lib=")
@@ -674,10 +746,18 @@ def main(builder=None):
builder.name = arg
elif opt in ('-r', '--resource'):
builder.resources.append(arg)
elif opt in ('-f', '--file'):
srcdst = arg.split(':')
if len(srcdst) != 2:
usage("-f or --file argument must be two paths, "
"separated by a colon")
builder.files.append(srcdst)
elif opt in ('-e', '--executable'):
builder.executable = arg
elif opt in ('-m', '--mainprogram'):
builder.mainprogram = arg
elif opt in ('-a', '--argv'):
builder.argv_emulation = 1
elif opt in ('-c', '--creator'):
builder.creator = arg
elif opt == '--iconfile':