-
Notifications
You must be signed in to change notification settings - Fork 1
/
build.py
239 lines (211 loc) · 6.06 KB
/
build.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
from setuptools import setup
from sys import platform, argv
import os
from shutil import rmtree, copytree
import zipfile
# TODO: do we really need to still support simplejson?
# if OSX builds for 2.6 let's ditch it
using_simplejson = False
try:
from simplejson import dumps
using_simplejson = True
except ImportError:
from json import dumps
from bzrlib.branch import Branch
# get the current bzr version number
revno = Branch.open(".").revno()
app = 'Infinite8BitPlatformer'
# remove the build and dist directories
def clean():
print "Removing build and dist directories"
for d in ["build", "dist"]:
if os.path.isdir(d):
rmtree(d)
clean()
# the default os string and extension for each platform
platforms = {
"darwin": ("osx", ".app", "dist/Infinite8BitPlatformer.app/Contents/Resources"),
"win32": ("windows", "", "dist"),
"linux2": ("linux", "", "dist"),
}
# more convenient representation of the platform config
config = {
"platform": platform,
"os": platforms[platform][0],
"extension": platforms[platform][1],
"resources": platforms[platform][2],
"revno": revno,
}
# output the build.json config file for this build
print "Writing build.json file"
version_file = file(os.path.join("resources", "build.json"), "w")
version_file.write(dumps(config))
version_file.close()
### PLATFORM SPECIFIC SECTION ###
# mac osx
if platform == "darwin":
# add mac specific options
options = {
'includes': ['pygame'],
'resources': ['resources',],
'argv_emulation': True,
'iconfile': 'resources/icon.icns',
'semi_standalone': False,
}
if using_simplejson:
options['includes'].insert(0, 'simplejson')
# force the py2app build
argv.insert(1, "py2app")
# setup for mac .app (does the actual build)
setup(
setup_requires=['py2app'],
app=[app + ".py"],
options={'py2app': options},
)
elif platform == "win32":
import py2exe
import pygame
import glob
import sys
# hack to patch in win32com support
# http://www.py2exe.org/index.cgi/win32com.shell
# ...
# ModuleFinder can't handle runtime changes to __path__, but win32com uses them
try:
# py2exe 0.6.4 introduced a replacement modulefinder.
# This means we have to add package paths there, not to the built-in
# one. If this new modulefinder gets integrated into Python, then
# we might be able to revert this some day.
# if this doesn't work, try import modulefinder
try:
import py2exe.mf as modulefinder
except ImportError:
import modulefinder
import win32com
for p in win32com.__path__[1:]:
modulefinder.AddPackagePath("win32com", p)
for extra in ["win32com.shell"]: #,"win32com.mapi"
__import__(extra)
m = sys.modules[extra]
for p in m.__path__[1:]:
modulefinder.AddPackagePath(extra, p)
except ImportError:
# no build path setup, no worries.
pass
# hack to include simplejson egg in the build
if using_simplejson:
import pkg_resources
eggs = pkg_resources.require("simplejson")
from setuptools.archive_util import unpack_archive
for egg in eggs:
if os.path.isdir(egg.location):
copytree(egg.location, ".")
else:
unpack_archive(egg.location, ".")
rmtree("EGG-INFO")
# windows specific options
options = {
"script": app + ".py",
"icon_resources": [(1, os.path.join("resources", "main.ico"))],
}
resources = ['resources',]
# horrible monkey patch to make sdl mixer include work (say what?)
# http://www.python-forum.org/pythonforum/viewtopic.php?f=3&t=19455&start=0
origIsSystemDLL = py2exe.build_exe.isSystemDLL
def isSystemDLL(pathname):
if os.path.basename(pathname).lower() in ("libogg-0.dll", "sdl_ttf.dll"):
return 0
return origIsSystemDLL(pathname)
py2exe.build_exe.isSystemDLL = isSystemDLL
# stuff for shrinking the final binary
# http://www.moviepartners.com/blog/2009/03/20/making-py2exe-play-nice-with-pygame/
INCLUDE_STUFF = ['encodings', "encodings.latin_1", "pygame", "win32com.shell"]
MODULE_EXCLUDES =[
'email',
'AppKit',
'Foundation',
'bdb',
'difflib',
'tcl',
'Tkinter',
'Tkconstants',
'curses',
'distutils',
'setuptools',
#'urllib',
#'urllib2',
#'urlparse',
#'BaseHTTPServer',
'_LWPCookieJar',
'_MozillaCookieJar',
'ftplib',
'gopherlib',
#'_ssl',
'htmllib',
'httplib',
#'mimetools',
'mimetypes',
#'rfc822',
'tty',
#'webbrowser',
#'socket',
#'hashlib',
#'base64',
'compiler',
'pydoc',
'bzrlib',
]
# the rest of this stuff is from the original
# force the py2exe build
argv.insert(1, "py2exe")
# setup for windows .exe (does the actual build)
setup(
setup_requires = ['py2exe'],
windows=[options],
options = {
"py2exe": {
"optimize": 2,
"includes": INCLUDE_STUFF,
"compressed": 1,
#"ascii": 1,
# whether all library files should be bundled into the exe
"bundle_files": 2,
"ignores": ['tcl', 'AppKit', 'Numeric', 'Foundation'],
"excludes": MODULE_EXCLUDES
}
},
zipfile = None,
)
# manually copy resources as I couldn't get it to happen with py2exe
for r in resources:
print 'Copying resource "%s"' % r
copytree(r, os.path.join("dist", r))
if using_simplejson:
# get rid of simplejson directory
rmtree("simplejson")
elif platform == "linux2":
os.mkdir(platforms[platform][2])
copytree("resources", os.path.join("dist", "resources"))
### PLATFORM SECTION DONE ###
# zip up our app to the correctly named zipfile
def recursive_zip(zipf, directory, root=None):
if not root:
root = os.path.basename(directory)
list = os.listdir(directory)
for file in list:
realpath = os.path.join(directory, file)
arcpath = os.path.join(root, file)
print "Zipping:", arcpath
if os.path.isfile(realpath):
zipf.write(realpath, arcpath)
elif os.path.isdir(realpath):
recursive_zip(zipf, realpath, arcpath)
outfilename = "%s-%d-%s%s.zip" % (app, revno, config["os"], config["extension"])
zipout = zipfile.ZipFile(outfilename, "w")
recursive_zip(zipout, os.path.join("dist", platform == "darwin" and app + config["extension"] or ""))
zipout.close()
# clean up afterwards
clean()
# output the build-finished message
print "--- done ---"
print "Created %s" % outfilename