Mercurial > gub
view bin/gub @ 5481:df03d0971b5d
Logging nits.
author | Jan Nieuwenhuizen <janneke@gnu.org> |
---|---|
date | Thu, 20 Aug 2009 14:35:30 +0200 |
parents | b3782861ff7e |
children | b685562acfe2 |
line wrap: on
line source
#! /usr/bin/env python """ Copyright (c) 2005--2008 Jan Nieuwenhuizen <janneke@gnu.org> Han-Wen Nienhuys <hanwen@xs4all.nl> 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) if not prefix: prefix = bindir + '/..' sys.path.insert (0, prefix) if sys.path[0] == 'gbin/..': sys.path[0] = '/' os.getcwd = lambda: '/' argv0_relocation () import optparse import os import sys # from gub import buildrunner from gub import configure from gub import cross from gub import gup from gub import locker from gub import logging from gub import misc from gub import repository from gub.syntax import printf import gub.settings # otherwise naming conflict with settings local vars. def get_cli_parser (): p = optparse.OptionParser () p.usage='''gub [OPTION]... [PACKAGE]...''' p.description='Grand Unified Builder.' examples = ''' Examples: gub lilypond gub darwin-x86::lilypond gub freebsd-64::ftp://ftp.gnu.org/pub/gnu/bison/bison-2.3.tar.gz gub mingw::openoffice ''' def format_examples (self): return examples if 'epilog' in p.__dict__: p.formatter.format_epilog = format_examples p.epilog = examples else: p.formatter.format_description = format_examples p.description = examples p.add_option ('-k', '--keep', action='store_true', dest='keep_build', default=None, help='Leave build and src dir for inspection') p.add_option ('-s', '--src-package', action='store_true', default=None, help='Also roll source packages') p.add_option ('-p', '--platform', action='store', type='choice', default=None, help='select target platform', choices=list (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', default=None, help='Where to write result of inspection') p.add_option ('--download-only', action='store_true', default=False, help='Exit after downloading.') p.add_option ('--offline', action='store_true', dest='offline', default=False, help='Do not attempt to download anything') p.add_option ('--online', action='store_false', dest='offline', default=False, help='Download as part of the build') def set_stage (option, opt_str, value, parser): if value == 'download': parser.values.download_only = True else: parser.values.stage = value p.add_option ('--stage', action='callback', callback=set_stage, dest='stage', type='string', 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='verbosity', 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, help='allow packaging of tainted compiles' ) p.add_option ('--build-source', action='store_true', default=False, help='build source packages') p.add_option ('--lax-checksums', action='store_true', default=False, help="do not rebuild packages with failing checksums") p.add_option ('-n', '--dry-run', action='store_true', default=False, help='Print action, do not run.') p.add_option ('--show-dependencies', action='store_true', default=False, help='Print dependencies.') p.add_option ('-x', '--no-dependencies', action='store_true', default=False, help='Ignore dependencies.') p.add_option ('-l', '--skip-if-locked', default=False, action="store_true", help="Return successfully if another build is already running") p.add_option ('-j', '--jobs', default="1", action='store', 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 = [d for d in names if d in specs] 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: printf (v) #FIXME: move to BuildRunner? def build (settings, options, files): logging.stage ('calculating dependencies\n') (names, specs) = gup.get_source_packages (settings, files) if options.no_dependencies: names = list () for spec in list (specs.values ()): if spec.name () in files or spec.platform_name () in files: if not names: specs = dict () names += [spec.platform_name ()] specs[spec.platform_name ()] = spec platform = settings.platform dep_str = ' '.join (names) if options.show_dependencies: logging.stage ('dependencies[%(platform)s]: %(dep_str)s\n' % locals ()) sys.exit (0) dep_str.replace (misc.with_platform ('', platform), '') logging.info ('dependencies[%(platform)s]: %(dep_str)s\n' % locals ()) if options.fresh: for spec in list (specs.values()): status = spec.get_stamp_file () if os.path.exists (status): logging.info ('Removing status file: %(status)s\n' % locals ()) os.unlink (status) # TODO: figure out how to patch src_package from # stages. Simpleminded solution does not work # and causes mingw runtime to run autogenmagic # TODO: patch out clean if --keep was specified. # TODO: move taint check in special stage, and patch out --force # was specified. # TODO: patch out checksum comparison if --lax-checksum was specified. if options.download_only: options.offline = False if not options.offline: for name in names: specs[name].download () if options.download_only: sys.exit (0) # FIXME: hw, why is this? Doesn't this break if options.stage: names = files try: manager = gup.DependencyManager (settings.system_root) ## Todo: have a readonly lock for tools platform except locker.LockedError: logging.error ('another build in progress. Skipping.') if options.skip_if_locked: sys.exit (0) raise b = buildrunner.BuildRunner (manager, settings, options, specs) if options.show_dependencies: sys.exit (0) b.calculate_checksums () if options.dry_run: for name in sorted (b.checksums): printf (b.checksums[name]) sys.exit (0) configure.test_required (logging.default_logger.error) b.build_source_packages (names) def exceptional_build (settings, options, files, logger): try: build (settings, options, files) except: t, v, b = sys.exc_info () if not (t == SystemExit and not v.code): sys.stderr.write ('\n') logger.dump_tail (sys.stderr) sys.stderr.write ('\n') if t == misc.SystemFailed: # Log the python exception, and only print cluttering # output when using -v; what we want to see is the # command error. logger.write_log (misc.exception_string (), 'warning') else: # We have a python exception, print that. logger.write_log (misc.exception_string (), 'error') if buildrunner.target: sys.stderr.write ('*** Failed target: %s\n' % buildrunner.target) # Using "raise" here has this exception's stack trace at # the tail of GUB's output. Most of the time, it's more # helpful [for users] to see the actual error, rather # than *where* it occured in our Python code. # The exception is still available in the build log, # and will be printed when using -v ## raise return 1 logger.write_log ('done\n', 'stage') return 0 def logged_build (settings, options, files): logger = logging.set_default_log (settings.expand ('%(logdir)s/build.log'), options.verbosity) logger.write_log ('root: %s\n' % settings.system_root, 'verbose') logger.write_log ('platform: %s\n' % settings.platform, 'verbose') sys.exit (exceptional_build (settings, options, files, logger)) def main (): if not 'stat' in misc.librestrict (): os.environ['LIBRESTRICT'] = 'open:stat' printf ('non-stat restriction is obsolete, use') printf ('export LIBRESTRICT=open:stat') # sys.exit (2) os.environ = gub.settings.clean_environment () # FIXME: pydb hack. TODO: make gub run not from srcdir bindir = os.path.dirname (sys.argv[0]) gubdir = os.path.dirname (bindir) if gubdir: os.chdir (gubdir) cli_parser = get_cli_parser () (options, files) = cli_parser.parse_args () options.verbosity -= options.quiet options.src_package = options.src_package or options.platform == 'cygwin' logging.default_logger.threshold = options.verbosity logging.info ('files: %(files)s\n' % locals ()) logging.info ('CLEANED env: ' + str (os.environ) + '\n') if not options.platform and len (files): options.platform, x = misc.split_platform (files[0]) settings = gub.settings.Settings (options.platform) if options.inspect_key: inspect (settings, files) sys.exit (0) if not files: logging.error ('error: nothing to do\n') cli_parser.print_help () sys.exit (2) logged_build (settings, options, files) if __name__ == '__main__': main ()