source: rtems-tools/specbuilder/specbuilder/defaults.py @ a2bc901

4.104.115
Last change on this file since a2bc901 was a2bc901, checked in by Chris Johns <chrisj@…>, on 12/05/11 at 11:32:44

Add FreeBSD support.

  • Property mode set to 100644
File size: 16.7 KB
Line 
1#
2# $Id$
3#
4# RTEMS Tools Project (http://www.rtems.org/)
5# Copyright 2010 Chris Johns (chrisj@rtems.org)
6# All rights reserved.
7#
8# This file is part of the RTEMS Tools package in 'rtems-tools'.
9#
10# RTEMS Tools is free software: you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation, either version 3 of the License, or
13# (at your option) any later version.
14#
15# RTEMS Tools is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with RTEMS Tools.  If not, see <http://www.gnu.org/licenses/>.
22#
23
24#
25# Determine the defaults and load the specific file.
26#
27
28import glob
29import pprint
30import re
31import os
32
33import error
34import execute
35
36defaults = {
37# Hack. Suspect a hidden platform or comand line thing
38'_with_noarch_subpackages': '1',
39
40# Paths
41'_host_platform': '%{_host_cpu}-%{_host_vendor}-%{_host_os}%{?_gnu}',
42'_build':         '%{_host}',
43'_arch':          '%{_host_arch}',
44'_topdir':        os.getcwd(),
45'_srcrpmdir':     '%{_topdir}/SRPMS',
46'_sourcedir':     '%{_topdir}/SOURCES',
47'_specdir':       '%{_topdir}/SPECS',
48'_rpmdir':        '%{_topdir}/TARS',
49'_builddir':      '%{_topdir}/BUILD/%{name}-%{version}-%{release}',
50'_docdir':        '%{_defaultdocdir}',
51'_usrlibrpm':     '%{_topdir}/RPMLIB',
52'_tmppath':       '%{_topdir}/TMP',
53'buildroot:':     '%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)',
54
55# Not sure.
56'_gnu':           '-gnu',
57
58# Cloned stuff from an RPM insall
59'___build_args': '-e',
60'___build_cmd':  '%{?_sudo:%{_sudo} }%{?_remsh:%{_remsh} %{_remhost} }%{?_remsudo:%{_remsudo} }%{?_remchroot:%{_remchroot} %{_remroot} }%{___build_shell} %{___build_args}',
61'___build_post': 'exit 0',
62'___build_pre': '''# ___build_pre in defaults.py
63RPM_SOURCE_DIR="%{_sourcedir}"
64RPM_BUILD_DIR="%{_builddir}"
65RPM_OPT_FLAGS="%{optflags}"
66RPM_ARCH="%{_arch}"
67RPM_OS="%{_os}"
68export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS
69RPM_DOC_DIR="%{_docdir}"
70export RPM_DOC_DIR
71RPM_PACKAGE_NAME="%{name}"
72RPM_PACKAGE_VERSION="%{version}"
73RPM_PACKAGE_RELEASE="%{release}"
74export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE
75%{?buildroot:RPM_BUILD_ROOT="%{buildroot}"}
76export RPM_BUILD_ROOT
77%{?_javaclasspath:CLASSPATH="%{_javaclasspath}"; export CLASSPATH}
78%{?_targetcflags:CFLAGS_FOR_TARGET="%{_targetcflags}"}
79%{?_targetcxxflags:CXXFLAGS_FOR_TARGET="%{_targetcxxflags}"}
80export CFLAGS_FOR_TARGET
81LANG=C
82export LANG
83unset DISPLAY || :
84umask 022
85cd "%{_builddir}"''',
86'___build_shell': '%{?_buildshell:%{_buildshell}}%{!?_buildshell:/bin/sh}',
87'___build_template': '''#!%{___build_shell}
88%{___build_pre}
89%{nil}''',
90'___setup_shell':      '/bin/sh',
91'__aclocal':           'aclocal',
92'__ar':                'ar',
93'__arch_install_post': '%{nil}',
94'__as':                'as',
95'__autoconf':          'autoconf',
96'__autoheader':        'autoheader',
97'__automake':          'automake',
98'__awk':               'awk',
99'__bash':              '/bin/bash',
100'__bzip2':             '/usr/bin/bzip2',
101'__cat':               '/bin/cat',
102'__cc':                '/usr/bin/gcc',
103'__check_files':       '%{_usrlibrpm}/check-files %{buildroot}',
104'__chgrp':             '/usr/bin/chgrp',
105'__chmod':             '/bin/chmod',
106'__chown':             '/usr/sbin/chown',
107'__cp':                '/bin/cp',
108'__cpio':              '/usr/bin/cpio',
109'__cpp':               '/usr/bin/gcc -E',
110'__cxx':               '/usr/bin/g++',
111'__grep':              '/usr/bin/grep',
112'__gzip':              '/usr/bin/gzip',
113'__id':                '/usr/bin/id',
114'__id_u':              '%{__id} -u',
115'__install':           '/usr/bin/install',
116'__install_info':      '/usr/bin/install-info',
117'__ld':                '/usr/bin/ld',
118'__ldconfig':          '/sbin/ldconfig',
119'__ln_s':              'ln -s',
120'__make':              '/usr/bin/make',
121'__mkdir':             '/bin/mkdir',
122'__mkdir_p':           '/bin/mkdir -p',
123'__mv':                '/bin/mv',
124'__nm':                '/usr/bin/nm',
125'__objcopy':           '%{_bindir}/objcopy',
126'__objdump':           '%{_bindir}/objdump',
127'__patch':             '/usr/bin/patch',
128'__perl':              'perl',
129'__perl_provides':     '%{_usrlibrpm}/perl.prov',
130'__perl_requires':     '%{_usrlibrpm}/perl.req',
131'__ranlib':            'ranlib',
132'__remsh':             '%{__rsh}',
133'__rm':                '/bin/rm',
134'__rsh':               '/usr/bin/rsh',
135'__sed':               '/usr/bin/sed',
136'__setup_post':        '%{__chmod} -R a+rX,g-w,o-w .',
137'__sh':                '/bin/sh',
138'__tar':               '/usr/bin/tar',
139'__tar_extract':       '%{__tar} -xvvf',
140'__unzip':             '/usr/bin/unzip',
141'__xz':                '/usr/bin/xz',
142'_datadir':            '%{_prefix}/share',
143'_defaultdocdir':      '%{_prefix}/share/doc',
144'_exeext':             '',
145'_exec_prefix':        '%{_prefix}',
146'_lib':                'lib',
147'_libdir':             '%{_exec_prefix}/%{_lib}',
148'_libexecdir':         '%{_exec_prefix}/libexec',
149'_localedir':          '%{_datadir}/locale',
150'_localstatedir':      '%{_prefix}/var',
151'_usr':                '/usr/local',
152'_usrsrc':             '%{_usr}/src',
153'_var':                '/usr/local/var',
154'_varrun':             '%{_var}/run',
155'configure': '''
156CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS ;
157CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS ;
158FFLAGS="${FFLAGS:-%optflags}" ; export FFLAGS ;
159./configure --build=%{_build} --host=%{_host} \
160      --target=%{_target_platform} \
161      --program-prefix=%{?_program_prefix} \
162      --prefix=%{_prefix} \
163      --exec-prefix=%{_exec_prefix} \
164      --bindir=%{_bindir} \
165      --sbindir=%{_sbindir} \
166      --sysconfdir=%{_sysconfdir} \
167      --datadir=%{_datadir} \
168      --includedir=%{_includedir} \
169      --libdir=%{_libdir} \
170      --libexecdir=%{_libexecdir} \
171      --localstatedir=%{_localstatedir} \
172      --sharedstatedir=%{_sharedstatedir} \
173      --mandir=%{_mandir} \
174      --infodir=%{_infodir}''',
175'nil':                 ''
176}
177
178class command_line:
179    """Process the command line in a common way across all SpecBuilder commands."""
180
181    _defaults = { 'params'   : [],
182                  'warn-all' : '0',
183                  'quiet'    : '0',
184                  'trace'    : '0',
185                  'dry-run'  : '0',
186                  'no-clean' : '0',
187                  'no-smp'   : '0',
188                  'rebuild'  : '0' }
189
190    _long_opts = { '--prefix'         : '_prefix',
191                   '--prefixbase'     : '_prefixbase',
192                   '--topdir'         : '_topdir',
193                   '--specdir'        : '_specdir',
194                   '--builddir'       : '_builddir',
195                   '--sourcedir'      : '_sourcedir',
196                   '--usrlibrpm'      : '_usrlibrpm',
197                   '--tmppath'        : '_tmppath',
198                   '--log'            : '_logfile',
199                   '--url'            : '_url_base',
200                   '--rtems'          : '_rtemssrc',
201                   '--targetcflags'   : '_targetcflags',
202                   '--targetcxxflags' : '_targetcxxflags',
203                   '--libstdcxxflags' : '_libstdcxxflags' }
204
205    _long_true_opts = { '--trace'    : '_trace',
206                        '--dry-run'  : '_dry_run',
207                        '--warn-all' : '_warn_all',
208                        '--no-clean' : '_no_clean',
209                        '--no-smp'   : '_no_smp',
210                        '--rebuild'  : '_rebuild' }
211
212    _target_triplets = { '--host'   : '_host',
213                         '--build'  : '_build',
214                         '--target' : '_target' }
215
216    def __init__(self, argv):
217        self.command_path = os.path.dirname(argv[0])
218        if len(self.command_path) == 0:
219            self.command_path = '.'
220        self.command_name = os.path.basename(argv[0])
221        self.args = argv[1:]
222        self.defaults = {}
223        for to in command_line._long_true_opts:
224            self.defaults[command_line._long_true_opts[to]] = '0'
225        self._process()
226
227    def __str__(self):
228        def _dict(dd):
229            s = ''
230            ddl = dd.keys()
231            ddl.sort()
232            for d in ddl:
233                s += '  ' + d + ': ' + str(dd[d]) + '\n'
234            return s
235
236        s = 'command: ' + self.command() + \
237            '\nargs: ' + str(self.args) + \
238            '\nopts:\n' + _dict(self.opts)
239
240        return s
241
242    def _process(self):
243
244        def _process_lopt(opt, arg, long_opts, args, values = False):
245            for lo in long_opts:
246                if values and opt.startswith(lo):
247                    equals = opt.find('=')
248                    if equals < 0:
249                        if arg == len(args) - 1:
250                            raise error.general('missing option value: ' + lo)
251                        arg += 1
252                        value = args[arg]
253                    else:
254                        value = opt[equals + 1:]
255                    return lo, long_opts[lo], value, arg
256                elif opt == lo:
257                    return lo, long_opts[lo], True, arg
258            return None, None, None, arg
259
260        self.opts = command_line._defaults
261        i = 0
262        while i < len(self.args):
263            a = self.args[i]
264            if a.startswith('-'):
265                if a.startswith('--'):
266                    if a.startswith('--warn-all'):
267                        self.opts['warn-all'] = True
268                    else:
269                        lo, macro, value, i = _process_lopt(a, i,
270                                                            command_line._long_true_opts,
271                                                            self.args)
272                        if lo:
273                            self.defaults[macro] = '1'
274                            self.opts[lo[2:]] = '1'
275                        else:
276                            lo, macro, value, i = _process_lopt(a, i,
277                                                                command_line._long_opts,
278                                                                self.args, True)
279                            if lo:
280                                self.defaults[macro] = value
281                                self.opts[lo[2:]] = value
282                            else:
283                                #
284                                # The target triplet is 'cpu-vendor-os'.
285                                #
286                                lo, macro, value, i = _process_lopt(a, i,
287                                                                    command_line._target_triplets,
288                                                                    self.args, True)
289                                if lo:
290                                    #
291                                    # This is a target triplet. Run it past config.sub to make
292                                    # make sure it is ok.
293                                    #
294                                    e = execute.capture_execution()
295                                    config_sub = os.path.join(self.command_path,
296                                                              'specbuilder', 'config.sub')
297                                    exit_code, proc, output = e.shell(config_sub + ' ' + value)
298                                    if exit_code == 0:
299                                        value = output
300                                    self.defaults[macro] = value
301                                    self.opts[lo[2:]] = value
302                                    _arch = macro + '_cpu'
303                                    _vendor = macro + '_vendor'
304                                    _os = macro + '_os'
305                                    _arch_value = ''
306                                    _vendor_value = ''
307                                    _os_value = ''
308                                    dash = value.find('-')
309                                    if dash >= 0:
310                                        _arch_value = value[:dash]
311                                        value = value[dash + 1:]
312                                    dash = value.find('-')
313                                    if dash >= 0:
314                                        _vendor_value = value[:dash]
315                                        value = value[dash + 1:]
316                                    if len(value):
317                                        _os_value = value
318                                    self.defaults[_arch] = _arch_value
319                                    self.defaults[_vendor] = _vendor_value
320                                    self.defaults[_os] = _os_value
321                                if not lo:
322                                    raise error.general('invalid argument: ' + a)
323                else:
324                    if a == '-n':
325                        self.opts['dry-run'] = '1'
326                    elif a == '-q':
327                        self.opts['quiet'] = '1'
328            else:
329                self.opts['params'].append(a)
330            i += 1
331
332    def _post_process(self, _defaults):
333        if self.no_smp():
334            _defaults['_smp_mflags'] = _defaults['nil']
335        return _defaults
336
337    def expand(self, s, _defaults):
338        """Simple basic expander of spec file macros."""
339        mf = re.compile(r'%{[^}]+}')
340        expanded = True
341        while expanded:
342            expanded = False
343            for m in mf.findall(s):
344                name = m[2:-1]
345                if name in _defaults:
346                    s = s.replace(m, _defaults[name])
347                    expanded = True
348                else:
349                    raise error.general('cannot process default macro: ' + m)
350        return s
351
352    def command(self):
353        return os.path.join(self.command_path, self.command_name)
354       
355    def dry_run(self):
356        return self.opts['dry-run'] != '0'
357
358    def quiet(self):
359        return self.opts['quiet'] != '0'
360
361    def trace(self):
362        return self.opts['trace'] != '0'
363
364    def warn_all(self):
365        return self.opts['warn-all'] != '0'
366
367    def no_clean(self):
368        return self.opts['no-clean'] != '0'
369
370    def no_smp(self):
371        return self.opts['no-smp'] != '0'
372
373    def rebuild(self):
374        return self.opts['rebuild'] != '0'
375
376    def params(self):
377        return self.opts['params']
378
379    def get_spec_files(self, spec):
380        if spec.find('*') >= 0 or spec.find('?'):
381            specdir = os.path.dirname(spec)
382            specbase = os.path.basename(spec)
383            if len(specbase) == 0:
384                specbase = '*'
385            if len(specdir) == 0:
386                specdir = self.expand(defaults['_specdir'], defaults)
387            if not os.path.isdir(specdir):
388                raise error.general('specdir is not a directory or does not exist: ' + specdir)
389            files = glob.glob(os.path.join(specdir, specbase))
390            specs = files
391        else:
392            specs = [spec]
393        return specs
394
395    def spec_files(self):
396        specs = []
397        for spec in self.opts['params']:
398            specs.extend(self.get_spec_files(spec))
399        return specs
400
401    def logfiles(self):
402        if 'log' in self.opts:
403            return self.opts['log'].split(',')
404        return ['stdout']
405
406    def urls(self):
407        if 'url' in self.opts:
408            return self.opts['url'].split(',')
409        return None
410
411    def prefixbase(self):
412        if 'prefixbase' in self.opts:
413            return self.opts['prefixbase']
414        return None
415
416def load(args):
417    """
418    Copy the defaults, get the host specific values and merge
419    them overriding any matching defaults, then create an options
420    object to handle the command line merging in any command line
421    overrides. Finally post process the command line.
422    """
423    d = defaults
424    overrides = None
425    if os.name == 'nt':
426        import windows
427        overrides = windows.load()
428    else:
429        uname = os.uname()
430        if uname[0] == 'Darwin':
431            import darwin
432            overrides = darwin.load()
433        elif uname[0] == 'FreeBSD':
434            import freebsd
435            overrides = freebsd.load()
436        elif uname[0] == 'Linux':
437            import linux
438            overrides = linux.load()
439    if overrides is None:
440        raise error.general('no hosts defaults found; please add')
441    for k in overrides:
442        d[k] = overrides[k]
443    import rtems
444    overrides = rtems.load()
445    if overrides is not None:
446        for k in overrides:
447            d[k] = overrides[k]
448    o = command_line(args)
449    for k in o.defaults:
450        d[k] = o.defaults[k]
451    d = o._post_process(d)
452    return o, d
453
454if __name__ == '__main__':
455    import sys
456    try:
457        _opts, _defaults = load(args = sys.argv)
458        print _opts
459        pprint.pprint(_defaults)
460    except error.general, gerr:
461        print gerr
462        sys.exit(1)
463    except error.internal, ierr:
464        print ierr
465        sys.exit(1)
466    sys.exit(0)
Note: See TracBrowser for help on using the repository browser.