source: rtems_waf/rtems.py @ 254b827

Last change on this file since 254b827 was 254b827, checked in by Sebastian Huber <sebastian.huber@…>, on 06/16/16 at 08:15:55

Use long commands on more platforms

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