source: rtems_waf/rtems.py @ 1aef190

Last change on this file since 1aef190 was 1aef190, checked in by Chris Johns <chrisj@…>, on Jun 16, 2016 at 3:28:52 AM

Add long command line support for gcc.

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