source: rtems-source-builder/tb/defaults.py @ 864360e

4.104.114.95
Last change on this file since 864360e was 864360e, checked in by Chris Johns <chris@…>, on 10/29/12 at 15:40:18

Add a force option.

  • Property mode set to 100644
File size: 19.3 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2010-2012 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
24import glob
25import pprint
26import re
27import os
28
29import error
30import execute
31
32basepath = 'tb'
33
34defaults = {
35# Nothing
36'nil':                 '',
37
38# Set to invalid values.
39'_host':          '',
40'_build':         '%{_host}',
41'_target':        '',
42
43# Paths
44'_host_platform': '%{_host_cpu}-%{_host_vendor}-%{_host_os}%{?_gnu}',
45'_build':         '%{_host}',
46'_arch':          '%{_host_arch}',
47'_tbdir':         '',
48'_topdir':        os.getcwd(),
49'_configdir':     '%{_topdir}/config:%{_tbdir}/config',
50'_tardir':        '%{_topdir}/tar',
51'_sourcedir':     '%{_topdir}/sources',
52'_builddir':      '%{_topdir}/build/%{name}-%{version}-%{release}',
53'_docdir':        '%{_defaultdocdir}',
54'_tmppath':       '%{_topdir}/build/tmp',
55'buildroot:':     '%{_tmppath}/%{name}-root-%(%{__id_u} -n)',
56
57# Defaults, override in platform specific modules.
58'___setup_shell':      '/bin/sh',
59'__aclocal':           'aclocal',
60'__ar':                'ar',
61'__arch_install_post': '%{nil}',
62'__as':                'as',
63'__autoconf':          'autoconf',
64'__autoheader':        'autoheader',
65'__automake':          'automake',
66'__awk':               'awk',
67'__bash':              '/bin/bash',
68'__bzip2':             '/usr/bin/bzip2',
69'__cat':               '/bin/cat',
70'__cc':                '/usr/bin/gcc',
71'__chgrp':             '/usr/bin/chgrp',
72'__chmod':             '/bin/chmod',
73'__chown':             '/usr/sbin/chown',
74'__cp':                '/bin/cp',
75'__cpio':              '/usr/bin/cpio',
76'__cpp':               '/usr/bin/gcc -E',
77'__cxx':               '/usr/bin/g++',
78'__grep':              '/usr/bin/grep',
79'__gzip':              '/usr/bin/gzip',
80'__id':                '/usr/bin/id',
81'__id_u':              '%{__id} -u',
82'__install':           '/usr/bin/install',
83'__install_info':      '/usr/bin/install-info',
84'__ld':                '/usr/bin/ld',
85'__ldconfig':          '/sbin/ldconfig',
86'__ln_s':              'ln -s',
87'__make':              'make',
88'__mkdir':             '/bin/mkdir',
89'__mkdir_p':           '/bin/mkdir -p',
90'__mv':                '/bin/mv',
91'__nm':                '/usr/bin/nm',
92'__objcopy':           '%{_bindir}/objcopy',
93'__objdump':           '%{_bindir}/objdump',
94'__patch':             '/usr/bin/patch',
95'__perl':              'perl',
96'__perl_provides':     '%{_usrlibrpm}/perl.prov',
97'__perl_requires':     '%{_usrlibrpm}/perl.req',
98'__ranlib':            'ranlib',
99'__remsh':             '%{__rsh}',
100'__rm':                '/bin/rm',
101'__rsh':               '/usr/bin/rsh',
102'__sed':               '/usr/bin/sed',
103'__setup_post':        '%{__chmod} -R a+rX,g-w,o-w .',
104'__sh':                '/bin/sh',
105'__tar':               '/usr/bin/tar',
106'__tar_extract':       '%{__tar} -xvvf',
107'__unzip':             '/usr/bin/unzip',
108'__xz':                '/usr/bin/xz',
109'_datadir':            '%{_prefix}/share',
110'_defaultdocdir':      '%{_prefix}/share/doc',
111'_exeext':             '',
112'_exec_prefix':        '%{_prefix}',
113'_lib':                'lib',
114'_libdir':             '%{_exec_prefix}/%{_lib}',
115'_libexecdir':         '%{_exec_prefix}/libexec',
116'_localedir':          '%{_datadir}/locale',
117'_localstatedir':      '%{_prefix}/var',
118'_prefix':             '%{_usr}',
119'_usr':                '/usr/local',
120'_usrsrc':             '%{_usr}/src',
121'_var':                '/usr/local/var',
122'_varrun':             '%{_var}/run',
123
124# Shell Build Settings.
125'___build_args': '-e',
126'___build_cmd':  '%{?_sudo:%{_sudo} }%{?_remsh:%{_remsh} %{_remhost} }%{?_remsudo:%{_remsudo} }%{?_remchroot:%{_remchroot} %{_remroot} }%{___build_shell} %{___build_args}',
127'___build_post': 'exit 0',
128
129# Prebuild set up script.
130'___build_pre': '''# ___build_pre in as set up in defaults.py
131# Directories
132TB_SOURCE_DIR="%{_sourcedir}"
133TB_BUILD_DIR="%{_builddir}"
134TB_OPT_FLAGS="%{optflags}"
135TB_ARCH="%{_arch}"
136TB_OS="%{_os}"
137export TB_SOURCE_DIR TB_BUILD_DIR TB_OPT_FLAGS TB_ARCH TB_OS
138# Documentation
139TB_DOC_DIR="%{_docdir}"
140export TB_DOC_DIR
141# Packages
142TB_PACKAGE_NAME="%{name}"
143TB_PACKAGE_VERSION="%{version}"
144TB_PACKAGE_RELEASE="%{release}"
145export TBPACKAGE_NAME TB_PACKAGE_VERSION TB_PACKAGE_RELEASE
146# Build root directory
147%{?buildroot:TB_BUILD_ROOT="%{buildroot}"}
148export TB_BUILD_ROOT
149# The compiler flags
150%{?_targetcflags:CFLAGS_FOR_TARGET="%{_targetcflags}"}
151%{?_targetcxxflags:CXXFLAGS_FOR_TARGET="%{_targetcxxflags}"}
152export CFLAGS_FOR_TARGET
153# Default environment set up.
154LANG=C
155export LANG
156unset DISPLAY || :
157umask 022
158cd "%{_builddir}"''',
159'___build_shell': '%{?_buildshell:%{_buildshell}}%{!?_buildshell:/bin/sh}',
160'___build_template': '''#!%{___build_shell}
161%{___build_pre}
162%{nil}''',
163
164# Configure command
165'configure': '''
166CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS ;
167CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS ;
168FFLAGS="${FFLAGS:-%optflags}" ; export FFLAGS ;
169./configure --build=%{_build} --host=%{_host} \
170      --target=%{_target_platform} \
171      --program-prefix=%{?_program_prefix} \
172      --prefix=%{_prefix} \
173      --exec-prefix=%{_exec_prefix} \
174      --bindir=%{_bindir} \
175      --sbindir=%{_sbindir} \
176      --sysconfdir=%{_sysconfdir} \
177      --datadir=%{_datadir} \
178      --includedir=%{_includedir} \
179      --libdir=%{_libdir} \
180      --libexecdir=%{_libexecdir} \
181      --localstatedir=%{_localstatedir} \
182      --sharedstatedir=%{_sharedstatedir} \
183      --mandir=%{_mandir} \
184      --infodir=%{_infodir}'''
185}
186
187class command_line:
188    """Process the command line in a common way for all Tool Builder commands."""
189
190    _defaults = { 'params'   : [],
191                  'warn-all' : '0',
192                  'quiet'    : '0',
193                  'force'    : '0',
194                  'trace'    : '0',
195                  'dry-run'  : '0',
196                  'no-clean' : '0',
197                  'no-smp'   : '0',
198                  'rebuild'  : '0' }
199
200    _long_opts = { '--prefix'         : '_prefix',
201                   '--prefixbase'     : '_prefixbase',
202                   '--topdir'         : '_topdir',
203                   '--configdir'      : '_configdir',
204                   '--builddir'       : '_builddir',
205                   '--sourcedir'      : '_sourcedir',
206                   '--usrlibrpm'      : '_usrlibrpm', # XXX remove ?
207                   '--tmppath'        : '_tmppath',
208                   '--log'            : '_logfile',
209                   '--url'            : '_url_base',
210                   '--targetcflags'   : '_targetcflags',
211                   '--targetcxxflags' : '_targetcxxflags',
212                   '--libstdcxxflags' : '_libstdcxxflags' }
213
214    _long_true_opts = { '--force'    : '_force',
215                        '--trace'    : '_trace',
216                        '--dry-run'  : '_dry_run',
217                        '--warn-all' : '_warn_all',
218                        '--no-clean' : '_no_clean',
219                        '--no-smp'   : '_no_smp',
220                        '--rebuild'  : '_rebuild' }
221
222    _target_triplets = { '--host'   : '_host',
223                         '--build'  : '_build',
224                         '--target' : '_target' }
225
226    def _help(self):
227        print '%s: [options] [args]' % (self.command_name)
228        print 'Options and arguments:'
229        print '--force                : Create directories that are not present'
230        print '--trace                : Trace the execution (not current used)'
231        print '--dry-run              : Do everything but actually run the build'
232        print '--warn-all             : Generate warnings'
233        print '--no-clean             : Do not clean up the build tree'
234        print '--no-smp               : Run with 1 job and not as many as CPUs'
235        print '--rebuild              : Rebuild (not used)'
236        print '--host                 : Set the host triplet'
237        print '--build                : Set the build triplet'
238        print '--target               : Set the target triplet'
239        print '--prefix path          : Tools build prefix, ie where they are installed'
240        print '--prefixbase path      : '
241        print '--topdir path          : Top of the build tree, default is $PWD'
242        print '--configdir path       : Path to the configuration directory, default: ./config'
243        print '--builddir path        : Path to the build directory, default: ./build'
244        print '--sourcedir path       : Path to the source directory, default: ./source'
245        print '--tmppath path         : Path to the temp directory, default: ./tmp'
246        print '--log file             : Log file where all build out is written too'
247        print '--url url              : URL to look for source'
248        print '--targetcflags flags   : List of C flags for the target code'
249        print '--targetcxxflags flags : List of C++ flags for the target code'
250        print '--libstdcxxflags flags : List of C++ flags to build the target libstdc++ code'
251        print '--with-<label>         : Add the --with-<label> to the build'
252        print '--without-<label>      : Add the --without-<label> to the build'
253        raise error.exit()
254
255    def __init__(self, argv):
256        self.command_path = os.path.dirname(argv[0])
257        if len(self.command_path) == 0:
258            self.command_path = '.'
259        self.command_name = os.path.basename(argv[0])
260        self.args = argv[1:]
261        self.defaults = {}
262        for to in command_line._long_true_opts:
263            self.defaults[command_line._long_true_opts[to]] = '0'
264        self.defaults['_tbdir'] = self.command_path
265        self._process()
266
267    def __str__(self):
268        def _dict(dd):
269            s = ''
270            ddl = dd.keys()
271            ddl.sort()
272            for d in ddl:
273                s += '  ' + d + ': ' + str(dd[d]) + '\n'
274            return s
275
276        s = 'command: ' + self.command() + \
277            '\nargs: ' + str(self.args) + \
278            '\nopts:\n' + _dict(self.opts)
279
280        return s
281
282    def _process(self):
283
284        def _process_lopt(opt, arg, long_opts, args, values = False):
285            for lo in long_opts:
286                if values and opt.startswith(lo):
287                    equals = opt.find('=')
288                    if equals < 0:
289                        if arg == len(args) - 1:
290                            raise error.general('missing option value: ' + lo)
291                        arg += 1
292                        value = args[arg]
293                    else:
294                        value = opt[equals + 1:]
295                    return lo, long_opts[lo], value, arg
296                elif opt == lo:
297                    return lo, long_opts[lo], True, arg
298            return None, None, None, arg
299
300        self.opts = command_line._defaults
301        i = 0
302        while i < len(self.args):
303            a = self.args[i]
304            if a.startswith('-'):
305                if a.startswith('--'):
306                    if a.startswith('--warn-all'):
307                        self.opts['warn-all'] = True
308                    elif a == '--help':
309                        self._help()
310                    else:
311                        lo, macro, value, i = _process_lopt(a, i,
312                                                            command_line._long_true_opts,
313                                                            self.args)
314                        if lo:
315                            self.defaults[macro] = '1'
316                            self.opts[lo[2:]] = '1'
317                        else:
318                            lo, macro, value, i = _process_lopt(a, i,
319                                                                command_line._long_opts,
320                                                                self.args, True)
321                            if lo:
322                                self.defaults[macro] = value
323                                self.opts[lo[2:]] = value
324                            else:
325                                #
326                                # The target triplet is 'cpu-vendor-os'.
327                                #
328                                lo, macro, value, i = _process_lopt(a, i,
329                                                                    command_line._target_triplets,
330                                                                    self.args, True)
331                                if lo:
332                                    #
333                                    # This is a target triplet. Run it past config.sub to make
334                                    # make sure it is ok.
335                                    #
336                                    e = execute.capture_execution()
337                                    config_sub = os.path.join(self.command_path,
338                                                              basepath, 'config.sub')
339                                    exit_code, proc, output = e.shell(config_sub + ' ' + value)
340                                    if exit_code == 0:
341                                        value = output
342                                    self.defaults[macro] = value
343                                    self.opts[lo[2:]] = value
344                                    _arch = macro + '_cpu'
345                                    _vendor = macro + '_vendor'
346                                    _os = macro + '_os'
347                                    _arch_value = ''
348                                    _vendor_value = ''
349                                    _os_value = ''
350                                    dash = value.find('-')
351                                    if dash >= 0:
352                                        _arch_value = value[:dash]
353                                        value = value[dash + 1:]
354                                    dash = value.find('-')
355                                    if dash >= 0:
356                                        _vendor_value = value[:dash]
357                                        value = value[dash + 1:]
358                                    if len(value):
359                                        _os_value = value
360                                    self.defaults[_arch] = _arch_value
361                                    self.defaults[_vendor] = _vendor_value
362                                    self.defaults[_os] = _os_value
363                                if not lo:
364                                    raise error.general('invalid argument: ' + a)
365                else:
366                    if a == '-f':
367                        self.opts['force'] = '1'
368                    elif a == '-n':
369                        self.opts['dry-run'] = '1'
370                    elif a == '-q':
371                        self.opts['quiet'] = '1'
372                    elif a == '-?':
373                        self._help()
374            else:
375                self.opts['params'].append(a)
376            i += 1
377
378    def _post_process(self, _defaults):
379        if self.no_smp():
380            _defaults['_smp_mflags'] = _defaults['nil']
381        if _defaults['_host'] == _defaults['nil']:
382            raise error.general('host not set')
383        return _defaults
384
385    def expand(self, s, _defaults):
386        """Simple basic expander of config file macros."""
387        mf = re.compile(r'%{[^}]+}')
388        expanded = True
389        while expanded:
390            expanded = False
391            for m in mf.findall(s):
392                name = m[2:-1]
393                if name in _defaults:
394                    s = s.replace(m, _defaults[name])
395                    expanded = True
396                else:
397                    raise error.general('cannot process default macro: ' + m)
398        return s
399
400    def command(self):
401        return os.path.join(self.command_path, self.command_name)
402
403    def force(self):
404        return self.opts['force'] != '0'
405
406    def dry_run(self):
407        return self.opts['dry-run'] != '0'
408
409    def set_dry_run(self):
410        self.opts['dry-run'] = '1'
411
412    def quiet(self):
413        return self.opts['quiet'] != '0'
414
415    def trace(self):
416        return self.opts['trace'] != '0'
417
418    def warn_all(self):
419        return self.opts['warn-all'] != '0'
420
421    def no_clean(self):
422        return self.opts['no-clean'] != '0'
423
424    def no_smp(self):
425        return self.opts['no-smp'] != '0'
426
427    def rebuild(self):
428        return self.opts['rebuild'] != '0'
429
430    def params(self):
431        return self.opts['params']
432
433    def get_config_files(self, config):
434        if config.find('*') >= 0 or config.find('?'):
435            configdir = os.path.dirname(config)
436            configbase = os.path.basename(config)
437            if len(configbase) == 0:
438                configbase = '*'
439            if len(configdir) == 0:
440                configdir = self.expand(defaults['_configdir'], defaults)
441            if not os.path.isdir(configdir):
442                raise error.general('configdir is not a directory or does not exist: ' + configdir)
443            files = glob.glob(os.path.join(configdir, configbase))
444            configs = files
445        else:
446            configs = [config]
447        return configs
448
449    def config_files(self):
450        configs = []
451        for config in self.opts['params']:
452            configs.extend(self.get_config_files(config))
453        return configs
454
455    def logfiles(self):
456        if 'log' in self.opts:
457            return self.opts['log'].split(',')
458        return ['stdout']
459
460    def urls(self):
461        if 'url' in self.opts:
462            return self.opts['url'].split(',')
463        return None
464
465    def prefixbase(self):
466        if 'prefixbase' in self.opts:
467            return self.opts['prefixbase']
468        return None
469
470def load(args):
471    """
472    Copy the defaults, get the host specific values and merge them overriding
473    any matching defaults, then create an options object to handle the command
474    line merging in any command line overrides. Finally post process the
475    command line.
476    """
477    d = defaults
478    overrides = None
479    if os.name == 'nt':
480        import windows
481        overrides = windows.load()
482    else:
483        uname = os.uname()
484        try:
485            if uname[0] == 'Darwin':
486                import darwin
487                overrides = darwin.load()
488            elif uname[0] == 'FreeBSD':
489                import freebsd
490                overrides = freebsd.load()
491            elif uname[0] == 'Linux':
492                import linux
493                overrides = linux.load()
494        except:
495            pass
496    if overrides is None:
497        raise error.general('no hosts defaults found; please add')
498    for k in overrides:
499        d[k] = overrides[k]
500    o = command_line(args)
501    for k in o.defaults:
502        d[k] = o.defaults[k]
503    d = o._post_process(d)
504    return o, d
505
506if __name__ == '__main__':
507    import sys
508    try:
509        _opts, _defaults = load(args = sys.argv)
510        print _opts
511        pprint.pprint(_defaults)
512    except error.general, gerr:
513        print gerr
514        sys.exit(1)
515    except error.internal, ierr:
516        print ierr
517        sys.exit(1)
518    sys.exit(0)
Note: See TracBrowser for help on using the repository browser.