source: rtems_waf/rtems.py @ 1b89636

Last change on this file since 1b89636 was 1b89636, checked in by Sebastian Huber <sebastian.huber@…>, on 10/18/18 at 07:36:17

Avoid default RTEMS application configuration

Use a test body with a proper RTEMS application configuration to avoid a
dependency on the default configuration. Do not include
<rtems/score/cpuopts.h> directly since this header file is an
implementation detail.

Update #3551.

  • Property mode set to 100644
File size: 29.7 KB
Line 
1
2# Copyright 2012-2016 Chris Johns (chrisj@rtems.org)
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are met:
6
7# 1. Redistributions of source code must retain the above copyright notice, this
8# list of conditions and the following disclaimer.
9
10# 2. Redistributions in binary form must reproduce the above copyright notice,
11# this list of conditions and the following disclaimer in the documentation
12# and/or other materials provided with the distribution.
13
14# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25from __future__ import print_function
26
27#
28# RTEMS support for applications.
29#
30
31import copy
32import os
33import os.path
34from . import pkgconfig
35import re
36import subprocess
37import sys
38
39rtems_default_version = None
40rtems_filters = None
41rtems_long_commands = False
42
43windows = os.name == 'nt' or sys.platform in ['msys', 'cygwin']
44
45def options(opt):
46    opt.add_option('--rtems',
47                   default = None,
48                   dest = 'rtems_path',
49                   help = 'Path to an installed RTEMS (defaults to prefix).')
50    opt.add_option('--rtems-tools',
51                   default = None,
52                   dest = 'rtems_tools',
53                   help = 'Path to RTEMS tools (defaults to path to installed RTEMS).')
54    opt.add_option('--rtems-version',
55                   default = None,
56                   dest = 'rtems_version',
57                   help = 'RTEMS version (default is derived from prefix).')
58    opt.add_option('--rtems-archs',
59                   default = 'all',
60                   dest = 'rtems_archs',
61                   help = 'List of RTEMS architectures to build.')
62    opt.add_option('--rtems-bsps',
63                   default = 'all',
64                   dest = 'rtems_bsps',
65                   help = 'List of BSPs to build.')
66    opt.add_option('--show-commands',
67                   action = 'store_true',
68                   default = False,
69                   dest = 'show_commands',
70                   help = 'Print the commands as strings.')
71
72def init(ctx, filters = None, version = None, long_commands = False, bsp_init = None):
73    global rtems_filters
74    global rtems_default_version
75    global rtems_long_commands
76
77    #
78    # Set the RTEMS filter to the context.
79    #
80    rtems_filters = filters
81
82    #
83    # Set the default version, can be overridden.
84    #
85    rtems_default_version = version
86
87    #
88    # Set the long commands option.
89    #
90    rtems_long_commands = long_commands
91
92    env = None
93    contexts = []
94    try:
95        import waflib.Options
96        import waflib.ConfigSet
97
98        #
99        # Load the configuation set from the lock file.
100        #
101        env = waflib.ConfigSet.ConfigSet()
102        env.load(waflib.Options.lockfile)
103
104        #
105        # Check the tools, architectures and bsps.
106        #
107        rtems_version, rtems_path, rtems_tools, archs, arch_bsps = \
108            check_options(ctx,
109                          env.options['prefix'],
110                          env.options['rtems_tools'],
111                          env.options['rtems_path'],
112                          env.options['rtems_version'],
113                          env.options['rtems_archs'],
114                          env.options['rtems_bsps'])
115
116        #
117        # Update the contexts for all the bsps.
118        #
119        from waflib.Build import BuildContext, CleanContext, \
120            InstallContext, UninstallContext
121        for x in arch_bsps:
122            for y in (BuildContext, CleanContext, InstallContext, UninstallContext):
123                name = y.__name__.replace('Context','').lower()
124                class context(y):
125                    cmd = name + '-' + x
126                    variant = x
127                contexts += [context]
128
129        #
130        # Transform the command to per BSP commands.
131        #
132        commands = []
133        for cmd in waflib.Options.commands:
134            if cmd in ['build', 'clean', 'install']:
135                for x in arch_bsps:
136                    commands += [cmd + '-' + x]
137            else:
138                commands += [cmd]
139        waflib.Options.commands = commands
140    except:
141        pass
142
143    if bsp_init:
144        bsp_init(ctx, env, contexts)
145
146def test_application(more = []):
147    code =  ['#include <rtems.h>']
148    code += more
149    code += ['void Init(rtems_task_argument arg) { (void)arg; }']
150    code += ['#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER']
151    code += ['#define CONFIGURE_MAXIMUM_TASKS 1']
152    code += ['#define CONFIGURE_RTEMS_INIT_TASKS_TABLE']
153    code += ['#define CONFIGURE_INIT']
154    code += ['#include <rtems/confdefs.h>']
155    return os.linesep.join(code)
156
157def configure(conf, bsp_configure = None):
158    #
159    # Check the environment for any flags.
160    #
161    for f in ['CC', 'CXX', 'AS', 'LD', 'AR', 'LINK_CC', 'LINK_CXX',
162              'CPPFLAGS', 'CFLAGS', 'CXXFLAGS', 'ASFLAGS', 'LINKFLAGS', 'LIB'
163              'WFLAGS', 'RFLAGS', 'MFLAGS', 'IFLAGS']:
164        if f in os.environ:
165            conf.msg('Environment variable set', f, color = 'RED')
166
167    #
168    # Handle the configurable commands options.
169    #
170    if conf.options.show_commands:
171        show_commands = 'yes'
172    else:
173        show_commands = 'no'
174    if rtems_long_commands and windows:
175        long_commands = 'yes'
176    else:
177        long_commands = 'no'
178
179    rtems_version, rtems_path, rtems_tools, archs, arch_bsps = \
180        check_options(conf,
181                      conf.options.prefix,
182                      conf.options.rtems_tools,
183                      conf.options.rtems_path,
184                      conf.options.rtems_version,
185                      conf.options.rtems_archs,
186                      conf.options.rtems_bsps)
187
188    if rtems_tools is None:
189        conf.fatal('RTEMS tools not found.')
190
191    _log_header(conf)
192
193    conf.msg('RTEMS Version', rtems_version, 'YELLOW')
194    conf.msg('Architectures', ', '.join(archs), 'YELLOW')
195
196    tools = {}
197    env = conf.env.derive()
198
199    for ab in arch_bsps:
200        conf.setenv(ab, env)
201
202        conf.msg('Board Support Package (BSP)', ab, 'YELLOW')
203
204        #
205        # Show and long commands support.
206        #
207        conf.env.SHOW_COMMANDS = show_commands
208        conf.env.LONG_COMMANDS = long_commands
209
210        conf.msg('Show commands', show_commands)
211        conf.msg('Long commands', long_commands)
212
213        arch = _arch_from_arch_bsp(ab)
214        bsp  = _bsp_from_arch_bsp(ab)
215
216        conf.env.ARCH_BSP = '%s/%s' % (arch.split('-')[0], bsp)
217
218        conf.env.RTEMS_PATH = rtems_path
219        conf.env.RTEMS_VERSION = rtems_version
220        conf.env.RTEMS_ARCH_BSP = ab
221        conf.env.RTEMS_ARCH = arch.split('-')[0]
222        conf.env.RTEMS_ARCH_RTEMS = arch
223        conf.env.RTEMS_BSP = bsp
224
225        tools = _find_tools(conf, arch, rtems_tools, tools)
226        for t in tools[arch]:
227            conf.env[t] = tools[arch][t]
228
229        conf.load('gcc')
230        conf.load('g++')
231        conf.load('gas')
232
233        #
234        # Get the version of the tools being used.
235        #
236        rtems_cc = conf.env.CC[0]
237        try:
238            import waflib.Context
239            out = conf.cmd_and_log([rtems_cc, '--version'],
240                                   output = waflib.Context.STDOUT)
241        except Exception as e:
242            conf.fatal('CC version not found: %s' % (e.stderr))
243        #
244        # First line is the version
245        #
246        vline = out.split('\n')[0]
247        conf.msg('Compiler version (%s)' % (os.path.basename(rtems_cc)),
248                                            ' '.join(vline.split()[2:]))
249
250        flags = _load_flags(conf, ab, rtems_path)
251
252        cflags = _filter_flags('cflags', flags['CFLAGS'],
253                               arch, rtems_path)
254        ldflags = _filter_flags('ldflags', flags['LDFLAGS'],
255                               arch, rtems_path)
256
257        conf.env.CFLAGS    = cflags['cflags']
258        conf.env.CXXFLAGS  = cflags['cflags']
259        conf.env.ASFLAGS   = cflags['cflags']
260        conf.env.WFLAGS    = cflags['warnings']
261        conf.env.RFLAGS    = cflags['specs']
262        conf.env.MFLAGS    = cflags['machines']
263        conf.env.IFLAGS    = cflags['includes']
264        conf.env.LINKFLAGS = cflags['cflags'] + ldflags['ldflags']
265        conf.env.LIB       = flags['LIB']
266        conf.env.LIBPATH   = ldflags['libpath']
267
268        conf.env.RTRACE_WRAPPER_ST = '-W %s'
269
270        #
271        # Checks for various RTEMS features.
272        #
273        conf.check_cc(fragment = test_application(),
274                      execute = False,
275                      msg = 'Checking for a valid RTEMS BSP installation')
276        load_cpuopts(conf)
277
278        #
279        # Add tweaks.
280        #
281        tweaks(conf, ab)
282
283        #
284        # If the user has supplied a BSP specific configure function
285        # call it.
286        #
287        if bsp_configure:
288            bsp_configure(conf, ab)
289
290        conf.setenv('', env)
291
292    conf.env.RTEMS_TOOLS = rtems_tools
293    conf.env.ARCHS = archs
294    conf.env.ARCH_BSPS = arch_bsps
295
296    conf.env.SHOW_COMMANDS = show_commands
297    conf.env.LONG_COMMANDS = long_commands
298
299def build(bld):
300    if bld.env.SHOW_COMMANDS == 'yes':
301        output_command_line()
302    if bld.env.LONG_COMMANDS == 'yes':
303        long_command_line()
304
305def load_cpuopts(conf):
306    options = ['RTEMS_DEBUG',
307               'RTEMS_MULTIPROCESSING',
308               'RTEMS_NEWLIB',
309               'RTEMS_POSIX_API',
310               'RTEMS_SMP',
311               'RTEMS_NETWORKING']
312    for opt in options:
313        enabled = check_cpuopt(conf, opt)
314        if enabled:
315            conf.env[opt] = 'Yes'
316        else:
317            conf.env[opt] = 'No'
318
319def check_cpuopt(conf, opt):
320    code =  ['#ifndef %s' % (opt)]
321    code += ['  #error %s is not defined' % (opt)]
322    code += ['#endif']
323    code += ['#if %s' % (opt)]
324    code += ['  /* %s is true */' % (opt)]
325    code += ['#else']
326    code += ['  #error %s is false' % (opt)]
327    code += ['#endif']
328    try:
329        conf.check_cc(fragment = test_application(code),
330                      execute = False,
331                      msg = 'Checking for %s' % (opt))
332    except conf.errors.WafError:
333        return False;
334    return True
335
336def tweaks(conf, arch_bsp):
337    #
338    # Hack to work around NIOS2 naming.
339    #
340    if conf.env.RTEMS_ARCH in ['nios2']:
341        conf.env.OBJCOPY_FLAGS = ['-O', 'elf32-littlenios2']
342    elif conf.env.RTEMS_ARCH in ['arm']:
343        conf.env.OBJCOPY_FLAGS = ['-I', 'binary', '-O', 'elf32-littlearm']
344    else:
345        conf.env.OBJCOPY_FLAGS = ['-O', 'elf32-' + conf.env.RTEMS_ARCH]
346
347    #
348    # Check for a i386 PC bsp.
349    #
350    if re.match('i386-.*-pc[3456]86', arch_bsp) is not None:
351        conf.env.LINKFLAGS += ['-Wl,-Ttext,0x00100000']
352
353    if '-ffunction-sections' in conf.env.CFLAGS:
354      conf.env.LINKFLAGS += ['-Wl,--gc-sections']
355
356def check_options(ctx, prefix, rtems_tools, rtems_path, rtems_version, rtems_archs, rtems_bsps):
357    #
358    # Set defaults
359    #
360    if rtems_version is None:
361        if rtems_default_version is None:
362            m = re.compile('[^0-9.]*([0-9.]+)$').match(prefix)
363            if m:
364                rtems_version = m.group(1)
365            else:
366                ctx.fatal('RTEMS version cannot derived from prefix: ' + prefix)
367        else:
368            rtems_version = rtems_default_version
369    if rtems_path is None:
370        rtems_path = prefix
371    if rtems_tools is None:
372        rtems_tools = rtems_path
373
374    #
375    # Check the paths are valid.
376    #
377    if not os.path.exists(rtems_path):
378        ctx.fatal('RTEMS path not found.')
379    if os.path.exists(os.path.join(rtems_path, 'lib', 'pkgconfig')):
380        rtems_config = None
381    elif os.path.exists(os.path.join(rtems_path, 'rtems-config')):
382        rtems_config = os.path.join(rtems_path, 'rtems-config')
383    else:
384        ctx.fatal('RTEMS path is not valid. No lib/pkgconfig or rtems-config found.')
385    rtems_share_rtems_version = os.path.join(rtems_path, 'share', 'rtems' + rtems_version)
386    if not os.path.exists(os.path.join(rtems_share_rtems_version)):
387        ctx.fatal('RTEMS path is not valid, "%s" not found.' % (rtems_share_rtems_version))
388
389    #
390    # We can more than one path to tools. This happens when testing different
391    # versions.
392    #
393    rt = rtems_tools.split(',')
394    tools = []
395    for path in rt:
396        if not os.path.exists(path):
397            ctx.fatal('RTEMS tools path not found: ' + path)
398        if not os.path.exists(os.path.join(path, 'bin')):
399            ctx.fatal('RTEMS tools path does not contain a \'bin\' directory: ' + path)
400        tools += [os.path.join(path, 'bin')]
401
402    #
403    # Filter the tools.
404    #
405    tools = filter(ctx, 'tools', tools)
406
407    #
408    # Match the archs requested against the ones found. If the user
409    # wants all (default) set all used.
410    #
411    if rtems_archs == 'all':
412        archs = _find_installed_archs(rtems_config, rtems_path, rtems_version)
413    else:
414        archs = _check_archs(rtems_config, rtems_archs, rtems_path, rtems_version)
415
416    #
417    # Filter the architectures.
418    #
419    archs = filter(ctx, 'archs', archs)
420
421    #
422    # We some.
423    #
424    if len(archs) == 0:
425        ctx.fatal('Could not find any architectures')
426
427    #
428    # Get the list of valid BSPs. This process filters the architectures
429    # to those referenced by the BSPs.
430    #
431    if rtems_bsps == 'all':
432        arch_bsps = _find_installed_arch_bsps(rtems_config, rtems_path, archs, rtems_version)
433    else:
434        arch_bsps = _check_arch_bsps(rtems_bsps, rtems_config, rtems_path, archs, rtems_version)
435
436    if len(arch_bsps) == 0:
437        ctx.fatal('No valid arch/bsps found')
438
439    #
440    # Filter the bsps.
441    #
442    arch_bsps = filter(ctx, 'bsps', arch_bsps)
443
444    return rtems_version, rtems_path, tools, archs, arch_bsps
445
446def check_env(ctx, var):
447    if var in ctx.env and len(ctx.env[var]) != 0:
448        return True
449    return False
450
451def check(ctx, option):
452    if option in ctx.env:
453        return ctx.env[option] == 'Yes'
454    return False
455
456def check_debug(ctx):
457    return check(ctx, 'RTEMS_DEBUG')
458
459def check_multiprocessing(ctx):
460    return check(ctx, 'RTEMS_MULTIPROCESSING')
461
462def check_newlib(ctx):
463    return check(ctx, 'RTEMS_NEWLIB')
464
465def check_posix(ctx):
466    return check(ctx, 'RTEMS_POSIX_API')
467
468def check_smp(ctx):
469    return check(ctx, 'RTEMS_SMP')
470
471def check_networking(ctx):
472    return check(ctx, 'RTEMS_NETWORKING')
473
474def arch(arch_bsp):
475    """ Given an arch/bsp return the architecture."""
476    return _arch_from_arch_bsp(arch_bsp).split('-')[0]
477
478def bsp(arch_bsp):
479    """ Given an arch/bsp return the BSP."""
480    return _bsp_from_arch_bsp(arch_bsp)
481
482def arch_bsps(ctx):
483    """ Return the list of arch/bsps we are building."""
484    return ctx.env.ARCH_BSPS
485
486def arch_bsp_env(ctx, arch_bsp):
487    return ctx.env_of_name(arch_bsp).derive()
488
489def filter(ctx, filter, items):
490    if rtems_filters is None:
491        return items
492    if type(rtems_filters) is not dict:
493        ctx.fatal("Invalid RTEMS filter type, " \
494                  "ie { 'tools': { 'in': [], 'out': [] }, 'arch': {}, 'bsps': {} }")
495    if filter not in rtems_filters:
496        return items
497    items_in = []
498    items_out = []
499    if 'in' in rtems_filters[filter]:
500        items_in = copy.copy(rtems_filters[filter]['in'])
501    if 'out' in rtems_filters[filter]:
502        items_out = copy.copy(rtems_filters[filter]['out'])
503    filtered_items = []
504    for i in items:
505        item = i
506        ab = '%s/%s' % (arch(item), bsp(item))
507        for inre in items_in:
508            if re.compile(inre).match(ab):
509                items_in.remove(inre)
510                filtered_items += [item]
511                item = None
512                break
513        if item is not None:
514            for outre in items_out:
515                if re.compile(outre).match(ab):
516                    item = None
517                    break
518        if item is not None:
519            filtered_items += [item]
520    if len(items_in) != 0:
521        ctx.fatal('Following %s not found: %s' % (filter, ', '.join(items_in)))
522    return sorted(filtered_items)
523
524def arch_rtems_version(version, arch):
525    """ Return the RTEMS architecture path, ie sparc-rtems4.11."""
526    return '%s-rtems%s' % (arch, version)
527
528def arch_bsp_path(version, arch_bsp):
529    """ Return the BSP path."""
530    return '%s/%s' % (arch_rtems_version(version, arch(arch_bsp)), bsp(arch_bsp))
531
532def arch_bsp_include_path(version, arch_bsp):
533    """ Return the BSP include path."""
534    return '%s/lib/include' % (arch_bsp_path(version, arch_bsp))
535
536def arch_bsp_lib_path(version, arch_bsp):
537    """ Return the BSP library path. """
538    return '%s/lib' % (arch_bsp_path(version, arch_bsp))
539
540def library_path(library, cc, cflags):
541    cmd = cc + cflags + ['-print-file-name=%s' % library]
542    a = subprocess.check_output(cmd)
543    lib = os.path.abspath(a.strip())
544    if os.path.exists(lib):
545        return os.path.dirname(lib)
546    return None
547
548def root_filesystem(bld, name, files, tar, obj):
549    tar_rule = 'tar -cf ${TGT} --format=ustar -C ../.. $(echo "${SRC}" | sed -e \'s/\.\.\/\.\.\///g\')'
550    if windows:
551        tar_rule = 'sh -c "%s"' % (tar_rule)
552    bld(name = name + '_tar',
553        target = tar,
554        source = files,
555        rule = tar_rule)
556    bld.objects(name = name,
557                target = obj,
558                source = tar,
559                rule = '${OBJCOPY} -I binary -B ${RTEMS_ARCH} ${OBJCOPY_FLAGS} ${SRC} ${TGT}')
560
561def clone_tasks(bld):
562    if bld.cmd == 'build':
563        for obj in bld.all_task_gen[:]:
564            for x in arch_bsp:
565                cloned_obj = obj.clone(x)
566                kind = Options.options.build_kind
567                if kind.find(x) < 0:
568                    cloned_obj.posted = True
569            obj.posted = True
570
571#
572# From the demos. Use this to get the command to cut+paste to play.
573#
574def output_command_line():
575    # first, display strings, people like them
576    from waflib import Utils, Logs
577    from waflib.Context import Context
578    def exec_command(self, cmd, **kw):
579        subprocess = Utils.subprocess
580        kw['shell'] = isinstance(cmd, str)
581        if isinstance(cmd, str):
582            Logs.info('%s' % cmd)
583        else:
584            cmdstr = ' '.join(cmd)
585            Logs.info('(%d) %s' % (len(cmdstr), cmdstr)) # here is the change
586        if not isinstance(kw['cwd'], str):
587            kw['cwd'] = str(kw['cwd'])
588        Logs.debug('runner_env: kw=%s' % kw)
589        try:
590            if self.logger:
591                self.logger.info(cmd)
592                kw['stdout'] = kw['stderr'] = subprocess.PIPE
593                p = subprocess.Popen(cmd, **kw)
594                (out, err) = p.communicate()
595                if out:
596                    self.logger.debug('out: %s' % out.decode(sys.stdout.encoding or 'iso8859-1'))
597                if err:
598                    self.logger.error('err: %s' % err.decode(sys.stdout.encoding or 'iso8859-1'))
599                return p.returncode
600            else:
601                p = subprocess.Popen(cmd, **kw)
602                return p.wait()
603        except OSError:
604            return -1
605    Context.exec_command = exec_command
606
607    # Change the outputs for tasks too
608    from waflib.Task import Task
609    def display(self):
610        return '' # no output on empty strings
611
612    Task.__str__ = display
613
614#
615# From the extras. Use this to support long command lines.
616#
617def long_command_line():
618    def exec_command(self, cmd, **kw):
619        # workaround for command line length limit:
620        # http://support.microsoft.com/kb/830473
621        import tempfile
622        tmp = None
623        try:
624            if not isinstance(cmd, str) and len(str(cmd)) > 8192:
625                (fd, tmp) = tempfile.mkstemp(dir=self.generator.bld.bldnode.abspath())
626                flat = ['"%s"' % x.replace('\\', '\\\\').replace('"', '\\"') for x in cmd[1:]]
627                try:
628                    os.write(fd, ' '.join(flat).encode())
629                finally:
630                    if tmp:
631                        os.close(fd)
632                # Line may be very long:
633                # Logs.debug('runner:' + ' '.join(flat))
634                cmd = [cmd[0], '@' + tmp]
635            ret = super(self.__class__, self).exec_command(cmd, **kw)
636        finally:
637            if tmp:
638                os.remove(tmp)
639        return ret
640    for k in 'c cxx cprogram cxxprogram cshlib cxxshlib cstlib cxxstlib'.split():
641        cls = Task.classes.get(k)
642        if cls:
643            derived_class = type(k, (cls,), {})
644            derived_class.exec_command = exec_command
645            if hasattr(cls, 'hcode'):
646                derived_class.hcode = cls.hcode
647
648def _find_tools(conf, arch, paths, tools):
649    if arch not in tools:
650        arch_tools = {}
651        arch_tools['CC']          = conf.find_program([arch + '-gcc'], path_list = paths)
652        arch_tools['CXX']         = conf.find_program([arch + '-g++'], path_list = paths)
653        arch_tools['LINK_CC']     = arch_tools['CC']
654        arch_tools['LINK_CXX']    = arch_tools['CXX']
655        arch_tools['AS']          = conf.find_program([arch + '-gcc'], path_list = paths)
656        arch_tools['LD']          = conf.find_program([arch + '-ld'],  path_list = paths)
657        arch_tools['AR']          = conf.find_program([arch + '-ar'], path_list = paths)
658        arch_tools['NM']          = conf.find_program([arch + '-nm'], path_list = paths)
659        arch_tools['OBJDUMP']     = conf.find_program([arch + '-objdump'], path_list = paths)
660        arch_tools['OBJCOPY']     = conf.find_program([arch + '-objcopy'], path_list = paths)
661        arch_tools['READELF']     = conf.find_program([arch + '-readelf'], path_list = paths)
662        arch_tools['STRIP']       = conf.find_program([arch + '-strip'], path_list = paths)
663        arch_tools['RTEMS_LD']    = conf.find_program(['rtems-ld'], path_list = paths,
664                                                      mandatory = False)
665        arch_tools['RTEMS_TLD']   = conf.find_program(['rtems-tld'], path_list = paths,
666                                                      mandatory = False)
667        arch_tools['RTEMS_BIN2C'] = conf.find_program(['rtems-bin2c'], path_list = paths,
668                                                      mandatory = False)
669        arch_tools['TAR']         = conf.find_program(['tar'], mandatory = False)
670        tools[arch] = arch_tools
671    return tools
672
673def _find_installed_archs(config, path, version):
674    archs = []
675    if config is None:
676        for d in os.listdir(path):
677            if d.endswith('-rtems' + version):
678                archs += [d]
679    else:
680        a = subprocess.check_output([config, '--list-format', '"%(arch)s"'])
681        a = a[:-1].replace('"', '')
682        archs = set(a.split())
683        archs = ['%s-rtems%s' % (x, version) for x in archs]
684    archs.sort()
685    return archs
686
687def _check_archs(config, req, path, version):
688    installed = _find_installed_archs(config, path, version)
689    archs = []
690    for a in req.split(','):
691        arch = a + '-rtems' + version
692        if arch in installed:
693            archs += [arch]
694    archs.sort()
695    return archs
696
697def _find_installed_arch_bsps(config, path, archs, version):
698    arch_bsps = []
699    if config is None:
700        for f in os.listdir(_pkgconfig_path(path)):
701            if f.endswith('.pc'):
702                if _arch_from_arch_bsp(f[:-3]) in archs:
703                    arch_bsps += [f[:-3]]
704    else:
705        ab = subprocess.check_output([config, '--list-format'])
706        ab = ab[:-1].replace('"', '')
707        ab = ab.replace('/', '-rtems%s-' % (version))
708        arch_bsps = [x for x in set(ab.split())]
709    arch_bsps.sort()
710    return arch_bsps
711
712def _check_arch_bsps(req, config, path, archs, version):
713    archs_bsps = []
714    for ab in req.split(','):
715        abl = ab.split('/')
716        if len(abl) != 2:
717            return []
718        found = False
719        for arch in archs:
720            a = '%s-rtems%s' % (abl[0], version)
721            if a == arch:
722                found = True
723                break
724        if not found:
725            return []
726        archs_bsps += ['%s-%s' % (a, abl[1])]
727    if len(archs_bsps) == 0:
728        return []
729    installed = _find_installed_arch_bsps(config, path, archs, version)
730    bsps = []
731    for b in archs_bsps:
732        if b in installed:
733            bsps += [b]
734    bsps.sort()
735    return bsps
736
737def _arch_from_arch_bsp(arch_bsp):
738    return '-'.join(arch_bsp.split('-')[:2])
739
740def _bsp_from_arch_bsp(arch_bsp):
741    return '-'.join(arch_bsp.split('-')[2:])
742
743def _pkgconfig_path(path):
744    return os.path.join(path, 'lib', 'pkgconfig')
745
746def _load_flags(conf, arch_bsp, path):
747    if not os.path.exists(path):
748        ctx.fatal('RTEMS path not found.')
749    if os.path.exists(_pkgconfig_path(path)):
750        pc = os.path.join(_pkgconfig_path(path), arch_bsp + '.pc')
751        conf.to_log('Opening and load pkgconfig: ' + pc)
752        pkg = pkgconfig.package(pc)
753        config = None
754    elif os.path.exists(os.path.join(path, 'rtems-config')):
755        config = os.path.join(path, 'rtems-config')
756        pkg = None
757    flags = {}
758    _log_header(conf)
759    flags['CFLAGS'] = _load_flags_set('CFLAGS', arch_bsp, conf, config, pkg)
760    flags['LDFLAGS'] = _load_flags_set('LDFLAGS', arch_bsp, conf, config, pkg)
761    flags['LIB'] = _load_flags_set('LIB', arch_bsp, conf, config, pkg)
762    return flags
763
764def _load_flags_set(flags, arch_bsp, conf, config, pkg):
765    conf.to_log('%s ->' % flags)
766    if pkg is not None:
767        flagstr = ''
768        try:
769            flagstr = pkg.get(flags)
770        except pkgconfig.error as e:
771            conf.to_log('pkconfig warning: ' + e.msg)
772        conf.to_log('  ' + flagstr)
773    else:
774        flags_map = { 'CFLAGS': '--cflags',
775                      'LDFLAGS': '--ldflags',
776                      'LIB': '--libs' }
777        ab = arch_bsp.split('-')
778        #conf.check_cfg(path = config,
779        #               package = '',
780        #               uselib_store = 'rtems',
781        #               args = '--bsp %s/%s %s' % (ab[0], ab[2], flags_map[flags]))
782        #print conf.env
783        #print '%r' % conf
784        #flagstr = '-l -c'
785        flagstr = subprocess.check_output([config, '--bsp', '%s/%s' % (ab[0], ab[2]), flags_map[flags]])
786        #print flags, ">>>>", flagstr
787        if flags == 'CFLAGS':
788            flagstr += ' -DWAF_BUILD=1'
789        if flags == 'LIB':
790            flagstr = 'rtemscpu rtemsbsp c rtemscpu rtemsbsp'
791    return flagstr.split()
792
793def _filter_flags(label, flags, arch, rtems_path):
794
795    flag_groups = \
796        [ { 'key': 'warnings', 'path': False, 'flags': { '-W': 1 }, 'cflags': False, 'lflags': False },
797          { 'key': 'includes', 'path': True,  'flags': { '-I': 1, '-isystem': 2, '-sysroot': 2 } },
798          { 'key': 'libpath',  'path': True,  'flags': { '-L': 1 } },
799          { 'key': 'machines', 'path': True,  'flags': { '-O': 1, '-m': 1, '-f': 1, '-G':1, '-E':1 } },
800          { 'key': 'specs',    'path': True,  'flags': { '-q': 1, '-B': 2, '--specs': 2 } } ]
801
802    flags = _strip_cflags(flags)
803
804    _flags = { label: [] }
805    for fg in flag_groups:
806        _flags[fg['key']] = []
807
808    iflags = iter(flags)
809    for opt in iflags:
810        in_label = True
811        opts = []
812        for fg in flag_groups:
813            key = fg['key']
814            for flag in fg['flags']:
815                if opt.startswith(flag):
816                    opt_count = fg['flags'][flag]
817                    if opt_count > 1:
818                        if opt != flag:
819                            opt_count -= 1
820                            if fg['path'] and arch in opt:
821                                opt = '%s%s/%s' % (flag, rtems_path,
822                                                   opt[opt.find(arch):])
823                    opts += [opt]
824                    for c in range(1, opt_count):
825                        opt = next(iflags)
826                        if fg['path'] and arch in opt:
827                            opt = '%s%s/%s' % (f, rtems_path,
828                                               opt[opt.find(arch):])
829                        opts += [opt]
830                    _flags[key] += opts
831                    if label in fg and not fg[label]:
832                        in_label = False
833                    break
834            if in_label:
835                _flags[label] += opts
836    return _flags
837
838def _strip_cflags(cflags):
839    _cflags = []
840    for o in cflags:
841        if o.startswith('-O'):
842            pass
843        elif o.startswith('-g'):
844            pass
845        else:
846            _cflags += [o]
847    return _cflags
848
849def _log_header(conf):
850    conf.to_log('-----------------------------------------')
851
852from waflib import Task
853from waflib import TaskGen
854from waflib import Utils
855from waflib import Node
856from waflib.Tools.ccroot import link_task, USELIB_VARS
857
858USELIB_VARS['rap'] = set(['RTEMS_LINKFLAGS'])
859USELIB_VARS['rtrace'] = set(['RTRACE_FLAGS', 'RTRACE_CFG', 'RTRACE_WRAPPER', 'RTRACE_LINKCMDS'])
860
861class rap(link_task):
862    "Link object files into a RTEMS application"
863    run_str = '${RTEMS_LD} ${RTEMS_LINKFLAGS} --cc ${CC} ${SRC} -o ${TGT[0].abspath()} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}'
864    ext_out = ['.rap']
865    vars    = ['RTEMS_LINKFLAGS', 'LINKDEPS']
866    inst_to = '${BINDIR}'
867
868class rtrace(link_task):
869    "Link object files into a RTEMS trace application"
870    run_str = '${RTEMS_TLD} ${RTACE_FLAGS} ${RTRACE_WRAPPER_ST:RTRACE_WRAPPER} -C ${RTRACE_CFG} -r ${RTEMS_PATH} -B ${ARCH_BSP} -c ${CC} -l ${CC} -- ${SRC} ${LINKFLAGS} ${RTRACE_LINKFLAGS} -o ${TGT[0].abspath()} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}'
871    ext_out = ['.texe']
872    vars    = ['RTRACE_FLAGS', 'RTRACE_CFG', 'RTRACE_WRAPER', 'RTRACE_LINKFLAGS', 'LINKDEPS']
873    inst_to = '${BINDIR}'
874    color = 'PINK'
Note: See TracBrowser for help on using the repository browser.