#!/usr/bin/python # ostree-buildone-raw: Generic build system wrapper # Copyright 2010, 2011 Colin Walters # Licensed under the new-BSD license (http://www.opensource.org/licenses/bsd-license.php) # ostree-buildone-raw wraps systems that implement the GNOME build API: # http://people.gnome.org/~walters/docs/build-api.txt import os,sys,subprocess,tempfile,re from multiprocessing import cpu_count import select,time root = None prefix = '/usr' # libdir detection if os.path.isdir('/lib64'): libdir=os.path.join(prefix, 'lib64') else: libdir=os.path.join(prefix, 'lib') default_buildapi_jobs = ['-j', '%d' % (cpu_count() * 2, )] configargs = ['--prefix=' + prefix, '--libdir=' + libdir, '--sysconfdir=/etc', '--localstatedir=/var', '--bindir=' + os.path.join(prefix, 'bin'), '--sbindir=' + os.path.join(prefix, 'sbin'), '--datadir=' + os.path.join(prefix, 'share'), '--includedir=' + os.path.join(prefix, 'include'), '--libexecdir=' + os.path.join(prefix, 'libexec'), '--mandir=' + os.path.join(prefix, 'share', 'man'), '--infodir=' + os.path.join(prefix, 'share', 'info')] makeargs = ['make'] top_srcdir=os.getcwd() for arg in sys.argv[1:]: if arg.startswith('--'): configargs.append(arg) else: makeargs.append(arg) def log(msg): fullmsg = 'ostree-buildone: ' + msg + '\n' sys.stdout.write(fullmsg) sys.stdout.flush() def fatal(msg): log(msg) sys.exit(1) def run_sync(args, env=None): log("Running: %r" % (args, )) f = open('/dev/null', 'r') proc = subprocess.Popen(args, stdin=f, stdout=sys.stdout, stderr=sys.stderr, close_fds=True, env=env) f.close() returncode = proc.wait() log("pid %d exited with code %d" % (proc.pid, returncode)) if returncode != 0: sys.exit(1) class BuildSystemScanner(object): @classmethod def _find_file(cls, names): for name in names: if os.path.exists(name): return name return None @classmethod def get_configure_source_script(cls): return cls._find_file(('./configure.ac', './configure.in')) @classmethod def get_configure_script(cls): return cls._find_file(('./configure', )) @classmethod def get_bootstrap_script(cls): return cls._find_file(('./autogen.sh', )) @classmethod def get_silent_rules(cls): src = cls.get_configure_source_script() if not src: return False f = open(src) for line in f: if line.find('AM_SILENT_RULES') >= 0: f.close() return True f.close() return False def _search_file(filename, pattern): f = open(filename) for line in f: if line.startswith(pattern): f.close() return line f.close() return None def _find_buildapi_makevariable(name): var = '.%s:' % (name, ) line = None if os.path.exists('Makefile.in'): line = _search_file('Makefile.in', var) if not line and os.path.exists('Makefile'): line = _search_file('Makefile', var) return line is not None def phase_bootstrap(): have_configure = BuildSystemScanner.get_configure_script() have_configure_source = BuildSystemScanner.get_configure_source_script() if not (have_configure or have_configure_source): fatal("No configure or bootstrap script detected; unknown buildsystem") return need_v1 = BuildSystemScanner.get_silent_rules() if need_v1: log("Detected AM_SILENT_RULES, adding --disable-silent-rules to configure") configargs.append('--disable-silent-rules') if have_configure: phase_configure() else: bootstrap = BuildSystemScanner.get_bootstrap_script() if bootstrap: log("Detected bootstrap script: %s, using it" % (bootstrap, )) args = [bootstrap] args.extend(configargs) # Add NOCONFIGURE; GNOME style scripts use this env = dict(os.environ) env['NOCONFIGURE'] = '1' run_sync(args, env=env) else: log("No bootstrap script found; using generic autoreconf") run_sync(['autoreconf', '-f', '-i']) phase_configure() def phase_configure(): use_builddir = True doesnot_support_builddir = _find_buildapi_makevariable('buildapi-no-builddir') if doesnot_support_builddir: log("Found .buildapi-no-builddir; copying source tree to _build") shutil.rmtree('_build') os.mkdir('_build') shutil.copytree('.', '_build', symlinks=True, ignore=shutil.ignore_patterns('_build')) use_builddir = False builddir = '.' else: builddir = '_build' if not use_builddir: configdir = './' else: configdir = os.getcwd() builddir = builddir log("Using build directory %r" % (builddir, )) if not os.path.isdir(builddir): os.mkdir(builddir) os.chdir(builddir) configstatus = 'config.status' if not os.path.exists(configstatus): args = [os.path.join(configdir, 'configure')] args.extend(configargs) run_sync(args) else: log("Found %s, skipping configure" % (configstatus, )) phase_build() build_status = False def phase_build(): if not os.path.exists('Makefile'): log("No Makefile found") sys.exit(1) args = makeargs user_specified_jobs = False for arg in args: if arg == '-j': user_specified_jobs = True if not user_specified_jobs: notparallel = _find_buildapi_makevariable('NOTPARALLEL') if not notparallel: log("Didn't find NOTPARALLEL, using parallel make by default") args.extend(default_buildapi_jobs) run_sync(args) def phase_complete(): sys.exit(0) log("invocation arguments: %r" % (sys.argv, )) # Start off the process phase_bootstrap()