diff options
Diffstat (limited to 'bin/metabuild')
-rwxr-xr-x | bin/metabuild | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/bin/metabuild b/bin/metabuild new file mode 100755 index 0000000..4f1f509 --- /dev/null +++ b/bin/metabuild @@ -0,0 +1,133 @@ +#!/usr/bin/python + +# metabuild: Generic build system wrapper +# Copyright 2010 Colin Walters <walters@verbum.org> +# Licensed under the new-BSD license (http://www.opensource.org/licenses/bsd-license.php) + +# metabuild currently just wraps autotools (configure+make). +# To use it, you must first use the "inroot" tool to enter an alternative +# buildroot. +# +# $ inroot /path/to/buildroot bash +# +# Next, just type: +# $ metabuild +# This will: +# 1) Run ./configure if necessary +# 2) Run make +# +# The build output is automatically logged to $TMPDIR/build-$(PWD).log. +# For example, invoking metabuild in a directory named "foo" will log +# to /tmp/build-foo.log +# +# You can pass arguments to metabuild; if they start with '--', they're +# given to configure. Otherwise, they're passed to make. +# +# $ metabuild --enable-libfoo # passed to configure +# $ metabuild -j 1 # passed to make + +import os,sys,subprocess,tempfile +from multiprocessing import cpu_count +import glib,gio + +if 'INROOT_DIR' not in os.environ: + print "INROOT_DIR not set; run under inroot" + sys.exit(1) +root = os.environ['INROOT_DIR'] +if os.path.isdir('/lib64'): + libdir=os.path.join(root, 'lib64') +else: + libdir=os.path.join(root, 'lib') + +configargs = ['--prefix=' + root, '--libdir=' + libdir] +makeargs = ['make', '-j', '%d' % (cpu_count() * 2, )] +for arg in sys.argv[1:]: + if arg.startswith('--'): + configargs.append(arg) + else: + makeargs.append(arg) + +have_configure=(os.path.exists('configure.ac') or os.path.exists('configure.in')) +if have_configure and not os.path.exists('configure'): + if os.path.exists('autogen.sh'): + args = ['./autogen.sh'] + args.extend(configargs) + subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr) + else: + subprocess.check_call(['autoreconf', '-f', '-i'], stdout=sys.stdout, stderr=sys.stderr) + args = ['./configure'] + args.extend(configargs) + subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr) +prefix_matches=True +if have_configure and os.path.exists('config.log'): + previous_prefix = None + f = open('config.log') + for line in f: + if line.startswith('prefix=\''): + previous_prefix = line[8:-2] + break + f.close() + if previous_prefix != root: + print "Reruning configure due to prefix change (%r -> %r)" % (root, previous_prefix) + prefix_matches=False + +if have_configure and (not os.path.exists('Makefile') or not prefix_matches): + args = ['./configure'] + args.extend(configargs) + subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr) + +class Tail(object): + def __init__(self, filename, output): + self.filename = filename + self.output = output + self._gfile = gio.File(path=filename) + self._mon = self._gfile.monitor(gio.FILE_MONITOR_NONE) + self._fd = os.open(self.filename, os.O_RDONLY) + self._position = 0 + self._mon.connect('changed', self._on_changed) + self._do_read() + + def _do_read(self): + buf = os.read(self._fd, 8192) + while buf != '': + self._position += len(buf) + self.output.write(buf) + buf = os.read(self._fd, 8192) + + def _on_changed(self, mon, gfile, other, event): + self._do_read() + + def finish(self): + self._do_read() + +loop = glib.MainLoop() +build_condition = None + +tempdir = os.environ.get('TMPDIR', '/tmp') +logfile_path = os.path.join(tempdir, 'build-%s.log' % (os.path.basename(os.getcwd()), )) +try: + os.unlink(logfile_path) +except OSError, e: + pass +logfile_write_fd = os.open(logfile_path, os.O_WRONLY | os.O_CREAT | os.O_EXCL) +sys.stdout.write('metabuild: logging to %r\n' % (logfile_path, )) +sys.stdout.flush() +def child_setup(*args): + os.dup2(logfile_write_fd, 1) + os.dup2(logfile_write_fd, 2) +(make_pid, stdin_fd, stdout_fd, stderr_fd) = \ + glib.spawn_async(makeargs, + flags=(glib.SPAWN_DO_NOT_REAP_CHILD | glib.SPAWN_SEARCH_PATH), + child_setup=child_setup) +os.close(logfile_write_fd) +tail = Tail(logfile_path, sys.stdout) +def on_child(pid, condition): + global loop + global build_condition + build_condition = condition + loop.quit() +glib.child_watch_add(make_pid, on_child) +loop.run() +tail.finish() +print "metabuild: make exited with status %r, logfile=%r" % (build_condition, logfile_path) +sys.exit(0 if build_condition == 0 else 1) |