Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 481 lines (395 sloc) 15.193 kb
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
1 """
2 This paver file is intented to help with the release process as much as
3 possible. It relies on virtualenv to generate 'bootstrap' environments as
4 independent from the user system as possible (e.g. to make sure the sphinx doc
5 is built against the built scipy, not an installed one).
6
7 Building a simple (no-superpack) windows installer from wine
8 ============================================================
9
10 It assumes that blas/lapack are in c:\local\lib inside drive_c. Build python
11 2.5 and python 2.6 installers.
12
13 paver bdist_wininst_simple
14
15 You will have to configure your wine python locations (WINE_PYS).
16
17 The superpack requires all the atlas libraries for every arch to be installed
18 (see SITECFG), and can then be built as follows::
19
20 paver bdist_superpack
21
22 Building changelog + notes
23 ==========================
24
25 Assumes you have git and the binaries/tarballs in installers/::
26
27 paver write_release
28 paver write_note
29
30 This automatically put the checksum into NOTES.txt, and write the Changelog
31 which can be uploaded to sourceforge.
32
33 TODO
34 ====
35 - the script is messy, lots of global variables
36 - make it more easily customizable (through command line args)
37 - missing targets: install & test, sdist test, debian packaging
38 - fix bdist_mpkg: we build the same source twice -> how to make sure we use
39 the same underlying python for egg install in venv and for bdist_mpkg
40 """
41 import os
42 import sys
43 import subprocess
44 import re
45 import shutil
46 try:
47 from hash import md5
48 except ImportError:
49 import md5
50
51 import distutils
52
53 try:
54 from paver.tasks import VERSION as _PVER
55 if not _PVER >= '1.0':
56 raise RuntimeError("paver version >= 1.0 required (was %s)" % _PVER)
57 except ImportError, e:
58 raise RuntimeError("paver version >= 1.0 required")
59
60 import paver
61 import paver.doctools
62 import paver.path
cbb82e4 David Cournapeau Fix bdist_wininst_simple task.
cournape authored
63 from paver.easy import options, Bunch, task, needs, dry, sh, call_task, cmdopts
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
64
65 sys.path.insert(0, os.path.dirname(__file__))
66 try:
67 setup_py = __import__("setup")
68 FULLVERSION = setup_py.FULLVERSION
69 finally:
70 sys.path.pop(0)
71
b8fa0df David Cournapeau Do not hardcode python version anymore in bdist_mpkg.
cournape authored
72 # Default python version
73 PYVER="2.5"
74
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
75 # Wine config for win32 builds
f53f767 David Cournapeau Fix paver file to handle bdist targets on windows.
cournape authored
76 if sys.platform == "win32":
77 WINE_PY25 = [r"C:\Python25\python.exe"]
78 WINE_PY26 = [r"C:\Python26\python26.exe"]
79 elif sys.platform == "darwin":
352b639 David Cournapeau Fix wine build under darwin.
cournape authored
80 WINE_PY25 = ["/Applications/Darwine/Wine.bundle/Contents/bin/wine",
81 "/Users/david/.wine/drive_c/Python25/python.exe"]
82 WINE_PY26 = ["/Applications/Darwine/Wine.bundle/Contents/bin/wine",
83 "/Users/david/.wine/drive_c/Python26/python.exe"]
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
84 else:
352b639 David Cournapeau Fix wine build under darwin.
cournape authored
85 WINE_PY25 = ["/home/david/.wine/drive_c/Python25/python.exe"]
86 WINE_PY26 = ["/home/david/.wine/drive_c/Python26/python.exe"]
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
87 WINE_PYS = {'2.6' : WINE_PY26, '2.5': WINE_PY25}
88 SUPERPACK_BUILD = 'build-superpack'
89 SUPERPACK_BINDIR = os.path.join(SUPERPACK_BUILD, 'binaries')
90
91 # XXX: fix this in a sane way
b8fa0df David Cournapeau Do not hardcode python version anymore in bdist_mpkg.
cournape authored
92 MPKG_PYTHON = {"2.5": "/Library/Frameworks/Python.framework/Versions/2.5/bin/python",
93 "2.6": "/Library/Frameworks/Python.framework/Versions/2.6/bin/python"}
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
94 # Full path to the *static* gfortran runtime
95 LIBGFORTRAN_A_PATH = "/usr/local/lib/libgfortran.a"
96
97 # Where to put built documentation (where it will picked up for copy to
98 # binaries)
99 PDF_DESTDIR = paver.path.path('build') / 'pdf'
100 HTML_DESTDIR = paver.path.path('build') / 'html'
101 DOC_ROOT = paver.path.path("doc")
102 DOC_SRC = DOC_ROOT / "source"
103 DOC_BLD = DOC_ROOT / "build"
104 DOC_BLD_LATEX = DOC_BLD / "latex"
105
106 # Source of the release notes
107 RELEASE = 'doc/release/0.8.0-notes.rst'
108
109 # Start/end of the log (from git)
110 LOG_START = 'svn/tags/0.7.0'
111 LOG_END = 'master'
112
113 # Virtualenv bootstrap stuff
114 BOOTSTRAP_DIR = "bootstrap"
115 BOOTSTRAP_PYEXEC = "%s/bin/python" % BOOTSTRAP_DIR
116 BOOTSTRAP_SCRIPT = "%s/bootstrap.py" % BOOTSTRAP_DIR
117
118 # Where to put the final installers, as put on sourceforge
119 RELEASE_DIR = 'release'
120 INSTALLERS_DIR = os.path.join(RELEASE_DIR, 'installers')
121
122
123 options(sphinx=Bunch(builddir="build", sourcedir="source", docroot='doc'),
124 virtualenv=Bunch(script_name=BOOTSTRAP_SCRIPT,
125 packages_to_install=["sphinx==0.6.1"]),
126 wininst=Bunch(pyver="2.5", scratch=True))
127
128 # Bootstrap stuff
129 @task
130 def bootstrap():
131 """create virtualenv in ./install"""
132 install = paver.path.path(BOOTSTRAP_DIR)
133 if not install.exists():
134 install.mkdir()
135 call_task('paver.virtual.bootstrap')
136 sh('cd %s; %s bootstrap.py' % (BOOTSTRAP_DIR, sys.executable))
137
138 @task
139 def clean():
140 """Remove build, dist, egg-info garbage."""
141 d = ['build', 'dist', 'scipy.egg-info']
142 for i in d:
143 paver.path.path(i).rmtree()
144
145 (paver.path.path('doc') / options.sphinx.builddir).rmtree()
146
147 @task
148 def clean_bootstrap():
149 paver.path.path('bootstrap').rmtree()
150
151 @task
152 @needs('clean', 'clean_bootstrap')
153 def nuke():
154 """Remove everything: build dir, installers, bootstrap dirs, etc..."""
155 d = [SUPERPACK_BUILD, INSTALLERS_DIR]
156 for i in d:
157 paver.path.path(i).rmtree()
158
159 # NOTES/Changelog stuff
160 def compute_md5():
161 released = paver.path.path(INSTALLERS_DIR).listdir()
162 checksums = []
163 for f in released:
164 m = md5.md5(open(f, 'r').read())
165 checksums.append('%s %s' % (m.hexdigest(), f))
166
167 return checksums
168
169 def write_release_task(filename='NOTES.txt'):
170 source = paver.path.path(RELEASE)
171 target = paver.path.path(filename)
172 if target.exists():
173 target.remove()
174 source.copy(target)
175 ftarget = open(str(target), 'a')
176 ftarget.writelines("""
177 Checksums
178 =========
179
180 """)
181 ftarget.writelines(['%s\n' % c for c in compute_md5()])
182
183 def write_log_task(filename='Changelog'):
184 st = subprocess.Popen(
185 ['git', 'svn', 'log', '%s..%s' % (LOG_START, LOG_END)],
186 stdout=subprocess.PIPE)
187
188 out = st.communicate()[0]
189 a = open(filename, 'w')
190 a.writelines(out)
191 a.close()
192
193 @task
194 def write_release():
195 write_release_task()
196
197 @task
198 def write_log():
199 write_log_task()
200
201 #------------
202 # Doc tasks
203 #------------
204 @task
205 def html(options):
206 """Build scipy documentation and put it into build/docs"""
207 # Don't use paver html target because of scipy bootstrapping problems
208 subprocess.check_call(["make", "html"], cwd="doc")
209 builtdocs = paver.path.path("doc") / options.sphinx.builddir / "html"
210 HTML_DESTDIR.rmtree()
211 builtdocs.copytree(HTML_DESTDIR)
212
213 @task
214 def latex():
215 """Build scipy documentation in latex format."""
216 subprocess.check_call(["make", "latex"], cwd="doc")
217
218 @task
219 @needs('latex')
220 def pdf():
221 def build_pdf():
222 subprocess.check_call(["make", "all-pdf"], cwd=str(DOC_BLD_LATEX))
223 dry("Build pdf doc", build_pdf)
224
225 PDF_DESTDIR.rmtree()
226 PDF_DESTDIR.makedirs()
227
228 user = DOC_BLD_LATEX / "scipy-user.pdf"
229 user.copy(PDF_DESTDIR / "userguide.pdf")
230 ref = DOC_BLD_LATEX / "scipy-ref.pdf"
231 ref.copy(PDF_DESTDIR / "reference.pdf")
232
233 def tarball_name(type='gztar'):
234 root = 'scipy-%s' % FULLVERSION
235 if type == 'gztar':
236 return root + '.tar.gz'
237 elif type == 'zip':
238 return root + '.zip'
239 raise ValueError("Unknown type %s" % type)
240
241 @task
242 def sdist():
243 # To be sure to bypass paver when building sdist... paver + scipy.distutils
244 # do not play well together.
245 sh('python setup.py sdist --formats=gztar,zip')
246
247 # Copy the superpack into installers dir
248 if not os.path.exists(INSTALLERS_DIR):
249 os.makedirs(INSTALLERS_DIR)
250
251 for t in ['gztar', 'zip']:
252 source = os.path.join('dist', tarball_name(t))
253 target = os.path.join(INSTALLERS_DIR, tarball_name(t))
254 shutil.copy(source, target)
255
256 #------------------
257 # Wine-based builds
258 #------------------
747dc66 David Cournapeau Fix ATLAS/SSE handling for wine builds.
cournape authored
259 SSE3_CFG = {'BLAS': 'None', 'LAPACK': 'None', 'ATLAS': r'C:\local\lib\yop\sse3'}
260 SSE2_CFG = {'BLAS': 'None', 'LAPACK': 'None', 'ATLAS': r'C:\local\lib\yop\sse2'}
261 NOSSE_CFG = {'ATLAS': 'None', 'BLAS': r'C:\local\lib\yop\nosse', 'LAPACK': r'C:\local\lib\yop\nosse'}
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
262
263 SITECFG = {"sse2" : SSE2_CFG, "sse3" : SSE3_CFG, "nosse" : NOSSE_CFG}
264
265 def internal_wininst_name(arch, ismsi=False):
266 """Return the name of the wininst as it will be inside the superpack (i.e.
267 with the arch encoded."""
268 if ismsi:
269 ext = '.msi'
270 else:
271 ext = '.exe'
272 return "scipy-%s-%s%s" % (FULLVERSION, arch, ext)
273
274 def wininst_name(pyver, ismsi=False):
275 """Return the name of the installer built by wininst command."""
276 # Yeah, the name logic is harcoded in distutils. We have to reproduce it
277 # here
278 if ismsi:
279 ext = '.msi'
280 else:
281 ext = '.exe'
282 name = "scipy-%s.win32-py%s%s" % (FULLVERSION, pyver, ext)
283 return name
284
285 def bdist_wininst_arch(pyver, arch, scratch=True):
286 """Arch specific wininst build."""
287 if scratch:
288 paver.path.path('build').rmtree()
289
290 if not os.path.exists(SUPERPACK_BINDIR):
291 os.makedirs(SUPERPACK_BINDIR)
e0da5ef David Cournapeau Fix bdist_wininst_arch task on win32.
cournape authored
292 env = os.environ.copy()
293 for k, v in SITECFG[arch].items():
294 env[k] = v
295 _bdist_wininst(pyver, env)
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
296 source = os.path.join('dist', wininst_name(pyver))
297 target = os.path.join(SUPERPACK_BINDIR, internal_wininst_name(arch))
298 if os.path.exists(target):
299 os.remove(target)
300 os.rename(source, target)
301
302 def superpack_name(pyver, numver):
303 """Return the filename of the superpack installer."""
304 return 'scipy-%s-win32-superpack-python%s.exe' % (numver, pyver)
305
306 def prepare_nsis_script(pyver, numver):
307 if not os.path.exists(SUPERPACK_BUILD):
308 os.makedirs(SUPERPACK_BUILD)
309
d426942 David Cournapeau Fix nsis template location.
cournape authored
310 tpl = os.path.join('tools/win32/build_scripts/nsis_scripts', 'scipy-superinstaller.nsi.in')
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
311 source = open(tpl, 'r')
312 target = open(os.path.join(SUPERPACK_BUILD, 'scipy-superinstaller.nsi'), 'w')
313
314 installer_name = superpack_name(pyver, numver)
315 cnt = "".join(source.readlines())
6d54df7 David Cournapeau Fix bdist_superpack paver task (forgot to change name from numpy to scip...
cournape authored
316 cnt = cnt.replace('@SCIPY_INSTALLER_NAME@', installer_name)
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
317 for arch in ['nosse', 'sse2', 'sse3']:
318 cnt = cnt.replace('@%s_BINARY@' % arch.upper(),
319 internal_wininst_name(arch))
320
321 target.write(cnt)
322
323 @task
324 def bdist_wininst_nosse(options):
325 """Build the nosse wininst installer."""
326 bdist_wininst_arch(options.wininst.pyver, 'nosse', scratch=options.wininst.scratch)
327
328 @task
329 def bdist_wininst_sse2(options):
330 """Build the sse2 wininst installer."""
331 bdist_wininst_arch(options.wininst.pyver, 'sse2', scratch=options.wininst.scratch)
332
333 @task
334 def bdist_wininst_sse3(options):
335 """Build the sse3 wininst installer."""
336 bdist_wininst_arch(options.wininst.pyver, 'sse3', scratch=options.wininst.scratch)
337
338 @task
339 @needs('bdist_wininst_nosse', 'bdist_wininst_sse2', 'bdist_wininst_sse3')
340 def bdist_superpack(options):
341 """Build all arch specific wininst installers."""
342 prepare_nsis_script(options.wininst.pyver, FULLVERSION)
343 subprocess.check_call(['makensis', 'scipy-superinstaller.nsi'],
344 cwd=SUPERPACK_BUILD)
345
346 # Copy the superpack into installers dir
347 if not os.path.exists(INSTALLERS_DIR):
348 os.makedirs(INSTALLERS_DIR)
349
350 source = os.path.join(SUPERPACK_BUILD,
351 superpack_name(options.wininst.pyver, FULLVERSION))
352 target = os.path.join(INSTALLERS_DIR,
353 superpack_name(options.wininst.pyver, FULLVERSION))
354 shutil.copy(source, target)
355
356 @task
cbb82e4 David Cournapeau Fix bdist_wininst_simple task.
cournape authored
357 @cmdopts([('python_version=', 'p', 'Python version to build the installer against')])
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
358 def bdist_wininst_simple():
359 """Simple wininst-based installer."""
cbb82e4 David Cournapeau Fix bdist_wininst_simple task.
cournape authored
360 call_task("clean")
f53f767 David Cournapeau Fix paver file to handle bdist targets on windows.
cournape authored
361 env = os.environ.copy()
362 for k, v in SITECFG['nosse'].items():
363 env[k] = v
364 _bdist_wininst(options.bdist_wininst_simple.python_version, env)
365
366 def _bdist_wininst(pyver, cfg_env):
367 log = open('build.log', 'w')
368 try:
369 ret = subprocess.call(WINE_PYS[pyver] + ['setup.py', 'build', '-c', 'mingw32', 'bdist_wininst'],
370 env=cfg_env, stdout=log, stderr=subprocess.STDOUT)
371 finally:
372 log.close()
373
374 if ret:
375 raise RuntimeError("Error while building windows installer, see build.log")
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
376
377 #-------------------
378 # Mac OS X installer
379 #-------------------
380 def macosx_version():
381 if not sys.platform == 'darwin':
382 raise ValueError("Not darwin ??")
383 st = subprocess.Popen(["sw_vers"], stdout=subprocess.PIPE)
384 out = st.stdout.readlines()
385 ver = re.compile("ProductVersion:\s+([0-9]+)\.([0-9]+)\.([0-9]+)")
386 for i in out:
387 m = ver.match(i)
388 if m:
389 return m.groups()
390
391 def mpkg_name():
392 maj, min = macosx_version()[:2]
393 pyver = ".".join([str(i) for i in sys.version_info[:2]])
394 return "scipy-%s-py%s-macosx%s.%s.mpkg" % \
395 (FULLVERSION, pyver, maj, min)
396
397 def dmg_name():
398 #maj, min = macosx_version()[:2]
399 pyver = ".".join([str(i) for i in sys.version_info[:2]])
400 #return "scipy-%s-py%s-macosx%s.%s.dmg" % \
401 # (FULLVERSION, pyver, maj, min)
402 return "scipy-%s-py%s-python.org.dmg" % \
403 (FULLVERSION, pyver)
404
405 def prepare_static_gfortran_runtime(d):
406 if not os.path.exists(d):
407 os.makedirs(d)
408 shutil.copy(LIBGFORTRAN_A_PATH, d)
409
410 @task
b8fa0df David Cournapeau Do not hardcode python version anymore in bdist_mpkg.
cournape authored
411 @cmdopts([('python_version=', 'p', 'Python version to build the installer against')])
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
412 def bdist_mpkg():
413 call_task("clean")
414
b8fa0df David Cournapeau Do not hardcode python version anymore in bdist_mpkg.
cournape authored
415 try:
416 pyver = options.bdist_mpkg.python_version
417 except AttributeError:
418 pyver = PYVER
419
28a5f5f David Cournapeau Add paver file for scipy.
cournape authored
420 prepare_static_gfortran_runtime("build")
421 ldflags = "-undefined dynamic_lookup -bundle -arch i386 -arch ppc -Wl,-search_paths_first"
422 ldflags += " -L%s" % os.path.join(os.path.dirname(__file__), "build")
423 sh("LDFLAGS='%s' %s setupegg.py bdist_mpkg" % (ldflags, MPKG_PYTHON[pyver]))
424
425 @task
426 @needs("bdist_mpkg", "pdf")
427 def dmg():
428 pyver = ".".join([str(i) for i in sys.version_info[:2]])
429
430 dmg_n = dmg_name()
431 dmg = paver.path.path('scipy-macosx-installer') / dmg_n
432 if dmg.exists():
433 dmg.remove()
434
435 # Clean the image source
436 content = DMG_CONTENT
437 content.rmtree()
438 content.mkdir()
439
440 # Copy mpkg into image source
441 mpkg_n = mpkg_name()
442 mpkg_tn = "scipy-%s-py%s.mpkg" % (FULLVERSION, pyver)
443 mpkg_source = paver.path.path("dist") / mpkg_n
444 mpkg_target = content / mpkg_tn
445 mpkg_source.copytree(content / mpkg_tn)
446
447 # Copy docs into image source
448
449 #html_docs = HTML_DESTDIR
450 #html_docs.copytree(content / "Documentation" / "html")
451
452 pdf_docs = DMG_CONTENT / "Documentation"
453 pdf_docs.rmtree()
454 pdf_docs.makedirs()
455
456 user = PDF_DESTDIR / "userguide.pdf"
457 user.copy(pdf_docs / "userguide.pdf")
458 ref = PDF_DESTDIR / "reference.pdf"
459 ref.copy(pdf_docs / "reference.pdf")
460
461 # Build the dmg
462 cmd = ["./create-dmg", "--window-size", "500", "500", "--background",
463 "art/dmgbackground.png", "--icon-size", "128", "--icon", mpkg_tn,
464 "125", "320", "--icon", "Documentation", "375", "320", "--volname", "scipy",
465 dmg_n, "./content"]
466 subprocess.check_call(cmd, cwd="scipy-macosx-installer")
467
468 @task
469 def simple_dmg():
470 # Build the dmg
471 image_name = dmg_name()
472 image = paver.path.path(image_name)
473 image.remove()
474 cmd = ["hdiutil", "create", image_name, "-srcdir", str("dist")]
475 sh(" ".join(cmd))
476
477 @task
478 def write_note_changelog():
479 write_release_task(os.path.join(RELEASE_DIR, 'NOTES.txt'))
480 write_log_task(os.path.join(RELEASE_DIR, 'Changelog'))
Something went wrong with that request. Please try again.