#!/usr/bin/python """ Copyright (c) 2005--2007 Jan Nieuwenhuizen Han-Wen Nienhuys This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ def argv0_relocation (): import os, sys bindir = os.path.dirname (sys.argv[0]) prefix = os.path.dirname (bindir) sys.path.insert (0, prefix) argv0_relocation () import sys # from gub import cross ## fixme: double use of gub name. from gub import build import gub.settings from gub import misc from gub import locker from gub import gup def get_cli_parser (): import optparse p = optparse.OptionParser () p.usage='''gub [OPTION]... [PACKAGE]...''' p.description='Grand Unified Builder.' p.add_option ('-B', '--branch', action='append', dest='branches', default=[], metavar='NAME=BRANCH', help='select branch') p.add_option ('-k', '--keep', action='store_true', dest='keep_build', default=None, help='leave build and src dir for inspection') p.add_option ('-p', '--platform', action='store', dest='platform', type='choice', default=None, help='select target platform', choices=gub.settings.platforms.keys ()) p.add_option ('--inspect', action='store', dest='inspect_key', default=None, help='Key of package to inspect') p.add_option ('--inspect-output', action='store', dest='inspect_output', default=None, help='Where to write result of inspection') p.add_option ('--offline', action='store_true', dest='offline', help='Do not attempt to download anything') p.add_option ('--online', action='store_false', dest='offline', help='Download as part of the build') p.add_option ('--stage', action='store', dest='stage', default=None, help='Force rebuild of stage') p.add_option ('--fresh', action='store_true', dest='fresh', default=False, help='Restart all builds') p.add_option ('--cross-distcc-host', action='append', dest='cross_distcc_hosts', default=[], help='Add another cross compiling distcc host') p.add_option ('--native-distcc-host', action='append', dest='native_distcc_hosts', default=[], help='Add another native distcc host') p.add_option ('-v', '--verbose', action='count', dest='verbose', default=0) p.add_option ('-q', '--quiet', action='count', dest='quiet', default=0) p.add_option ('--lilypond-versions', action='store', default='uploads/lilypond.versions', dest='lilypond_versions') p.add_option ('--force-package', action='store_true', default=False, dest='force_package', help='allow packaging of tainted compiles' ) p.add_option ('--build-source', action='store_true', default=False, dest='build_source', help='build source packages') p.add_option ('--lax-checksums', action='store_true', default=False, dest='lax_checksums', help="do not rebuild packages with failing checksums") p.add_option ('-l', '--skip-if-locked', default=False, dest="skip_if_locked", action="store_true", help="Return successfully if another build is already running") p.add_option ('-j', '--jobs', default="1", action='store', dest='cpu_count', help='set number of simultaneous jobs') return p #FIXME: move to BuildRunner? def inspect (settings, files): (names, specs) = gup.get_source_packages (settings, files) pm = gup.get_target_manager (settings) gup.add_packages_to_self.manager (pm, settings, specs) deps = filter (specs.has_key, names) for f in files: v = pm.package_dict (f)[settings.options.inspect_key] if settings.options.inspect_output: open (settings.options.inspect_output, 'w').write (v) else: print v #FIXME: move to BuildRunner? def build (settings, files): (names, specs) = gup.get_source_packages (settings, files) def get_all_deps (name): package = specs[name] deps = package.get_build_dependencies () if not settings.is_distro: deps = [gup.get_base_package_name (d) for d in deps] return deps # FIXME: why do we only use deps for download, not for build? deps = gup.topologically_sorted (files, {}, get_all_deps, None) settings.os_interface.info ('deps:' + `deps` + '\n') import os PATH = os.environ['PATH'] os.environ['PATH'] = settings.expand ('%(tools_prefix)s/bin:' + PATH) if settings.options.stage == 'download': # FIXME: urg. [only] For a real clean gub, with nothing in # downloads/, we cannot go into build process, and let stage # handle its own, as someone wants to create all spec # substitution dicts, and that needs certain source trees to # be already checked-out, eg ghostscript for i in deps: specs[i].download () sys.exit (0) # FIXME: hw, why is this? Doesn't this break if settings.options.stage: names = files try: manager = gup.get_target_manager (settings) ## Todo: have a readonly lock for tools platform except locker.LockedError: settings.os_interface.error ('another build in progress. Skipping.') if settings.options.skip_if_locked: sys.exit (0) raise from gub import buildrunner b = buildrunner.BuildRunner (manager, settings, specs) b.build_source_packages (names) def exceptional_build (settings, files): status = 1 try: build (settings, files) status = 0 except SystemExit, e: status = e.code pass except KeyboardInterrupt, e: pass except Exception, e: status = 1 pass # FIXME: print/barf if deferred_commands not empty? settings.os_interface.defer_execution (False) if status: if settings.options.verbose < settings.os_interface.level['output']: print >>sys.stderr,\ ('\n\nTail of ' + settings.os_interface.log_file_name + ':\n' + '\n'.join (settings.os_interface.read_tail ())) log_file = settings.os_interface.log_file_name settings.os_interface.error (misc.exception_string (e)) else: settings.os_interface.info ('done\n') log = settings.os_interface.log_file_name settings.os_interface.error ('build log written to: %(log)s\n' % locals ()) return status def urg_add_more_settings_for_gub (settings, options): settings.build_source = options.build_source settings.lilypond_versions = options.lilypond_versions settings.cpu_count = options.cpu_count settings.set_distcc_hosts (options) def main (): cli_parser = get_cli_parser () (options, files) = cli_parser.parse_args () options.verbose -= options.quiet settings = gub.settings.Settings (options) urg_add_more_settings_for_gub (settings, options) if options.inspect_key: inspect (settings, files) sys.exit (0) settings.os_interface.stage ('root: ' + settings.system_root + '\n') settings.os_interface.info ('platform: ' + settings.platform + '\n') if not files: settings.os_interface.error ('error: nothing to do\n') cli_parser.print_help () sys.exit (2) sys.exit (exceptional_build (settings, files)) if __name__ == '__main__': main ()