summaryrefslogtreecommitdiffstats
path: root/bin/metabuild
diff options
context:
space:
mode:
Diffstat (limited to 'bin/metabuild')
-rwxr-xr-xbin/metabuild133
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)