diff options
Diffstat (limited to 'waf_libbsd.py')
-rw-r--r-- | waf_libbsd.py | 445 |
1 files changed, 251 insertions, 194 deletions
diff --git a/waf_libbsd.py b/waf_libbsd.py index 9ac5bf35..f1088584 100644 --- a/waf_libbsd.py +++ b/waf_libbsd.py @@ -1,7 +1,10 @@ +# SPDX-License-Identifier: BSD-2-Clause +"""LibBSD build configuration to waf integration module. +""" + +# Copyright (c) 2015, 2020 Chris Johns <chrisj@rtems.org>. All rights reserved. # -# Copyright (c) 2015-2018 Chris Johns <chrisj@rtems.org>. All rights reserved. -# -# Copyright (c) 2009-2015 embedded brains GmbH. All rights reserved. +# Copyright (c) 2009, 2015 embedded brains GmbH. All rights reserved. # # embedded brains GmbH # Dornierstr. 4 @@ -9,35 +12,30 @@ # Germany # <info@embedded-brains.de> # -# Copyright (c) 2012 OAR Corporation. All rights reserved. +# Copyright (c) 2012 OAR Corporation. All rights reserved. # -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. # -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. from __future__ import print_function -# Python 3 does no longer know the basestring class. Catch that. -try: - basestring -except NameError: - basestring = (str, bytes) import os import sys @@ -48,6 +46,10 @@ import builder import rtems_waf.rtems as rtems + +BUILDSET_DIR = builder.BUILDSET_DIR +BUILDSET_DEFAULT = builder.BUILDSET_DEFAULT + windows = os.name == 'nt' if windows: @@ -55,12 +57,16 @@ if windows: else: host_shell = '' +def _add_flags_if_not_present(current_flags, addional_flags): + for flag in addional_flags: + if flag not in current_flags: + current_flags.append(flag) + # # The waf builder for libbsd. # class Builder(builder.ModuleManager): - - def __init__(self, trace = False): + def __init__(self, trace=False): super(Builder, self).__init__() self.trace = trace self.data = {} @@ -82,12 +88,11 @@ class Builder(builder.ModuleManager): return sources def generate(self, rtems_version): - - def _dataInsert(data, cpu, frag): + def _dataInsert(data, cpu, space, frag): # - # The default handler returns an empty string. Skip it. + # The default handler returns None. Skip it. # - if type(frag) is not str: + if frag is not None: # Start at the top of the tree d = data path = frag[0] @@ -96,6 +101,10 @@ class Builder(builder.ModuleManager): # Select the sub-part of the tree as the compile options # specialise how files are built. d = d[path[0]] + # Group based on the space, ie kernel or user + if space not in d: + d[space] = {} + d = d[space] if type(path[1]) is list: p = ' '.join(path[1]) else: @@ -104,14 +113,14 @@ class Builder(builder.ModuleManager): d[p] = {} d = d[p] if cpu not in d: - d[cpu] = { } + d[cpu] = {} config = frag[0][2][0] if config != 'default': if 'configure' not in data: - data['configure'] = { } + data['configure'] = {} configTest = frag[1]['configTest'] if configTest not in data['configure']: - data['configure'][configTest] = { } + data['configure'][configTest] = {} data['configure'][configTest][config] = frag[0][2][1] if type(frag[1]) is list: if config not in d[cpu]: @@ -137,15 +146,24 @@ class Builder(builder.ModuleManager): self.data = {} - for mn in self.getEnabledModules(): + enabled_modules = self.getEnabledModules() + for mn in enabled_modules: m = self[mn] - if m.conditionalOn == "none": + enabled = True + for dep in m.dependencies: + if dep not in enabled_modules: + enabled = False + break + if enabled: for f in m.files: - _dataInsert(self.data, 'all', f.getFragment()) - for cpu, files in sorted(m.cpuDependentSourceFiles.items()): - for f in files: - _dataInsert(self.data, cpu, f.getFragment()) - + _dataInsert(self.data, 'all', f.getSpace(), + f.getFragment()) + for cpu, files in sorted(m.cpuDependentSourceFiles.items()): + for f in files: + _dataInsert(self.data, cpu, f.getSpace(), + f.getFragment()) + + # Start here if you need to understand self.data. Add 'True or' if self.trace: import pprint pprint.pprint(self.data) @@ -156,19 +174,23 @@ class Builder(builder.ModuleManager): for cfg in self.data['configure'][configTest]: if configTest == 'header': for h in self.data['configure'][configTest][cfg]: - conf.check(header_name = h, - features = "c", - includes = conf.env.IFLAGS, - mandatory = False) + conf.check(header_name=h, + features="c", + includes=conf.env.IFLAGS, + mandatory=False) elif configTest == 'library': for l in self.data['configure'][configTest][cfg]: - conf.check_cc(lib = l, - fragment = rtems.test_application(), - execute = False, - mandatory = False) + if conf.check_cc(lib=l, + fragment=rtems.test_application(), + execute=False, + mandatory=False): + conf.env['HAVE_%s' % l.upper()] = True else: bld.fatal('invalid config test: %s' % (configTest)) - + section_flags = ["-fdata-sections", "-ffunction-sections"] + _add_flags_if_not_present(conf.env.CFLAGS, section_flags) + _add_flags_if_not_present(conf.env.CXXFLAGS, section_flags) + _add_flags_if_not_present(conf.env.LINKFLAGS, ["-Wl,--gc-sections"]) def build(self, bld): # @@ -204,23 +226,45 @@ class Builder(builder.ModuleManager): defines += ['%s=1' % (o.strip().upper())] # - # Include paths - # - includes = [] - buildinclude = 'build-include' - if 'cpu-include-paths' in config: + # Include paths, maintain paths for each build space. + # + include_paths = config['include-paths'] + if 'build' not in include_paths: + bld.fatal('no build include path found in include-path defaults') + buildinclude = include_paths['build'] + if isinstance(buildinclude, list): + buildinclude = buildinclude[0] + inc_paths = sorted(include_paths) + inc_paths.remove('build') + inc_paths.remove('cpu') + includes = {} + for inc in inc_paths: + includes[inc] = include_paths[inc] + # cpu include paths must be the first searched + if 'cpu' in include_paths: cpu = bld.get_env()['RTEMS_ARCH'] - if cpu == "i386": - includes += ['freebsd/sys/x86/include'] - for i in config['cpu-include-paths']: - includes += [i.replace('@CPU@', cpu)] - if 'include-paths' in config: - includes += config['include-paths'] - if 'build-include-path' in config: - buildinclude = config['build-include-path'] - if not isinstance(buildinclude, basestring): - buildinclude = buildinclude[0] - includes += [buildinclude] + for i in include_paths['cpu']: + includes['kernel'].insert(0, i.replace('@CPU@', cpu)) + includes['kernel'] += [buildinclude] + + # + # Path mappings + # + if 'path-mappings' in config: + for source, target in config['path-mappings']: + for space in includes: + incs = includes[space] + if source in incs: + target = [target] if isinstance(target, + str) else target + i = incs.index(source) + incs.remove(source) + incs[i:i] = target + + # + # Place the kernel include paths after the user paths + # + includes['user'] += includes['kernel'] # # Collect the libbsd uses @@ -231,16 +275,17 @@ class Builder(builder.ModuleManager): # Network test configuration # if not os.path.exists(bld.env.NET_CONFIG): - bld.fatal('network configuraiton \'%s\' not found' % (bld.env.NET_CONFIG)) - tags = [ 'NET_CFG_INTERFACE_0', - 'NET_CFG_SELF_IP', - 'NET_CFG_NETMASK', - 'NET_CFG_PEER_IP', - 'NET_CFG_GATEWAY_IP' ] + bld.fatal('network configuraiton \'%s\' not found' % + (bld.env.NET_CONFIG)) + tags = [ + 'NET_CFG_INTERFACE_0', 'NET_CFG_SELF_IP', 'NET_CFG_NETMASK', + 'NET_CFG_PEER_IP', 'NET_CFG_GATEWAY_IP' + ] try: net_cfg_lines = open(bld.env.NET_CONFIG).readlines() except: - bld.fatal('network configuraiton \'%s\' read failed' % (bld.env.NET_CONFIG)) + bld.fatal('network configuraiton \'%s\' read failed' % + (bld.env.NET_CONFIG)) lc = 0 sed = 'sed ' for l in net_cfg_lines: @@ -255,10 +300,10 @@ class Builder(builder.ModuleManager): for t in tags: if lhs == t: sed += "-e 's/@%s@/%s/' " % (t, rhs) - bld(target = "testsuite/include/rtems/bsd/test/network-config.h", - source = "testsuite/include/rtems/bsd/test/network-config.h.in", - rule = sed + " < ${SRC} > ${TGT}", - update_outputs = True) + bld(target="testsuite/include/rtems/bsd/test/network-config.h", + source="testsuite/include/rtems/bsd/test/network-config.h.in", + rule=sed + " < ${SRC} > ${TGT}", + update_outputs=True) # # Add a copy rule for all headers where the install path and the source @@ -266,7 +311,8 @@ class Builder(builder.ModuleManager): # if 'header-paths' in config: header_build_copy_paths = [ - hp for hp in config['header-paths'] if hp[2] != '' and not hp[0].endswith(hp[2]) + hp for hp in config['header-paths'] + if hp[2] != '' and not hp[0].endswith(hp[2]) ] for headers in header_build_copy_paths: target = os.path.join(buildinclude, headers[2]) @@ -274,10 +320,10 @@ class Builder(builder.ModuleManager): for header in start_dir.ant_glob(headers[1]): relsourcepath = header.path_from(start_dir) targetheader = os.path.join(target, relsourcepath) - bld(features = 'subst', - target = targetheader, - source = header, - is_copy = True) + bld(features='subst', + target=targetheader, + source=header, + is_copy=True) # # Generate a header that contains information about enabled modules @@ -296,12 +342,13 @@ class Builder(builder.ModuleManager): output += '#define RTEMS_BSD_MODULE_{} 1\n'.format(modname) output += '#endif /* RTEMS_BSD_MODULES_H */\n' self.outputs[0].write(output) + modules_h_file_with_path = os.path.join(buildinclude, module_header_path, module_header_name) - bld(rule = rtems_libbsd_modules_h_gen, - target = modules_h_file_with_path, - before = ['c', 'cxx']) + bld(rule=rtems_libbsd_modules_h_gen, + target=modules_h_file_with_path, + before=['c', 'cxx']) # # Add the specific rule based builders @@ -311,20 +358,20 @@ class Builder(builder.ModuleManager): # KVM Symbols # if 'KVMSymbols' in self.data: - kvmsymbols = self.data['KVMSymbols'] + kvmsymbols = self.data['KVMSymbols']['kernel'] if 'includes' in kvmsymbols['files']: kvmsymbols_includes = kvmsymbols['files']['includes'] else: kvmsymbols_includes = [] - bld(target = kvmsymbols['files']['all']['default'][0], - source = 'rtemsbsd/rtems/generate_kvm_symbols', - rule = host_shell + './${SRC} > ${TGT}', - update_outputs = True) - bld.objects(target = 'kvmsymbols', - features = 'c', - cflags = cflags, - includes = kvmsymbols_includes + includes, - source = kvmsymbols['files']['all']['default'][0]) + bld(target=kvmsymbols['files']['all']['default'][0], + source='rtemsbsd/rtems/generate_kvm_symbols', + rule=host_shell + './${SRC} > ${TGT}', + update_outputs=True) + bld.objects(target='kvmsymbols', + features='c', + cflags=cflags, + includes=kvmsymbols_includes + includes['kernel'], + source=kvmsymbols['files']['all']['default'][0]) libbsd_use += ["kvmsymbols"] bld.add_group() @@ -334,32 +381,30 @@ class Builder(builder.ModuleManager): # if 'RPCGen' in self.data: if bld.env.AUTO_REGEN: - rpcgen = self.data['RPCGen'] + rpcgen = self.data['RPCGen']['user'] rpcname = rpcgen['files']['all']['default'][0][:-2] - bld(target = rpcname + '.h', - source = rpcname + '.x', - rule = host_shell + '${RPCGEN} -h -o ${TGT} ${SRC}') + bld(target=rpcname + '.h', + source=rpcname + '.x', + rule=host_shell + '${RPCGEN} -h -o ${TGT} ${SRC}') # # Route keywords # if 'RouteKeywords' in self.data: if bld.env.AUTO_REGEN: - routekw = self.data['RouteKeywords'] + routekw = self.data['RouteKeywords']['user'] rkwname = routekw['files']['all']['default'][0] rkw_rule = host_shell + "cat ${SRC} | " + \ "awk 'BEGIN { r = 0 } { if (NF == 1) " + \ "printf \"#define\\tK_%%s\\t%%d\\n\\t{\\\"%%s\\\", K_%%s},\\n\", " + \ "toupper($1), ++r, $1, toupper($1)}' > ${TGT}" - bld(target = rkwname + '.h', - source = rkwname, - rule = rkw_rule) + bld(target=rkwname + '.h', source=rkwname, rule=rkw_rule) # # Lex # if 'lex' in self.data: - lexes = self.data['lex'] + lexes = self.data['lex']['user'] for l in sorted(lexes.keys()): lex = lexes[l]['all']['default'] if 'cflags' in lex: @@ -373,23 +418,23 @@ class Builder(builder.ModuleManager): lex_rule = host_shell + '${LEX} -P ' + lex['sym'] + ' -t ${SRC} | ' + \ 'sed -e \'/YY_BUF_SIZE/s/16384/1024/\' > ${TGT}' if bld.env.AUTO_REGEN: - bld(target = lex['file'][:-2]+ '.c', - source = lex['file'], - rule = lex_rule) + bld(target=lex['file'][:-2] + '.c', + source=lex['file'], + rule=lex_rule) if lex['build']: - bld.objects(target = 'lex_%s' % (lex['sym']), - features = 'c', - cflags = cflags, - includes = lexIncludes + includes, - defines = defines + lexDefines, - source = lex['file'][:-2] + '.c') + bld.objects(target='lex_%s' % (lex['sym']), + features='c', + cflags=cflags, + includes=lexIncludes + includes['user'], + defines=defines + lexDefines, + source=lex['file'][:-2] + '.c') libbsd_use += ['lex_%s' % (lex['sym'])] # # Yacc # if 'yacc' in self.data: - yaccs = self.data['yacc'] + yaccs = self.data['yacc']['user'] for y in sorted(yaccs.keys()): yacc = yaccs[y]['all']['default'] yaccFile = yacc['file'] @@ -397,7 +442,8 @@ class Builder(builder.ModuleManager): yaccSym = yacc['sym'] else: yaccSym = os.path.basename(yaccFile)[:-2] - yaccHeader = '%s/%s' % (os.path.dirname(yaccFile), yacc['header']) + yaccHeader = '%s/%s' % (os.path.dirname(yaccFile), + yacc['header']) if 'cflags' in yacc: yaccDefines = [d[2:] for d in yacc['cflags']] else: @@ -408,19 +454,20 @@ class Builder(builder.ModuleManager): yaccIncludes = [] yacc_rule = host_shell + '${YACC} -b ' + yaccSym + \ ' -d -p ' + yaccSym + ' ${SRC} && ' + \ - 'sed -e \'/YY_BUF_SIZE/s/16384/1024/\' < ' + yaccSym + '.tab.c > ${TGT} && ' + \ + 'sed -e \'/YY_BUF_SIZE/s/16384/1024/\' < ' + \ + yaccSym + '.tab.c > ${TGT} && ' + \ 'rm -f ' + yaccSym + '.tab.c && mv ' + yaccSym + '.tab.h ' + yaccHeader if bld.env.AUTO_REGEN: - bld(target = yaccFile[:-2] + '.c', - source = yaccFile, - rule = yacc_rule) + bld(target=yaccFile[:-2] + '.c', + source=yaccFile, + rule=yacc_rule) if yacc['build']: - bld.objects(target = 'yacc_%s' % (yaccSym), - features = 'c', - cflags = cflags, - includes = yaccIncludes + includes, - defines = defines + yaccDefines, - source = yaccFile[:-2] + '.c') + bld.objects(target='yacc_%s' % (yaccSym), + features='c', + cflags=cflags, + includes=yaccIncludes + includes['user'], + defines=defines + yaccDefines, + source=yaccFile[:-2] + '.c') libbsd_use += ['yacc_%s' % (yaccSym)] # @@ -428,56 +475,54 @@ class Builder(builder.ModuleManager): # specific files for those flags. # objs = 0 - sources = sorted(self.data['sources']) - if 'default' in sources: - sources.remove('default') - for flags in sources: - objs += 1 - build = self.data['sources'][flags] - target = 'objs%02d' % (objs) - bld_sources = Builder._sourceList(bld, build['all']) - archs = sorted(build) - for i in ['all', 'cflags', 'includes']: - if i in archs: - archs.remove(i) - for arch in archs: - if bld.get_env()['RTEMS_ARCH'] == arch: - bld_sources += Builder._sourceList(bld, build[arch]) - if 'cflags' in build: - bld_defines = [d[2:] for d in build['cflags']] - else: - bld_defines = [] - if 'includes' in build: - bld_includes = build['includes'] - else: - bld_includes = [] - bld.objects(target = target, - features = 'c', - cflags = cflags, - includes = sorted(bld_includes) + includes, - defines = defines + sorted(bld_defines), - source = bld_sources) - libbsd_use += [target] - - # - # We hold the 'default' cflags set of files to the end to create the - # static library with. - # - build = self.data['sources']['default'] + for space in sorted(self.data['sources']): + sources = sorted(self.data['sources'][space]) + if space == 'kernel' and 'default' in sources: + sources.remove('default') + for flags in sources: + objs += 1 + build = self.data['sources'][space][flags] + target = 'objs%02d' % (objs) + bld_sources = Builder._sourceList(bld, build['all']) + archs = sorted(build) + for i in ['all', 'cflags', 'includes']: + if i in archs: + archs.remove(i) + for arch in archs: + if bld.get_env()['RTEMS_ARCH'] == arch: + bld_sources += Builder._sourceList(bld, build[arch]) + bld_cflags = sorted(build.get('cflags', [])) + if 'default' in bld_cflags: + bld_cflags.remove('default') + bld.objects(target=target, + features='c cxx', + cflags=cflags + bld_cflags, + cxxflags=cxxflags, + includes=sorted(build.get('includes', [])) + + includes[space], + defines=defines, + source=bld_sources) + libbsd_use += [target] + + # + # We hold the kernel 'default' cflags set of files to the end to + # create the static library with. + # + build = self.data['sources']['kernel']['default'] bld_sources = Builder._sourceList(bld, build['all']) archs = sorted(build) archs.remove('all') for arch in archs: if bld.get_env()['RTEMS_ARCH'] == arch: bld_sources += Builder._sourceList(bld, build[arch]) - bld.stlib(target = 'bsd', - features = 'c cxx', - cflags = cflags, - cxxflags = cxxflags, - includes = includes, - defines = defines, - source = bld_sources, - use = libbsd_use) + bld.stlib(target='bsd', + features='c cxx', + cflags=cflags, + cxxflags=cxxflags, + includes=includes['kernel'], + defines=defines, + source=bld_sources, + use=libbsd_use) # # Installs. @@ -494,36 +539,48 @@ class Builder(builder.ModuleManager): if 'header-paths' in config: headerPaths = config['header-paths'] cpu = bld.get_env()['RTEMS_ARCH'] - if cpu == "i386": - cpu = 'x86' for headers in headerPaths: - # Get the dest path - ipath = os.path.join(arch_inc_path, headers[2]) - start_dir = bld.path.find_dir(headers[0].replace('@CPU@', cpu)) - if start_dir != None: - bld.install_files("${PREFIX}/" + ipath, - start_dir.ant_glob(headers[1]), - cwd = start_dir, - relative_trick = True) + paths = [headers[0].replace('@CPU@', cpu)] + # Apply the path mappings + for source, targets in config['path-mappings']: + if source in paths: + i = paths.index(source) + paths.remove(source) + paths[i:i] = targets + + for hp in paths: + # Get the dest path + ipath = os.path.join(arch_inc_path, headers[2]) + start_dir = bld.path.find_dir(hp) + if start_dir != None: + bld.install_files("${PREFIX}/" + ipath, + start_dir.ant_glob(headers[1]), + cwd=start_dir, + relative_trick=True) bld.install_files(os.path.join("${PREFIX}", arch_inc_path, module_header_path), modules_h_file_with_path, - cwd = bld.path) + cwd=bld.path) # # Tests # tests = [] if 'tests' in self.data: - tests = self.data['tests'] + tests = self.data['tests']['user'] + enabled_modules = self.getEnabledModules() for testName in sorted(tests): - test = self.data['tests'][testName]['all'] + test = tests[testName]['all'] test_source = [] libs = ['bsd', 'm', 'z', 'rtemstest'] for cfg in test: build_test = True - if cfg != 'default': + for mod in test[cfg]['modules']: + if mod not in enabled_modules: + build_test = False + break + if build_test and cfg != 'default': for c in cfg.split(' '): if not bld.env['HAVE_%s' % (c)]: build_test = False @@ -533,11 +590,11 @@ class Builder(builder.ModuleManager): for f in test[cfg]['files']] libs = test[cfg]['libs'] + libs if build_test: - bld.program(target = '%s.exe' % (testName), - features = 'cprogram', - cflags = cflags, - includes = includes, - source = test_sources, - use = ['bsd'], - lib = libs, - install_path = None) + bld.program(target='%s.exe' % (testName), + features='cprogram', + cflags=cflags, + includes=includes['user'], + source=test_sources, + use=['bsd'], + lib=libs, + install_path=None) |