source: rtems-source-builder/source-builder/sb/setbuilder.py @ 8bedf50

5
Last change on this file since 8bedf50 was 8bedf50, checked in by Chris Johns <chrisj@…>, on 08/29/19 at 03:28:19

sb/setbuilder: Check is mail is valid.

  • Property mode set to 100644
File size: 30.7 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2010-2018 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# This code builds a package compiler tool suite given a tool set. A tool
22# set lists the various tools. These are specific tool configurations.
23#
24
25from __future__ import print_function
26
27import copy
28import datetime
29import glob
30import operator
31import os
32import sys
33import textwrap
34
35try:
36    import build
37    import check
38    import error
39    import log
40    import mailer
41    import options
42    import path
43    import reports
44    import shell
45    import sources
46    import version
47except KeyboardInterrupt:
48    print('abort: user terminated', file = sys.stderr)
49    sys.exit(1)
50except:
51    print('error: unknown application load error', file = sys.stderr)
52    sys.exit(1)
53
54def macro_expand(macros, _str):
55    cstr = None
56    while cstr != _str:
57        cstr = _str
58        _str = macros.expand(_str)
59        _str = shell.expand(macros, _str)
60    return _str
61
62class log_capture(object):
63    def __init__(self):
64        self.log = []
65        log.capture = self.capture
66
67    def __str__(self):
68        return os.linesep.join(self.log)
69
70    def capture(self, text):
71        self.log += [l for l in text.replace(chr(13), '').splitlines()]
72
73    def get(self):
74        return self.log
75
76    def clear(self):
77        self.log = []
78
79class buildset:
80    """Build a set builds a set of packages."""
81
82    def __init__(self, bset, _configs, opts, macros = None):
83        log.trace('_bset:   : %s: init' % (bset))
84        self.configs = _configs
85        self.opts = opts
86        if macros is None:
87            self.macros = copy.copy(opts.defaults)
88        else:
89            self.macros = copy.copy(macros)
90        log.trace('_bset:   : %s: macro defaults' % (bset))
91        log.trace(str(self.macros))
92        self.bset = bset
93        _target = macro_expand(self.macros, '%{_target}')
94        if len(_target):
95            pkg_prefix = _target
96        else:
97            pkg_prefix = macro_expand(self.macros, '%{_host}')
98        self.bset_pkg = '%s-%s-set' % (pkg_prefix, self.bset)
99        self.mail_header = ''
100        self.mail_report = ''
101        self.mail_report_0subject = ''
102        self.build_failure = None
103
104    def write_mail_header(self, text = '', prepend = False):
105        if type(text) is list:
106            text = os.linesep.join(text)
107        text = text.replace('\r', '').replace('\n', os.linesep)
108        if len(text) == 0 or text[-1] != os.linesep:
109            text += os.linesep
110        if prepend:
111            self.mail_header = text + self.mail_header
112        else:
113            self.mail_header += text
114
115    def get_mail_header(self):
116        return self.mail_header
117
118    def write_mail_report(self, text, prepend = False):
119        if type(text) is list:
120            text = os.linesep.join(text)
121        text = text.replace('\r', '').replace('\n', os.linesep)
122        if len(text) == 0 or text[-1] != os.linesep:
123            text += os.linesep
124        if prepend:
125            self.mail_report = text + self.mail_report
126        else:
127            self.mail_report += text
128
129    def get_mail_report(self):
130        return self.mail_report
131
132    def mail_single_report(self):
133        return self.macros.get('%{mail_single_report}') != 0
134
135    def mail_active(self, mail, nesting_count = 1):
136        return mail is not None and not (self.mail_single_report() and nesting_count > 1)
137
138    def mail_send(self, mail):
139        if True: #not self.opts.dry_run():
140            mail_subject = '%s on %s' % (self.bset, self.macros.expand('%{_host}'))
141            if mail['failure'] is not None:
142                mail_subject = 'FAILED %s (%s)' % (mail_subject, mail['failure'])
143            else:
144                mail_subject = 'PASSED %s' % (mail_subject)
145            mail_subject = 'Build %s: %s' % (reports.platform(mode = 'system'),
146                                             mail_subject)
147            body = mail['log']
148            body += (os.linesep * 2).join(mail['reports'])
149            mail['mail'].send(mail['to'], mail_subject, body)
150
151    def copy(self, src, dst):
152        log.output('copy: %s => %s' % (path.host(src), path.host(dst)))
153        if not self.opts.dry_run():
154            path.copy_tree(src, dst)
155
156    def report(self, _config, _build, opts, macros, format = None, mail = None):
157        if len(_build.main_package().name()) > 0 \
158           and not _build.macros.get('%{_disable_reporting}') \
159           and (not _build.opts.get_arg('--no-report') \
160                or _build.opts.get_arg('--mail')):
161            if format is None:
162                format = _build.opts.get_arg('--report-format')
163                if format is not None:
164                    if len(format) != 2:
165                        raise error.general('invalid report format option: %s' % \
166                                            ('='.join(format)))
167                    format = format[1]
168            if format is None:
169                format = 'text'
170            if format == 'text':
171                ext = '.txt'
172            elif format == 'asciidoc':
173                ext = '.txt'
174            elif format == 'html':
175                ext = '.html'
176            elif format == 'xml':
177                ext = '.xml'
178            elif format == 'ini':
179                ext = '.ini'
180            else:
181                raise error.general('invalid report format: %s' % (format))
182            buildroot = _build.config.abspath('%{buildroot}')
183            prefix = macro_expand(_build.macros, '%{_prefix}')
184            name = _build.main_package().name() + ext
185            log.notice('reporting: %s -> %s' % (_config, name))
186            if not _build.opts.get_arg('--no-report'):
187                outpath = path.host(path.join(buildroot, prefix, 'share', 'rtems', 'rsb'))
188                if not _build.opts.dry_run():
189                    outname = path.host(path.join(outpath, name))
190                else:
191                    outname = None
192                r = reports.report(format, self.configs,
193                                   copy.copy(opts), copy.copy(macros))
194                r.introduction(_build.config.file_name())
195                r.generate(_build.config.file_name())
196                r.epilogue(_build.config.file_name())
197                if not _build.opts.dry_run():
198                    _build.mkdir(outpath)
199                    r.write(outname)
200                del r
201            if mail:
202                r = reports.report('text', self.configs,
203                                   copy.copy(opts), copy.copy(macros))
204                r.introduction(_build.config.file_name())
205                r.generate(_build.config.file_name())
206                r.epilogue(_build.config.file_name())
207                self.write_mail_report(r.get_output())
208                del r
209
210    def root_copy(self, src, dst):
211        what = '%s -> %s' % \
212            (os.path.relpath(path.host(src)), os.path.relpath(path.host(dst)))
213        log.trace('_bset:   : %s: collecting: %s' % (self.bset, what))
214        self.copy(src, dst)
215
216    def install(self, mode, name, src, dst):
217        log.notice('%s: %s -> %s' % (mode, name, path.host(dst)))
218        self.copy(src, dst)
219
220    def install_mode(self):
221        return macro_expand(self.macros, '%{install_mode}')
222
223    def installing(self):
224        return self.install_mode() == 'installing'
225
226    def staging(self):
227        return not self.installing()
228
229    def canadian_cross(self, _build):
230        log.trace('_bset:   : Cxc for build machine: _build => _host')
231        macros_to_copy = [('%{_host}',        '%{_build}'),
232                          ('%{_host_alias}',  '%{_build_alias}'),
233                          ('%{_host_arch}',   '%{_build_arch}'),
234                          ('%{_host_cpu}',    '%{_build_cpu}'),
235                          ('%{_host_os}',     '%{_build_os}'),
236                          ('%{_host_vendor}', '%{_build_vendor}'),
237                          ('%{_tmproot}',     '%{_tmpcxcroot}'),
238                          ('%{buildroot}',    '%{buildcxcroot}'),
239                          ('%{_builddir}',    '%{_buildcxcdir}')]
240        cxc_macros = _build.copy_init_macros()
241        for m in macros_to_copy:
242            log.trace('_bset:   : Cxc: %s <= %s' % (m[0], cxc_macros[m[1]]))
243            cxc_macros[m[0]] = cxc_macros[m[1]]
244        _build.set_macros(cxc_macros)
245        _build.reload()
246        _build.make()
247        if not _build.macros.get('%{_disable_collecting}'):
248            self.root_copy(_build.config.expand('%{buildroot}'),
249                           _build.config.expand('%{_tmproot}'))
250        _build.set_macros(_build.copy_init_macros())
251        _build.reload()
252
253    def build_package(self, _config, _build):
254        if not _build.disabled():
255            if _build.canadian_cross():
256                self.canadian_cross(_build)
257            _build.make()
258            if not _build.macros.get('%{_disable_collecting}'):
259                self.root_copy(_build.config.expand('%{buildroot}'),
260                               _build.config.expand('%{_tmproot}'))
261
262    def bset_tar(self, _build):
263        tardir = _build.config.expand('%{_tardir}')
264        if (self.opts.get_arg('--bset-tar-file') or self.opts.canadian_cross()) \
265           and not _build.macros.get('%{_disable_packaging}'):
266            path.mkdir(tardir)
267            tar = path.join(tardir,
268                            _build.config.expand('%s.tar.bz2' % \
269                                                 (_build.main_package().name())))
270            log.notice('tarball: %s' % (os.path.relpath(path.host(tar))))
271            if not self.opts.dry_run():
272                tmproot = _build.config.expand('%{_tmproot}')
273                cmd = _build.config.expand('"cd ' + tmproot + \
274                                           ' && %{__tar} -cf - . | %{__bzip2} > ' + \
275                                           tar + '"')
276                _build.run(cmd, shell_opts = '-c', cwd = tmproot)
277
278    def parse(self, bset):
279
280        def _clean(line):
281            line = line[0:-1]
282            b = line.find('#')
283            if b >= 0:
284                line = line[1:b]
285            return line.strip()
286
287        bsetname = bset
288
289        if not path.exists(bsetname):
290            for cp in macro_expand(self.macros, '%{_configdir}').split(':'):
291                configdir = path.abspath(cp)
292                bsetname = path.join(configdir, bset)
293                if path.exists(bsetname):
294                    break
295                bsetname = None
296            if bsetname is None:
297                raise error.general('no build set file found: %s' % (bset))
298        try:
299            log.trace('_bset:   : %s: open: %s' % (self.bset, bsetname))
300            bset = open(path.host(bsetname), 'r')
301        except IOError as err:
302            raise error.general('error opening bset file: %s' % (bsetname))
303
304        configs = []
305
306        try:
307            lc = 0
308            for l in bset:
309                lc += 1
310                l = _clean(l)
311                if len(l) == 0:
312                    continue
313                log.trace('_bset:   : %s: %03d: %s' % (self.bset, lc, l))
314                ls = l.split()
315                if ls[0][-1] == ':' and ls[0][:-1] == 'package':
316                    self.bset_pkg = ls[1].strip()
317                    self.macros['package'] = self.bset_pkg
318                elif ls[0][0] == '%':
319                    def err(msg):
320                        raise error.general('%s:%d: %s' % (self.bset, lc, msg))
321                    if ls[0] == '%define':
322                        if len(ls) > 2:
323                            self.macros.define(ls[1].strip(),
324                                               ' '.join([f.strip() for f in ls[2:]]))
325                        else:
326                            self.macros.define(ls[1].strip())
327                    elif ls[0] == '%undefine':
328                        if len(ls) > 2:
329                            raise error.general('%s:%d: %undefine requires ' \
330                                                'just the name' % (self.bset, lc))
331                        self.macros.undefine(ls[1].strip())
332                    elif ls[0] == '%include':
333                        configs += self.parse(ls[1].strip())
334                    elif ls[0] in ['%patch', '%source']:
335                        sources.process(ls[0][1:], ls[1:], self.macros, err)
336                    elif ls[0] == '%hash':
337                        sources.hash(ls[1:], self.macros, err)
338                else:
339                    l = l.strip()
340                    c = build.find_config(l, self.configs)
341                    if c is None:
342                        raise error.general('%s:%d: cannot find file: %s' % (self.bset,
343                                                                             lc, l))
344                    configs += [c]
345        except:
346            bset.close()
347            raise
348
349        bset.close()
350
351        return configs
352
353    def load(self):
354
355        #
356        # If the build set file ends with .cfg the user has passed to the
357        # buildset builder a configuration so we just return it.
358        #
359        if self.bset.endswith('.cfg'):
360            configs = [self.bset]
361        else:
362            exbset = macro_expand(self.macros, self.bset)
363            self.macros['_bset'] = exbset
364            bset_tmp = build.short_name(exbset)
365            if bset_tmp.endswith('.bset'):
366                bset_tmp = bset_tmp[:-5]
367            self.macros['_bset_tmp'] = bset_tmp
368            root, ext = path.splitext(exbset)
369            if exbset.endswith('.bset'):
370                bset = exbset
371            else:
372                bset = '%s.bset' % (exbset)
373            configs = self.parse(bset)
374        return configs
375
376    def build(self, deps = None, nesting_count = 0, mail = None):
377
378        build_error = False
379
380        nesting_count += 1
381
382        if self.mail_active(mail, nesting_count):
383            mail['output'].clear()
384            mail['log'] = ''
385            mail['reports'] = []
386            mail['failure'] = None
387
388        log.trace('_bset: %2d: %s: make' % (nesting_count, self.bset))
389        log.notice('Build Set: %s' % (self.bset))
390
391        current_path = os.environ['PATH']
392
393        start = datetime.datetime.now()
394
395        mail_report = False
396        have_errors = False
397        interrupted = False
398
399        #
400        # If this is the outter most buildset it's files are installed. Nested
401        # build sets staged their installed file. The staged files are install
402        # when the outtter most build finishes.
403        #
404        if nesting_count != 1:
405            if self.installing():
406                self.macros['install_mode'] = 'staging'
407                #
408                # Prepend staging areas, bin directory tothe
409                # path. Lets the later package depend on the eailier
410                # ones.
411                #
412                pathprepend = ['%{stagingroot}/bin'] + \
413                    macro_expand(self.macros, '%{_pathprepend}').split(':')
414                pathprepend = [pp for pp in pathprepend if len(pp)]
415                if len(pathprepend) == 1:
416                    self.macros['_pathprepend'] = pathprepend[0]
417                else:
418                    self.macros['_pathprepend'] = ':'.join(pathprepend)
419
420        #
421        # Only the outter build set can have staging to install. Get the staging
422        # root via the config because it could require a valid config.
423        #
424        have_staging = False
425
426        try:
427            configs = self.load()
428
429            log.trace('_bset: %2d: %s: configs: %s'  % (nesting_count,
430                                                        self.bset, ', '.join(configs)))
431
432            sizes_valid = False
433            builds = []
434            for s in range(0, len(configs)):
435                b = None
436                try:
437                    #
438                    # Each section of the build set gets a separate set of
439                    # macros so we do not contaminate one configuration with
440                    # another.
441                    #
442                    opts = copy.copy(self.opts)
443                    macros = copy.copy(self.macros)
444                    if configs[s].endswith('.bset'):
445                        log.trace('_bset: %2d: %s %s' % (nesting_count,
446                                                         configs[s],
447                                                         '=' * (74 - len(configs[s]))))
448                        bs = buildset(configs[s], self.configs, opts, macros)
449                        bs.build(deps, nesting_count, mail)
450                        if self.installing():
451                            have_staging = True
452                        del bs
453                    elif configs[s].endswith('.cfg'):
454                        if mail:
455                            mail_report = True
456                        log.trace('_bset: %2d: %s %s' % (nesting_count,
457                                                         configs[s],
458                                                         '=' * (74 - len(configs[s]))))
459                        try:
460                            b = build.build(configs[s],
461                                            self.opts.get_arg('--pkg-tar-files'),
462                                            opts,
463                                            macros)
464                        except:
465                            build_error = True
466                            raise
467                        if b.macros.get('%{_disable_reporting}'):
468                            mail_report = False
469                        if deps is None:
470                            self.build_package(configs[s], b)
471                            self.report(configs[s], b,
472                                        copy.copy(self.opts),
473                                        copy.copy(self.macros),
474                                        mail = mail)
475                            # Always produce an XML report.
476                            self.report(configs[s], b,
477                                        copy.copy(self.opts),
478                                        copy.copy(self.macros),
479                                        format = 'xml',
480                                        mail = mail)
481                            if s == len(configs) - 1 and not have_errors:
482                                self.bset_tar(b)
483                        else:
484                            deps += b.config.includes()
485                        builds += [b]
486                        #
487                        # Dump post build macros.
488                        #
489                        log.trace('_bset:   : macros post-build')
490                        log.trace(str(b.macros))
491                    else:
492                        raise error.general('invalid config type: %s' % (configs[s]))
493                except error.general as gerr:
494                    have_errors = True
495                    if b is not None:
496                        if self.build_failure is None:
497                            self.build_failure = b.name()
498                        self.write_mail_header('')
499                        self.write_mail_header('= ' * 40)
500                        self.write_mail_header('Build FAILED: %s' % (b.name()))
501                        self.write_mail_header('- ' * 40)
502                        self.write_mail_header(str(log.default))
503                        self.write_mail_header('- ' * 40)
504                        if self.opts.keep_going():
505                            log.notice(str(gerr))
506                            if self.opts.always_clean():
507                                builds += [b]
508                        else:
509                            raise
510                    else:
511                        raise
512            #
513            # Installing or staging ...
514            #
515            log.trace('_bset: %2d: %s: deps:%r no-install:%r' % \
516                      (nesting_count, self.install_mode(),
517                       deps is None, self.opts.no_install()))
518            log.trace('_bset: %2d: %s: builds: %s' % \
519                      (nesting_count, self.install_mode(),
520                       ', '.join([b.name() for b in builds])))
521            if deps is None and not have_errors:
522                for b in builds:
523                    log.trace('_bset:   : %s: %r' % (self.install_mode(),
524                                                     b.installable()))
525                    if b.installable():
526                        prefix = b.config.expand('%{_prefix}')
527                        buildroot = path.join(b.config.expand('%{buildroot}'), prefix)
528                        if self.staging():
529                            prefix = b.config.expand('%{stagingroot}')
530                        self.install(self.install_mode(), b.name(), buildroot, prefix)
531
532            #
533            # Sizes ...
534            #
535            if len(builds) > 1:
536                size_build = 0
537                size_installed = 0
538                size_build_max = 0
539                for b in builds:
540                    s = b.get_build_size()
541                    size_build += s
542                    if s > size_build_max:
543                        size_build_max = s
544                    size_installed += b.get_installed_size()
545                size_sources = 0
546                for p in builds[0].config.expand('%{_sourcedir}').split(':'):
547                    size_sources += path.get_size(p)
548                size_patches = 0
549                for p in builds[0].config.expand('%{_patchdir}').split(':'):
550                    size_patches += path.get_size(p)
551                size_total = size_sources + size_patches + size_installed
552                build_max_size_human = build.humanize_number(size_build_max +
553                                                             size_installed, 'B')
554                build_total_size_human = build.humanize_number(size_total, 'B')
555                build_sources_size_human = build.humanize_number(size_sources, 'B')
556                build_patches_size_human = build.humanize_number(size_patches, 'B')
557                build_installed_size_human = build.humanize_number(size_installed, 'B')
558                build_size = 'usage: %s' % (build_max_size_human)
559                build_size += ' total: %s' % (build_total_size_human)
560                build_size += ' (sources: %s' % (build_sources_size_human)
561                build_size += ', patches: %s' % (build_patches_size_human)
562                build_size += ', installed %s)' % (build_installed_size_human)
563                sizes_valid = True
564            #
565            # Cleaning ...
566            #
567            if deps is None and \
568                    (not self.opts.no_clean() or self.opts.always_clean()):
569                for b in builds:
570                    if not b.disabled():
571                        log.notice('cleaning: %s' % (b.name()))
572                        b.cleanup()
573            #
574            # Log the build size message
575            #
576            if len(builds) > 1:
577                log.notice('Build Sizes: %s' % (build_size))
578            #
579            # Clear out the builds ...
580            #
581            for b in builds:
582                del b
583
584            #
585            # If builds have been staged install into the finaly prefix.
586            #
587            if have_staging and not self.opts.no_install() and not have_errors:
588                log.trace('_bset: %2d: install staging' % (nesting_count))
589                stagingroot = macro_expand(self.macros, '%{stagingroot}')
590                prefix = macro_expand(self.macros, '%{_prefix}')
591                self.install(self.install_mode(), self.bset, stagingroot, prefix)
592                staging_size = path.get_size(stagingroot)
593                if not self.opts.no_clean() or self.opts.always_clean():
594                    log.notice('clean staging: %s' % (self.bset))
595                    log.trace('removing: %s' % (stagingroot))
596                    if not self.opts.dry_run():
597                        if path.exists(stagingroot):
598                            path.removeall(stagingroot)
599                log.notice('Staging Size: %s' % (build.humanize_number(staging_size, 'B')))
600        except error.general as gerr:
601            if not build_error:
602                log.stderr(str(gerr))
603            raise
604        except KeyboardInterrupt:
605            interrupted = True
606            raise
607        except:
608            self.build_failure = 'RSB general failure'
609            interrupted = True
610            raise
611        finally:
612            end = datetime.datetime.now()
613            os.environ['PATH'] = current_path
614            build_time = str(end - start)
615            if self.mail_single_report() and nesting_count == 1:
616                mail_report = True
617            if interrupted or self.macros.defined('mail_disable'):
618                mail_report = False
619            if mail_report and mail is not None:
620                if self.installing():
621                    self.write_mail_header('Build Time: %s' % (build_time), True)
622                    self.write_mail_header('', True)
623                    self.write_mail_header(mail['header'], True)
624                    self.write_mail_header('')
625                    log.notice('Mailing report: %s' % (mail['to']))
626                    mail['log'] += self.get_mail_header()
627                    if sizes_valid:
628                        mail['log'] += 'Sizes' + os.linesep
629                        mail['log'] += '=====' + os.linesep + os.linesep
630                        mail['log'] += \
631                            'Maximum build usage: ' + build_max_size_human + os.linesep
632                        mail['log'] += \
633                            'Total size: ' + build_total_size_human + os.linesep
634                        mail['log'] += \
635                            'Installed : ' + build_installed_size_human + os.linesep
636                        mail['log'] += 'Sources: ' + build_sources_size_human + os.linesep
637                        mail['log'] += 'Patches: ' + build_patches_size_human + os.linesep
638                    mail['log'] += os.linesep
639                    mail['log'] += 'Output' + os.linesep
640                    mail['log'] += '======' + os.linesep + os.linesep
641                    mail['log'] += os.linesep.join(mail['output'].get())
642                    mail['log'] += os.linesep + os.linesep
643                    mail['log'] += 'Report' + os.linesep
644                    mail['log'] += '======' + os.linesep + os.linesep
645                mail['reports'] += [self.get_mail_report()]
646                if self.build_failure is not None:
647                    mail['failure'] = self.build_failure
648                if self.mail_active(mail, nesting_count):
649                    self.mail_send(mail)
650            log.notice('Build Set: Time %s' % (build_time))
651
652def list_bset_cfg_files(opts, configs):
653    if opts.get_arg('--list-configs') or opts.get_arg('--list-bsets'):
654        if opts.get_arg('--list-configs'):
655            ext = '.cfg'
656        else:
657            ext = '.bset'
658        for p in configs['paths']:
659            print('Examining: %s' % (os.path.relpath(p)))
660        for c in configs['files']:
661            if c.endswith(ext):
662                print('    %s' % (c))
663        return True
664    return False
665
666def run():
667    import sys
668    ec = 0
669    setbuilder_error = False
670    mail = None
671    try:
672        optargs = { '--list-configs':  'List available configurations',
673                    '--list-bsets':    'List available build sets',
674                    '--list-configs':  'List available configuration files.',
675                    '--list-deps':     'List the dependent files.',
676                    '--bset-tar-file': 'Create a build set tar file',
677                    '--pkg-tar-files': 'Create package tar files',
678                    '--no-report':     'Do not create a package report.',
679                    '--report-format': 'The report format (text, html, asciidoc).' }
680        mailer.append_options(optargs)
681        opts = options.load(sys.argv, optargs)
682        if opts.get_arg('--mail'):
683            mail = { 'mail'   : mailer.mail(opts),
684                     'output' : log_capture(),
685                     'log'    : '',
686                     'reports': [],
687                     'failure': None }
688            to_addr = opts.get_arg('--mail-to')
689            if to_addr is not None:
690                mail['to'] = to_addr[1]
691            else:
692                mail['to'] = macro_expand(opts.defaults, '%{_mail_tools_to}')
693            mail['from'] = mail['mail'].from_address()
694        log.notice('RTEMS Source Builder - Set Builder, %s' % (version.str()))
695        opts.log_info()
696        if not check.host_setup(opts):
697            raise error.general('host build environment is not set up correctly')
698        if mail:
699            mail['header'] = os.linesep.join(mail['output'].get()) + os.linesep
700            mail['header'] += os.linesep
701            mail['header'] += 'Host: '  + reports.platform('compact') + os.linesep
702            indent = '       '
703            for l in textwrap.wrap(reports.platform('extended'),
704                                   width = 80 - len(indent)):
705                mail['header'] += indent + l + os.linesep
706        configs = build.get_configs(opts)
707        if opts.get_arg('--list-deps'):
708            deps = []
709        else:
710            deps = None
711        if not list_bset_cfg_files(opts, configs):
712            prefix = macro_expand(opts.defaults, '%{_prefix}')
713            if opts.canadian_cross():
714                opts.disable_install()
715
716            if not opts.dry_run() and \
717               not opts.canadian_cross() and \
718               not opts.no_install() and \
719               not path.ispathwritable(prefix):
720                raise error.general('prefix is not writable: %s' % (path.host(prefix)))
721
722            for bset in opts.params():
723                setbuilder_error = True
724                b = buildset(bset, configs, opts)
725                b.build(deps, mail = mail)
726                b = None
727                setbuilder_error = False
728
729        if deps is not None:
730            c = 0
731            for d in sorted(set(deps)):
732                c += 1
733                print('dep[%d]: %s' % (c, d))
734    except error.general as gerr:
735        if not setbuilder_error:
736            log.stderr(str(gerr))
737        log.stderr('Build FAILED')
738        ec = 1
739    except error.internal as ierr:
740        if not setbuilder_error:
741            log.stderr(str(ierr))
742        log.stderr('Internal Build FAILED')
743        ec = 1
744    except error.exit as eerr:
745        pass
746    except KeyboardInterrupt:
747        log.notice('abort: user terminated')
748        ec = 1
749    except:
750        raise
751        log.notice('abort: unknown error')
752        ec = 1
753    sys.exit(ec)
754
755if __name__ == "__main__":
756    run()
Note: See TracBrowser for help on using the repository browser.