source: rtems-source-builder/source-builder/sb/options.py @ 650c6f9

Last change on this file since 650c6f9 was 650c6f9, checked in by Chris Johns <chrisj@…>, on 08/25/20 at 11:21:50

sb: Use shebang env python

Closes #4037

  • Property mode set to 100644
File size: 28.8 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2010-2016 Chris Johns (chrisj@rtems.org)
4# All rights reserved.
5#
6# This file is part of the RTEMS Tools package in 'rtems-tools'.
7#
8# Permission to use, copy, modify, and/or distribute this software for any
9# purpose with or without fee is hereby granted, provided that the above
10# copyright notice and this permission notice appear in all copies.
11#
12# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20#
21# Determine the defaults and load the specific file.
22#
23
24from __future__ import print_function
25
26import datetime
27import glob
28import pprint
29import re
30import os
31import string
32import sys
33
34from . import download
35from . import error
36from . import execute
37from . import git
38from . import log
39from . import macros
40from . import path
41from . import sources
42from . import version
43
44basepath = 'sb'
45
46#
47# Save the host and POSIX state.
48#
49host_windows = False
50host_posix = True
51
52class command_line:
53    """Process the command line in a common way for all Tool Builder commands."""
54
55    def __init__(self, argv, optargs, _defaults, command_path):
56        self._long_opts = {
57            # key                       macro                handler            param  defs   init
58            '--prefix'               : ('_prefix',           self._lo_path,     True,  None,  False),
59            '--topdir'               : ('_topdir',           self._lo_path,     True,  None,  False),
60            '--configdir'            : ('_configdir',        self._lo_path,     True,  None,  False),
61            '--builddir'             : ('_builddir',         self._lo_path,     True,  None,  False),
62            '--sourcedir'            : ('_sourcedir',        self._lo_path,     True,  None,  False),
63            '--patchdir'             : ('_patchdir',         self._lo_path,     True,  None,  False),
64            '--tmppath'              : ('_tmppath',          self._lo_path,     True,  None,  False),
65            '--jobs'                 : ('_jobs',             self._lo_jobs,     True,  'max', True),
66            '--log'                  : ('_logfile',          self._lo_string,   True,  None,  False),
67            '--url'                  : ('_url_base',         self._lo_string,   True,  None,  False),
68            '--no-download'          : ('_disable_download', self._lo_bool,     False, '0',   True),
69            '--macros'               : ('_macros',           self._lo_string,   True,  None,  False),
70            '--source-only-download' : ('_source_download',  self._lo_bool,     False, '0',   True),
71            '--targetcflags'         : ('_targetcflags',     self._lo_string,   True,  None,  False),
72            '--targetcxxflags'       : ('_targetcxxflags',   self._lo_string,   True,  None,  False),
73            '--libstdcxxflags'       : ('_libstdcxxflags',   self._lo_string,   True,  None,  False),
74            '--force'                : ('_force',            self._lo_bool,     False, '0',   True),
75            '--quiet'                : ('_quiet',            self._lo_bool,     False, '0',   True),
76            '--trace'                : ('_trace',            self._lo_bool,     False, '0',   True),
77            '--dry-run'              : ('_dry_run',          self._lo_bool,     False, '0',   True),
78            '--warn-all'             : ('_warn_all',         self._lo_bool,     False, '0',   True),
79            '--no-clean'             : ('_no_clean',         self._lo_bool,     False, '0',   True),
80            '--keep-going'           : ('_keep_going',       self._lo_bool,     False, '0',   True),
81            '--always-clean'         : ('_always_clean',     self._lo_bool,     False, '0',   True),
82            '--no-install'           : ('_no_install',       self._lo_bool,     False, '0',   True),
83            '--regression'           : ('_regression',       self._lo_bool,     False, '0',   True),
84            '--host'                 : ('_host',             self._lo_triplets, True,  None,  False),
85            '--build'                : ('_build',            self._lo_triplets, True,  None,  False),
86            '--target'               : ('_target',           self._lo_triplets, True,  None,  False),
87            '--rtems-tools'          : ('_rtems_tools',      self._lo_string,   True,  None,  False),
88            '--rtems-bsp'            : ('_rtems_bsp',        self._lo_string,   True,  None,  False),
89            '--rtems-version'        : ('_rtems_version',    self._lo_string,   True,  None,  False),
90            '--help'                 : (None,                self._lo_help,     False, None,  False)
91            }
92
93        self.command_path = command_path
94        self.command_name = path.basename(argv[0])
95        self.argv = argv
96        self.args = argv[1:]
97        self.optargs = optargs
98        self.defaults = _defaults
99        self.opts = { 'params' : [] }
100        for lo in self._long_opts:
101            self.opts[lo[2:]] = self._long_opts[lo][3]
102            if self._long_opts[lo][4]:
103                self.defaults[self._long_opts[lo][0]] = ('none',
104                                                         'none',
105                                                         self._long_opts[lo][3])
106
107    def __str__(self):
108        def _dict(dd):
109            s = ''
110            ddl = list(dd.keys())
111            ddl.sort()
112            for d in ddl:
113                s += '  ' + d + ': ' + str(dd[d]) + '\n'
114            return s
115
116        s = 'command: ' + self.command() + \
117            '\nargs: ' + str(self.args) + \
118            '\nopts:\n' + _dict(self.opts)
119
120        return s
121
122    def _lo_string(self, opt, macro, value):
123        if value is None:
124            raise error.general('option requires a value: %s' % (opt))
125        self.opts[opt[2:]] = value
126        self.defaults[macro] = value
127
128    def _lo_path(self, opt, macro, value):
129        if value is None:
130            raise error.general('option requires a path: %s' % (opt))
131        value = path.abspath(value)
132        self.opts[opt[2:]] = value
133        self.defaults[macro] = value
134
135    def _lo_jobs(self, opt, macro, value):
136        if value is None:
137            raise error.general('option requires a value: %s' % (opt))
138        ok = False
139        if value in ['max', 'none', 'half']:
140            ok = True
141        else:
142            try:
143                i = int(value)
144                ok = True
145            except:
146                pass
147            if not ok:
148                try:
149                    f = float(value)
150                    ok = True
151                except:
152                    pass
153        if not ok:
154            raise error.general('invalid jobs option: %s' % (value))
155        self.defaults[macro] = value
156        self.opts[opt[2:]] = value
157
158    def _lo_bool(self, opt, macro, value):
159        if value is not None:
160            raise error.general('option does not take a value: %s' % (opt))
161        self.opts[opt[2:]] = '1'
162        self.defaults[macro] = '1'
163
164    def _lo_triplets(self, opt, macro, value):
165        #
166        # This is a target triplet. Run it past config.sub to make make sure it
167        # is ok.  The target triplet is 'cpu-vendor-os'.
168        #
169        e = execute.capture_execution()
170        config_sub = path.join(self.command_path,
171                               basepath, 'config.sub')
172        exit_code, proc, output = e.shell(config_sub + ' ' + value)
173        if exit_code == 0:
174            value = output
175        self.defaults[macro] = ('triplet', 'none', value)
176        self.opts[opt[2:]] = value
177        _cpu = macro + '_cpu'
178        _arch = macro + '_arch'
179        _vendor = macro + '_vendor'
180        _os = macro + '_os'
181        _arch_value = ''
182        _vendor_value = ''
183        _os_value = ''
184        dash = value.find('-')
185        if dash >= 0:
186            _arch_value = value[:dash]
187            value = value[dash + 1:]
188        dash = value.find('-')
189        if dash >= 0:
190            _vendor_value = value[:dash]
191            value = value[dash + 1:]
192        if len(value):
193            _os_value = value
194        self.defaults[_cpu]    = _arch_value
195        self.defaults[_arch]   = _arch_value
196        self.defaults[_vendor] = _vendor_value
197        self.defaults[_os]     = _os_value
198
199    def _lo_help(self, opt, macro, value):
200        self.help()
201
202    def help(self):
203        print('%s: [options] [args]' % (self.command_name))
204        print('RTEMS Source Builder, an RTEMS Tools Project (c) 2012-2019 Chris Johns')
205        print('Options and arguments:')
206        print('--force                : Force the build to proceed')
207        print('--quiet                : Quiet output (not used)')
208        print('--trace                : Trace the execution')
209        print('--dry-run              : Do everything but actually run the build')
210        print('--warn-all             : Generate warnings')
211        print('--no-clean             : Do not clean up the build tree')
212        print('--always-clean         : Always clean the build tree, even with an error')
213        print('--keep-going           : Do not stop on an error.')
214        print('--regression           : Set --no-install, --keep-going and --always-clean')
215        print('--jobs                 : Run with specified number of jobs, default: num CPUs.')
216        print('--host                 : Set the host triplet')
217        print('--build                : Set the build triplet')
218        print('--target               : Set the target triplet')
219        print('--prefix path          : Tools build prefix, ie where they are installed')
220        print('--topdir path          : Top of the build tree, default is $PWD')
221        print('--configdir path       : Path to the configuration directory, default: ./config')
222        print('--builddir path        : Path to the build directory, default: ./build')
223        print('--sourcedir path       : Path to the source directory, default: ./source')
224        print('--patchdir path        : Path to the patches directory, default: ./patches')
225        print('--tmppath path         : Path to the temp directory, default: ./tmp')
226        print('--macros file[,[file]  : Macro format files to load after the defaults')
227        print('--log file             : Log file where all build out is written too')
228        print('--url url[,url]        : URL to look for source')
229        print('--no-download          : Disable the source downloader')
230        print('--no-install           : Do not install the packages to the prefix')
231        print('--targetcflags flags   : List of C flags for the target code')
232        print('--targetcxxflags flags : List of C++ flags for the target code')
233        print('--libstdcxxflags flags : List of C++ flags to build the target libstdc++ code')
234        print('--source-only-download : Only download the source')
235        print('--with-<label>         : Add the --with-<label> to the build')
236        print('--without-<label>      : Add the --without-<label> to the build')
237        print('--rtems-tools path     : Path to an install RTEMS tool set')
238        print('--rtems-bsp arc/bsp    : Standard RTEMS architecure and BSP specifier')
239        print('--rtems-version ver    : The RTEMS major/minor version string')
240        if self.optargs:
241            for a in self.optargs:
242                print('%-22s : %s' % (a, self.optargs[a]))
243        raise error.exit()
244
245    def process(self):
246        for a in self.args:
247            if a == '-?' or a == '--help':
248                self.help()
249        arg = 0
250        while arg < len(self.args):
251            a = self.args[arg]
252            if a.startswith('--'):
253                los = a.split('=', 1)
254                lo = los[0]
255                if lo in self._long_opts:
256                    long_opt = self._long_opts[lo]
257                    if len(los) == 1:
258                        if long_opt[2]:
259                            if arg == len(self.args) - 1:
260                                raise error.general('option requires a parameter: %s' % \
261                                                    (lo))
262                            arg += 1
263                            value = self.args[arg]
264                        else:
265                            value = None
266                    else:
267                        value = '='.join(los[1:])
268                    long_opt[1](lo, long_opt[0], value)
269                else:
270                    if a.startswith('--with'):
271                        if len(los) != 1:
272                            value = los[1]
273                        else:
274                            value = '1'
275                        self.defaults[los[0][2:].replace('-', '_').lower()] = \
276                            ('none', 'none', value)
277                    else:
278                        if lo not in self.optargs:
279                            raise error.general('unknown option: %s' % (lo))
280            else:
281                if a.startswith('-'):
282                    raise error.general('short options not supported; only "-?"')
283                self.opts['params'].append(a)
284            arg += 1
285
286    def pre_process(self):
287        arg = 0
288        while arg < len(self.args):
289            a = self.args[arg]
290            if a == '--source-only-download':
291                self.args += ['--dry-run',
292                              '--with-download',
293                              '--quiet',
294                              '--without-log',
295                              '--without-error-report']
296            if a == '--dry-run':
297                self.args += ['--without-error-report']
298            arg += 1
299
300    def post_process(self, logfile = True):
301        # Handle the log first.
302        logctrl = self.parse_args('--without-log')
303        if logctrl is None:
304            if logfile:
305                logfiles = self.logfiles()
306            else:
307                logfiles = None
308            log.default = log.log(streams = logfiles)
309        if self.trace():
310            log.tracing = True
311        if self.quiet():
312            log.quiet = True
313        # Must have a host
314        if self.defaults['_host'] == self.defaults['nil']:
315            raise error.general('--host not set')
316        # Must have a host
317        if self.defaults['_build'] == self.defaults['nil']:
318            raise error.general('--build not set')
319        # Default prefix
320        prefix = self.parse_args('--prefix')
321        if prefix is None:
322            value = path.join(self.defaults['_prefix'],
323                              'rtems',
324                              str(self.defaults['rtems_version']))
325            self.opts['prefix'] = value
326            self.defaults['_prefix'] = value
327        # Manage the regression option
328        if self.opts['regression'] != '0':
329            self.opts['no-install'] = '1'
330            self.defaults['_no_install'] = '1'
331            self.opts['keep-going'] = '1'
332            self.defaults['_keep_going'] = '1'
333            self.opts['always-clean'] = '1'
334            self.defaults['_always_clean'] = '1'
335        # Handle the jobs for make
336        if '_ncpus' not in self.defaults:
337            raise error.general('host number of CPUs not set')
338        ncpus = self.jobs(self.defaults['_ncpus'])
339        if ncpus > 1:
340            self.defaults['_smp_mflags'] = '-j %d' % (ncpus)
341        else:
342            self.defaults['_smp_mflags'] = self.defaults['nil']
343        # Load user macro files
344        um = self.user_macros()
345        if um:
346            checked = path.exists(um)
347            if False in checked:
348                raise error.general('macro file not found: %s' % \
349                                    (um[checked.index(False)]))
350            for m in um:
351                self.defaults.load(m)
352        # Check if the user has a private set of macros to load
353        if 'RSB_MACROS' in os.environ:
354            if path.exists(os.environ['RSB_MACROS']):
355                self.defaults.load(os.environ['RSB_MACROS'])
356        if 'HOME' in os.environ:
357            rsb_macros = path.join(os.environ['HOME'], '.rsb_macros')
358            if path.exists(rsb_macros):
359                self.defaults.load(rsb_macros)
360
361    def sb_released(self):
362        if version.released():
363            self.defaults['rsb_released'] = '1'
364        self.defaults['rsb_version'] = version.string()
365
366    def sb_git(self):
367        repo = git.repo(self.defaults.expand('%{_sbdir}'), self)
368        if repo.valid():
369            repo_valid = '1'
370            repo_head = repo.head()
371            repo_clean = not repo.dirty()
372            repo_remotes = '%{nil}'
373            remotes = repo.remotes()
374            if 'origin' in remotes:
375                repo_remotes = '%s/origin' % (remotes['origin']['url'])
376            repo_id = repo_head
377            if not repo_clean:
378                repo_id += '-modified'
379            repo_mail = repo.email()
380        else:
381            repo_valid = '0'
382            repo_head = '%{nil}'
383            repo_clean = '%{nil}'
384            repo_remotes = '%{nil}'
385            repo_id = 'no-repo'
386            repo_mail = None
387        self.defaults['_sbgit_valid'] = repo_valid
388        self.defaults['_sbgit_head']  = repo_head
389        self.defaults['_sbgit_clean'] = str(repo_clean)
390        self.defaults['_sbgit_remotes'] = str(repo_remotes)
391        self.defaults['_sbgit_id']    = repo_id
392        if repo_mail is not None:
393            self.defaults['_sbgit_mail'] = repo_mail
394
395    def command(self):
396        return path.join(self.command_path, self.command_name)
397
398    def force(self):
399        return self.opts['force'] != '0'
400
401    def dry_run(self):
402        return self.opts['dry-run'] != '0'
403
404    def set_dry_run(self):
405        self.opts['dry-run'] = '1'
406
407    def quiet(self):
408        return self.opts['quiet'] != '0'
409
410    def trace(self):
411        return self.opts['trace'] != '0'
412
413    def warn_all(self):
414        return self.opts['warn-all'] != '0'
415
416    def keep_going(self):
417        return self.opts['keep-going'] != '0'
418
419    def no_clean(self):
420        return self.opts['no-clean'] != '0'
421
422    def always_clean(self):
423        return self.opts['always-clean'] != '0'
424
425    def no_install(self):
426        return self.opts['no-install'] != '0'
427
428    def canadian_cross(self):
429        _host = self.defaults.expand('%{_host}')
430        _build = self.defaults.expand('%{_build}')
431        _target = self.defaults.expand('%{_target}')
432        #
433        # The removed fix has been put back. I suspect
434        # this was done as a result of another issue that
435        # has been fixed.
436        #
437        return len(_target) and len(_host) and len(_build) \
438            and _host != _build and _host != _target
439
440    def user_macros(self):
441        #
442        # Return something even if it does not exist.
443        #
444        if self.opts['macros'] is None:
445            return None
446        um = []
447        configs = self.defaults.expand('%{_configdir}').split(':')
448        for m in self.opts['macros'].split(','):
449            if path.exists(m):
450                um += [m]
451            else:
452                # Get the expanded config macros then check them.
453                cm = path.expand(m, configs)
454                ccm = path.exists(cm)
455                if True in ccm:
456                    # Pick the first found
457                    um += [cm[ccm.index(True)]]
458                else:
459                    um += [m]
460        return um if len(um) else None
461
462    def jobs(self, cpus):
463        cpus = int(cpus)
464        if self.opts['jobs'] == 'none':
465            cpus = 0
466        elif self.opts['jobs'] == 'max':
467            pass
468        elif self.opts['jobs'] == 'half':
469            cpus = cpus / 2
470        else:
471            ok = False
472            try:
473                i = int(self.opts['jobs'])
474                cpus = i
475                ok = True
476            except:
477                pass
478            if not ok:
479                try:
480                    f = float(self.opts['jobs'])
481                    cpus = f * cpus
482                    ok = True
483                except:
484                    pass
485                if not ok:
486                    raise error.internal('bad jobs option: %s' % (self.opts['jobs']))
487        if cpus <= 0:
488            cpu = 1
489        return cpus
490
491    def params(self):
492        return self.opts['params']
493
494    def parse_args(self, arg, error = True, extra = True):
495        for a in range(0, len(self.args)):
496            if self.args[a].startswith(arg):
497                lhs = None
498                rhs = None
499                if '=' in self.args[a]:
500                    eqs = self.args[a].split('=', 1)
501                    lhs = eqs[0]
502                    if len(eqs) > 2:
503                        rhs = '='.join(eqs[1:])
504                    else:
505                        rhs = eqs[1]
506                elif extra:
507                    lhs = self.args[a]
508                    a += 1
509                    if a < len(self.args):
510                        rhs = self.args[a]
511                return [lhs, rhs]
512            a += 1
513        return None
514
515    def get_arg(self, arg):
516        if self.optargs is None or arg not in self.optargs:
517            return None
518        return self.parse_args(arg)
519
520    def with_arg(self, label, default = 'not-found'):
521        # the default if there is no option for without.
522        result = default
523        for pre in ['with', 'without']:
524            arg_str = '--%s-%s' % (pre, label)
525            arg_label = '%s_%s' % (pre, label)
526            arg = self.parse_args(arg_str, error = False, extra = False)
527            if arg is not None:
528                if arg[1] is  None:
529                    result = 'yes'
530                else:
531                    result = arg[1]
532                break
533        return [arg_label, result]
534
535    def get_config_files(self, config):
536        #
537        # Convert to shell paths and return shell paths.
538        #
539        # @fixme should this use a passed in set of defaults and not
540        #        not the initial set of values ?
541        #
542        config = path.shell(config)
543        if '*' in config or '?' in config:
544            print(config)
545            configdir = path.dirname(config)
546            configbase = path.basename(config)
547            if len(configbase) == 0:
548                configbase = '*'
549            if not configbase.endswith('.cfg'):
550                configbase = configbase + '.cfg'
551            if len(configdir) == 0:
552                configdir = self.macros.expand(self.defaults['_configdir'])
553            configs = []
554            for cp in configdir.split(':'):
555                hostconfigdir = path.host(cp)
556                for f in glob.glob(os.path.join(hostconfigdir, configbase)):
557                    configs += path.shell(f)
558        else:
559            configs = [config]
560        return configs
561
562    def config_files(self):
563        configs = []
564        for config in self.opts['params']:
565            configs.extend(self.get_config_files(config))
566        return configs
567
568    def logfiles(self):
569        if 'log' in self.opts and self.opts['log'] is not None:
570            return self.opts['log'].split(',')
571        return ['rsb-log-%s.txt' % (datetime.datetime.now().strftime('%Y%m%d-%H%M%S'))]
572
573    def urls(self):
574        if self.opts['url'] is not None:
575            return self.opts['url'].split(',')
576        return None
577
578    def download_disabled(self):
579        return self.opts['no-download'] != '0'
580
581    def disable_install(self):
582        self.opts['no-install'] = '1'
583
584    def info(self):
585        s = ' Command Line: %s%s' % (' '.join(self.argv), os.linesep)
586        s += ' Python: %s' % (sys.version.replace('\n', ''))
587        return s
588
589    def log_info(self):
590        log.output(self.info())
591
592    def rtems_options(self):
593        # Check for RTEMS specific helper options.
594        rtems_tools = self.parse_args('--rtems-tools')
595        if rtems_tools is not None:
596            if self.get_arg('--with-tools') is not None:
597                raise error.general('--rtems-tools and --with-tools cannot be used together')
598            self.args.append('--with-tools=%s' % (rtems_tools[1]))
599        rtems_version = self.parse_args('--rtems-version')
600        if rtems_version is None:
601            rtems_version = str(version.version())
602        else:
603            rtems_version = rtems_version[1]
604        self.defaults['rtems_version'] = rtems_version
605        rtems_arch_bsp = self.parse_args('--rtems-bsp')
606        if rtems_arch_bsp is not None:
607            if self.get_arg('--target') is not None:
608                raise error.general('--rtems-bsp and --target cannot be used together')
609            ab = rtems_arch_bsp[1].split('/')
610            if len(ab) != 2:
611                raise error.general('invalid --rtems-bsp option')
612            self.args.append('--target=%s-rtems%s' % (ab[0], rtems_version))
613            self.args.append('--with-rtems-bsp=%s' % (ab[1]))
614
615def load(args, optargs = None, defaults = '%{_sbdir}/defaults.mc', logfile = True):
616    """
617    Copy the defaults, get the host specific values and merge them overriding
618    any matching defaults, then create an options object to handle the command
619    line merging in any command line overrides. Finally post process the
620    command line.
621    """
622
623    global host_windows
624    global host_posix
625
626    #
627    # The path to this command.
628    #
629    command_path = path.dirname(path.abspath(args[0]))
630    if len(command_path) == 0:
631        command_path = '.'
632
633    #
634    # The command line contains the base defaults object all build objects copy
635    # and modify by loading a configuration.
636    #
637    o = command_line(args,
638                     optargs,
639                     macros.macros(name = defaults,
640                                   sbdir = command_path),
641                     command_path)
642
643    overrides = None
644    if os.name == 'nt':
645        try:
646            from . import windows
647            overrides = windows.load()
648            host_windows = True
649            host_posix = False
650        except:
651            raise error.general('failed to load Windows host support')
652    elif os.name == 'posix':
653        uname = os.uname()
654        try:
655            if uname[0].startswith('MINGW64_NT'):
656                from . import windows
657                overrides = windows.load()
658                host_windows = True
659            elif uname[0].startswith('CYGWIN_NT'):
660                from . import windows
661                overrides = windows.load()
662            elif uname[0] == 'Darwin':
663                from . import darwin
664                overrides = darwin.load()
665            elif uname[0] == 'FreeBSD':
666                from . import freebsd
667                overrides = freebsd.load()
668            elif uname[0] == 'NetBSD':
669                from . import netbsd
670                overrides = netbsd.load()
671            elif uname[0] == 'Linux':
672                from . import linux
673                overrides = linux.load()
674            elif uname[0] == 'SunOS':
675                from . import solaris
676                overrides = solaris.load()
677        except error.general as ge:
678            raise error.general('failed to load %s host support: %s' % (uname[0], ge))
679        except:
680            raise error.general('failed to load %s host support' % (uname[0]))
681    else:
682        raise error.general('unsupported host type; please add')
683    if overrides is None:
684        raise error.general('no hosts defaults found; please add')
685    for k in overrides:
686        o.defaults[k] = overrides[k]
687
688    o.sb_released()
689    o.sb_git()
690    o.rtems_options()
691    o.pre_process()
692    o.process()
693    o.post_process(logfile)
694
695    #
696    # Load the release settings
697    #
698    def setting_error(msg):
699        raise error.general(msg)
700    hashes = version.load_release_settings('hashes')
701    for hash in hashes:
702        hs = hash[1].split()
703        if len(hs) != 2:
704            raise error.general('invalid release hash in VERSION')
705        sources.hash((hs[0], hash[0], hs[1]), o.defaults, setting_error)
706    release_path = version.load_release_setting('version', 'release_path',
707                                                raw = True)
708    if release_path is not None:
709        try:
710            release_path = ','.join([rp.strip() for rp in release_path.split(',')])
711        except:
712            raise error.general('invalid release path in VERSION')
713        download.set_release_path(release_path, o.defaults)
714    return o
715
716def run(args):
717    try:
718        dpath = path.dirname(args[0])
719        _opts = load(args = args,
720                     defaults = path.join(dpath, 'defaults.mc'))
721        log.notice('RTEMS Source Builder - Defaults, %s' % (version.string()))
722        _opts.log_info()
723        log.notice('Options:')
724        log.notice(str(_opts))
725        log.notice('Defaults:')
726        log.notice(str(_opts.defaults))
727        log.notice('with-opt1: %r' % (_opts.with_arg('opt1')))
728        log.notice('without-opt2: %r' % (_opts.with_arg('opt2')))
729    except error.general as gerr:
730        print(gerr)
731        sys.exit(1)
732    except error.internal as ierr:
733        print(ierr)
734        sys.exit(1)
735    except error.exit as eerr:
736        pass
737    except KeyboardInterrupt:
738        _notice(opts, 'abort: user terminated')
739        sys.exit(1)
740    sys.exit(0)
741
742if __name__ == '__main__':
743    run(sys.argv)
Note: See TracBrowser for help on using the repository browser.