Mercurial > gub
view bin/gub @ 6512:ccc20ae889ca default tip guix
mingw::guile-2.0.7 builds.
author | Jan Nieuwenhuizen <janneke@gnu.org> |
---|---|
date | Thu, 24 Mar 2016 08:03:39 +0100 |
parents | 72b46c22bf99 |
children |
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 pickle import optparse import os import time 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 gub_log from gub import misc from gub import repository from gub.syntax import printf from gub import loggedos 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 ''' misc.optparse_epilog (p, 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 ('-l', '--log', default='package', help='select log file granularity', choices=['build','package','platform']) 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 ('-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='versiondb/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 ('--skip-if-locked', default=False, action="store_true", help="Return successfully if another build is already running") 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): gub_log.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: printf ('dependencies[%(platform)s]: %(dep_str)s' % locals ()) sys.exit (0) dep_str.replace (misc.with_platform ('', platform), '') gub_log.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): gub_log.info ('Removing status file: %(status)s\n' % locals ()) os.unlink (status) 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: gub_log.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 False and huh_what_is_this_aboutoptions.dry_run: for name in sorted (b.checksums): printf (b.checksums[name]) sys.exit (0) configure.test_required (gub_log.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): log = buildrunner.logger if os.path.exists (log.log_file_name): sys.stderr.write ('\n') log.dump_tail (sys.stderr) sys.stderr.write ('\n') exception_verbosity = 'stage' 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. exception_verbosity = 'warning' log.write_log (misc.exception_string (), exception_verbosity) if buildrunner.target: logger.write_log ('*** Failed target: %s\n' % buildrunner.target, 'stage') # 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): # EXPENSIVE: #log_dir = settings.expand ('%(alllogdir)s') log_dir = settings.expand ('%(workdir)s/log') if not os.path.isdir (log_dir): os.makedirs (log_dir) log = os.path.join (log_dir, 'gub.log') if os.path.isfile (log): misc.rename_append_time (log) logger = gub_log.set_default_log (log, options.verbosity) buildrunner.logger = logger 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 environment_sanity (settings): environment_file = settings.alltargetdir + '/environment.pickle' environment = dict () if os.path.exists (environment_file): environment = dict (pickle.loads (open (environment_file, 'rb').read ())) # expand any ~ in the PATH os.environ['PATH'] = ":".join( map( lambda(x):os.path.expanduser(x), os.environ['PATH'].split(':'))) differ = [] for key in list (misc.uniq (sorted (environment.keys () + os.environ.keys ()))): if key == 'ABI': continue # we don't care about changes to this if environment.get (key, None) != os.environ.get (key, None): differ += [key] if list (environment.keys ()) and differ: printf ('*** environment changed\n') for key in differ: printf (' #new# %(key)s=' % locals () + os.environ.get (key, '')) if environment.get (key, None): printf (' %(key)s=' % locals () + environment[key]) else: printf (' unset %(key)s' % locals ()) sys.stderr.write ('\n*** press ^C in 10s or suffer a full rebuild') try: for i in range (10): time.sleep (1) sys.stderr.write ('.') except KeyboardInterrupt: sys.exit (1) except: pass open (environment_file, 'w').write (pickle.dumps (os.environ, protocol=2)) def main (): # stat restriction has become much more real using BASH # lots of specs do not compile atm if False and 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.build_source = options.build_source or options.platform == 'cygwin' if options.dry_run: loggedos.dry_run () gub_log.default_logger.threshold = options.verbosity gub_log.info ('files: %(files)s\n' % locals ()) gub_log.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: gub_log.error ('error: nothing to do\n') cli_parser.print_help () sys.exit (2) environment_sanity (settings) logged_build (settings, options, files) if __name__ == '__main__': main ()