source: rtems-source-builder/tb/defaults.py @ bf13d27

4.104.114.95
Last change on this file since bf13d27 was bf13d27, checked in by Chris Johns <chrisj@…>, on Oct 29, 2012 at 11:37:12 PM

Initial import.

  • Property mode set to 100644
File size: 19.0 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                  'trace'    : '0',
194                  'dry-run'  : '0',
195                  'no-clean' : '0',
196                  'no-smp'   : '0',
197                  'rebuild'  : '0' }
198
199    _long_opts = { '--prefix'         : '_prefix',
200                   '--prefixbase'     : '_prefixbase',
201                   '--topdir'         : '_topdir',
202                   '--configdir'      : '_configdir',
203                   '--builddir'       : '_builddir',
204                   '--sourcedir'      : '_sourcedir',
205                   '--usrlibrpm'      : '_usrlibrpm', # XXX remove ?
206                   '--tmppath'        : '_tmppath',
207                   '--log'            : '_logfile',
208                   '--url'            : '_url_base',
209                   '--targetcflags'   : '_targetcflags',
210                   '--targetcxxflags' : '_targetcxxflags',
211                   '--libstdcxxflags' : '_libstdcxxflags' }
212
213    _long_true_opts = { '--trace'    : '_trace',
214                        '--dry-run'  : '_dry_run',
215                        '--warn-all' : '_warn_all',
216                        '--no-clean' : '_no_clean',
217                        '--no-smp'   : '_no_smp',
218                        '--rebuild'  : '_rebuild' }
219
220    _target_triplets = { '--host'   : '_host',
221                         '--build'  : '_build',
222                         '--target' : '_target' }
223
224    def _help(self):
225        print '%s: [options] [args]' % (self.command_name)
226        print 'Options and arguments:'
227        print '--trace                : Trace the execution (not current used)'
228        print '--dry-run              : Do everything but actually run the build'
229        print '--warn-all             : Generate warnings'
230        print '--no-clean             : Do not clean up the build tree'
231        print '--no-smp               : Run with 1 job and not as many as CPUs'
232        print '--rebuild              : Rebuild (not used)'
233        print '--host                 : Set the host triplet'
234        print '--build                : Set the build triplet'
235        print '--target               : Set the target triplet'
236        print '--prefix path          : Tools build prefix, ie where they are installed'
237        print '--prefixbase path      : '
238        print '--topdir path          : Top of the build tree, default is $PWD'
239        print '--configdir path       : Path to the configuration directory, default: ./config'
240        print '--builddir path        : Path to the build directory, default: ./build'
241        print '--sourcedir path       : Path to the source directory, default: ./source'
242        print '--tmppath path         : Path to the temp directory, default: ./tmp'
243        print '--log file             : Log file where all build out is written too'
244        print '--url url              : URL to look for source'
245        print '--targetcflags flags   : List of C flags for the target code'
246        print '--targetcxxflags flags : List of C++ flags for the target code'
247        print '--libstdcxxflags flags : List of C++ flags to build the target libstdc++ code'
248        print '--with-<label>         : Add the --with-<label> to the build'
249        print '--without-<label>      : Add the --without-<label> to the build'
250        raise error.exit()
251
252    def __init__(self, argv):
253        self.command_path = os.path.dirname(argv[0])
254        if len(self.command_path) == 0:
255            self.command_path = '.'
256        self.command_name = os.path.basename(argv[0])
257        self.args = argv[1:]
258        self.defaults = {}
259        for to in command_line._long_true_opts:
260            self.defaults[command_line._long_true_opts[to]] = '0'
261        self.defaults['_tbdir'] = self.command_path
262        self._process()
263
264    def __str__(self):
265        def _dict(dd):
266            s = ''
267            ddl = dd.keys()
268            ddl.sort()
269            for d in ddl:
270                s += '  ' + d + ': ' + str(dd[d]) + '\n'
271            return s
272
273        s = 'command: ' + self.command() + \
274            '\nargs: ' + str(self.args) + \
275            '\nopts:\n' + _dict(self.opts)
276
277        return s
278
279    def _process(self):
280
281        def _process_lopt(opt, arg, long_opts, args, values = False):
282            for lo in long_opts:
283                if values and opt.startswith(lo):
284                    equals = opt.find('=')
285                    if equals < 0:
286                        if arg == len(args) - 1:
287                            raise error.general('missing option value: ' + lo)
288                        arg += 1
289                        value = args[arg]
290                    else:
291                        value = opt[equals + 1:]
292                    return lo, long_opts[lo], value, arg
293                elif opt == lo:
294                    return lo, long_opts[lo], True, arg
295            return None, None, None, arg
296
297        self.opts = command_line._defaults
298        i = 0
299        while i < len(self.args):
300            a = self.args[i]
301            if a.startswith('-'):
302                if a.startswith('--'):
303                    if a.startswith('--warn-all'):
304                        self.opts['warn-all'] = True
305                    elif a == '--help':
306                        self._help()
307                    else:
308                        lo, macro, value, i = _process_lopt(a, i,
309                                                            command_line._long_true_opts,
310                                                            self.args)
311                        if lo:
312                            self.defaults[macro] = '1'
313                            self.opts[lo[2:]] = '1'
314                        else:
315                            lo, macro, value, i = _process_lopt(a, i,
316                                                                command_line._long_opts,
317                                                                self.args, True)
318                            if lo:
319                                self.defaults[macro] = value
320                                self.opts[lo[2:]] = value
321                            else:
322                                #
323                                # The target triplet is 'cpu-vendor-os'.
324                                #
325                                lo, macro, value, i = _process_lopt(a, i,
326                                                                    command_line._target_triplets,
327                                                                    self.args, True)
328                                if lo:
329                                    #
330                                    # This is a target triplet. Run it past config.sub to make
331                                    # make sure it is ok.
332                                    #
333                                    e = execute.capture_execution()
334                                    config_sub = os.path.join(self.command_path,
335                                                              basepath, 'config.sub')
336                                    exit_code, proc, output = e.shell(config_sub + ' ' + value)
337                                    if exit_code == 0:
338                                        value = output
339                                    self.defaults[macro] = value
340                                    self.opts[lo[2:]] = value
341                                    _arch = macro + '_cpu'
342                                    _vendor = macro + '_vendor'
343                                    _os = macro + '_os'
344                                    _arch_value = ''
345                                    _vendor_value = ''
346                                    _os_value = ''
347                                    dash = value.find('-')
348                                    if dash >= 0:
349                                        _arch_value = value[:dash]
350                                        value = value[dash + 1:]
351                                    dash = value.find('-')
352                                    if dash >= 0:
353                                        _vendor_value = value[:dash]
354                                        value = value[dash + 1:]
355                                    if len(value):
356                                        _os_value = value
357                                    self.defaults[_arch] = _arch_value
358                                    self.defaults[_vendor] = _vendor_value
359                                    self.defaults[_os] = _os_value
360                                if not lo:
361                                    raise error.general('invalid argument: ' + a)
362                else:
363                    if a == '-n':
364                        self.opts['dry-run'] = '1'
365                    elif a == '-q':
366                        self.opts['quiet'] = '1'
367                    elif a == '-?':
368                        self._help()
369            else:
370                self.opts['params'].append(a)
371            i += 1
372
373    def _post_process(self, _defaults):
374        if self.no_smp():
375            _defaults['_smp_mflags'] = _defaults['nil']
376        if _defaults['_host'] == _defaults['nil']:
377            raise error.general('host not set')
378        return _defaults
379
380    def expand(self, s, _defaults):
381        """Simple basic expander of config file macros."""
382        mf = re.compile(r'%{[^}]+}')
383        expanded = True
384        while expanded:
385            expanded = False
386            for m in mf.findall(s):
387                name = m[2:-1]
388                if name in _defaults:
389                    s = s.replace(m, _defaults[name])
390                    expanded = True
391                else:
392                    raise error.general('cannot process default macro: ' + m)
393        return s
394
395    def command(self):
396        return os.path.join(self.command_path, self.command_name)
397
398    def dry_run(self):
399        return self.opts['dry-run'] != '0'
400
401    def set_dry_run(self):
402        self.opts['dry-run'] = '1'
403
404    def quiet(self):
405        return self.opts['quiet'] != '0'
406
407    def trace(self):
408        return self.opts['trace'] != '0'
409
410    def warn_all(self):
411        return self.opts['warn-all'] != '0'
412
413    def no_clean(self):
414        return self.opts['no-clean'] != '0'
415
416    def no_smp(self):
417        return self.opts['no-smp'] != '0'
418
419    def rebuild(self):
420        return self.opts['rebuild'] != '0'
421
422    def params(self):
423        return self.opts['params']
424
425    def get_config_files(self, config):
426        if config.find('*') >= 0 or config.find('?'):
427            configdir = os.path.dirname(config)
428            configbase = os.path.basename(config)
429            if len(configbase) == 0:
430                configbase = '*'
431            if len(configdir) == 0:
432                configdir = self.expand(defaults['_configdir'], defaults)
433            if not os.path.isdir(configdir):
434                raise error.general('configdir is not a directory or does not exist: ' + configdir)
435            files = glob.glob(os.path.join(configdir, configbase))
436            configs = files
437        else:
438            configs = [config]
439        return configs
440
441    def config_files(self):
442        configs = []
443        for config in self.opts['params']:
444            configs.extend(self.get_config_files(config))
445        return configs
446
447    def logfiles(self):
448        if 'log' in self.opts:
449            return self.opts['log'].split(',')
450        return ['stdout']
451
452    def urls(self):
453        if 'url' in self.opts:
454            return self.opts['url'].split(',')
455        return None
456
457    def prefixbase(self):
458        if 'prefixbase' in self.opts:
459            return self.opts['prefixbase']
460        return None
461
462def load(args):
463    """
464    Copy the defaults, get the host specific values and merge them overriding
465    any matching defaults, then create an options object to handle the command
466    line merging in any command line overrides. Finally post process the
467    command line.
468    """
469    d = defaults
470    overrides = None
471    if os.name == 'nt':
472        import windows
473        overrides = windows.load()
474    else:
475        uname = os.uname()
476        try:
477            if uname[0] == 'Darwin':
478                import darwin
479                overrides = darwin.load()
480            elif uname[0] == 'FreeBSD':
481                import freebsd
482                overrides = freebsd.load()
483            elif uname[0] == 'Linux':
484                import linux
485                overrides = linux.load()
486        except:
487            pass
488    if overrides is None:
489        raise error.general('no hosts defaults found; please add')
490    for k in overrides:
491        d[k] = overrides[k]
492    o = command_line(args)
493    for k in o.defaults:
494        d[k] = o.defaults[k]
495    d = o._post_process(d)
496    return o, d
497
498if __name__ == '__main__':
499    import sys
500    try:
501        _opts, _defaults = load(args = sys.argv)
502        print _opts
503        pprint.pprint(_defaults)
504    except error.general, gerr:
505        print gerr
506        sys.exit(1)
507    except error.internal, ierr:
508        print ierr
509        sys.exit(1)
510    sys.exit(0)
Note: See TracBrowser for help on using the repository browser.