source: rtems-source-builder/source-builder/sb/defaults.py @ a1d0eea

4.104.114.9
Last change on this file since a1d0eea was a1d0eea, checked in by Chris Johns <chrisj@…>, on Nov 9, 2012 at 8:46:03 PM

Add flex. It is needed by gcc.

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