[rtems-libbsd commit] Add support to build using waf.

Chris Johns chrisj at rtems.org
Wed May 20 07:45:46 UTC 2015


Module:    rtems-libbsd
Branch:    master
Commit:    5ba69495784a29ebc21811aedd37186556b263d0
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=5ba69495784a29ebc21811aedd37186556b263d0

Author:    Chris Johns <chrisj at rtems.org>
Date:      Wed May 20 17:45:16 2015 +1000

Add support to build using waf.

---

 .gitignore          |   2 +
 .gitmodules         |   3 +
 builder.py          |  52 +++++++
 freebsd-to-rtems.py |  14 +-
 rtems_waf           |   1 +
 waf_generator.py    | 398 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 465 insertions(+), 5 deletions(-)

diff --git a/.gitignore b/.gitignore
index 8a4e0b3..213cc0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@ testsuite/include/rtems/bsd/test/network-config.h
 /*.i
 /*.s
 /log
+.lock-waf*
+build
diff --git a/.gitmodules b/.gitmodules
index e079aa7..587cb06 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
 [submodule "freebsd-org"]
 	path = freebsd-org
 	url = https://github.com/freebsd/freebsd.git
+[submodule "rtems_waf"]
+	path = rtems_waf
+	url = git://git.rtems.org/chrisj/rtems_waf.git
diff --git a/builder.py b/builder.py
index 5302112..89fd4ec 100755
--- a/builder.py
+++ b/builder.py
@@ -52,6 +52,58 @@ isDryRun = False
 isDiffMode = False
 filesProcessed = 0
 
+class error(Exception):
+    """Base class for exceptions."""
+    def __init(self, msg):
+        self.msg = 'error: %s' % (msg)
+    def set_output(self, msg):
+        self.msg = msg
+    def __str__(self):
+        return self.msg
+
+def common_flags():
+    return ['-O',
+            '-g',
+            '-fno-strict-aliasing',
+            '-ffreestanding',
+            '-fno-common']
+
+def common_warnings():
+    return ['-Wall',
+            '-Wno-format']
+
+def common_no_warnings():
+    return ['-Wno-implicit-function-declaration']
+
+def includes():
+    return ['-Irtemsbsd/include',
+            '-Ifreebsd/sys',
+            '-Ifreebsd/sys/contrib/altq',
+            '-Ifreebsd/sys/contrib/pf',
+            '-Ifreebsd/include',
+            '-Ifreebsd/lib/libc/include',
+            '-Ifreebsd/lib/libc/isc/include',
+            '-Ifreebsd/lib/libc/resolv',
+            '-Ifreebsd/lib/libutil',
+            '-Ifreebsd/lib/libkvm',
+            '-Ifreebsd/lib/libmemstat',
+            '-Ifreebsd/lib/libipsec',
+            '-Irtemsbsd/sys',
+            '-ImDNSResponder/mDNSCore',
+            '-ImDNSResponder/mDNSShared',
+            '-ImDNSResponder/mDNSPosix',
+            '-Itestsuite/include']
+
+def cpu_includes():
+    return ['-Irtemsbsd/@CPU@/include',
+            '-Ifreebsd/sys/@CPU@/include']
+
+def cflags():
+    return ['-std=gnu11']
+
+def cxxflags():
+    return ['-std=gnu++11']
+
 # compare and process file only if different
 #  + copy or diff depending on execution mode
 def processIfDifferent(new, old, src):
diff --git a/freebsd-to-rtems.py b/freebsd-to-rtems.py
index 5545016..c645ac4 100755
--- a/freebsd-to-rtems.py
+++ b/freebsd-to-rtems.py
@@ -41,6 +41,7 @@ import getopt
 
 import builder
 import makefile
+import waf_generator
 import libbsd
 
 isForward = True
@@ -141,17 +142,20 @@ if isEarlyExit == True:
     print "Early exit at user request"
     sys.exit(0)
 
-makefile_generator = makefile.ModuleManager()
+makefile_gen = makefile.ModuleManager()
+waf_gen = waf_generator.ModuleManager()
 
-libbsd.sources(makefile_generator)
+libbsd.sources(makefile_gen)
+libbsd.sources(waf_gen)
 
 # Perform the actual file manipulation
 if isForward:
     if not isOnlyMakefile:
-        makefile_generator.copyFromFreeBSDToRTEMS()
-    makefile_generator.generate()
+        makefile_gen.copyFromFreeBSDToRTEMS()
+    makefile_gen.generate()
+    waf_gen.generate()
 else:
-    makefile_generator.copyFromRTEMSToFreeBSD()
+    makefile_gen.copyFromRTEMSToFreeBSD()
 
 # Print a summary if changing files
 if builder.isDiffMode == False:
diff --git a/rtems_waf b/rtems_waf
new file mode 160000
index 0000000..7bcf72b
--- /dev/null
+++ b/rtems_waf
@@ -0,0 +1 @@
+Subproject commit 7bcf72b72ec42f2feedac5f5cc5f2f57d50b5d2b
diff --git a/waf_generator.py b/waf_generator.py
new file mode 100755
index 0000000..d5548d5
--- /dev/null
+++ b/waf_generator.py
@@ -0,0 +1,398 @@
+#
+#  Copyright (c) 2015 Chris Johns <chrisj at rtems.org>. All rights reserved.
+#
+#  Copyright (c) 2009-2015 embedded brains GmbH.  All rights reserved.
+#
+#   embedded brains GmbH
+#   Dornierstr. 4
+#   82178 Puchheim
+#   Germany
+#   <info at embedded-brains.de>
+#
+#  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.
+#
+#  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.
+
+import os
+import tempfile
+
+import builder
+
+trace = False
+
+data = { }
+
+def _add_files(name, files):
+    if type(files) is not list:
+        files = [files]
+    if name not in data:
+        data[name] = []
+    data[name] += files
+
+class SourceFileFragmentComposer(builder.BuildSystemFragmentComposer):
+
+    def __init__(self, cflags = "default"):
+        self.cflags = cflags
+
+    def compose(self, path):
+        return ['sources', self.cflags], [path]
+
+class TestFragementComposer(builder.BuildSystemFragmentComposer):
+
+    def __init__(self, testName, fileFragments, runTest = True, netTest = False):
+        self.testName = testName
+        self.fileFragments = fileFragments
+        self.runTest = runTest
+        self.netTest = netTest
+
+    def compose(self, path):
+        return ['tests', self.testName], { 'files': self.fileFragments,
+                                           'run': self.runTest,
+                                           'net': self.netTest }
+
+class KVMSymbolsFragmentComposer(builder.BuildSystemFragmentComposer):
+
+    def compose(self, path):
+        return ['KVMSymbols', 'files'], [path]
+
+class RPCGENFragmentComposer(builder.BuildSystemFragmentComposer):
+
+    def compose(self, path):
+        return ['RPCGen', 'files'], [path]
+
+class RouteKeywordsFragmentComposer(builder.BuildSystemFragmentComposer):
+
+    def compose(self, path):
+        return ['RouteKeywords', 'files'], [path]
+
+class LexFragmentComposer(builder.BuildSystemFragmentComposer):
+
+    def __init__(self, sym, dep):
+        self.sym = sym
+        self.dep = dep
+
+    def compose(self, path):
+        return ['lex', path], { 'file': path,
+                                'sym': self.sym,
+                                'dep': self.dep }
+
+class YaccFragmentComposer(builder.BuildSystemFragmentComposer):
+
+    def __init__(self, sym, header):
+        self.sym = sym
+        self.header = header
+
+    def compose(self, path):
+        return ['yacc', path], { 'file': path,
+                                 'sym': self.sym,
+                                 'header': self.header }
+
+# Module Manager - Collection of Modules
+class ModuleManager(builder.ModuleManager):
+
+    def restart(self):
+        self.script = ''
+
+    def add(self, line = ''):
+        self.script += line + os.linesep
+
+    def write(self):
+        try:
+            out = tempfile.NamedTemporaryFile(delete = False)
+            out.write(self.script)
+            out.close()
+            wscript = builder.RTEMS_DIR + '/wscript'
+            builder.processIfDifferent(out.name, wscript, "wscript")
+        finally:
+            try:
+                os.remove(out.name)
+            except:
+                pass
+
+    def setGenerators(self):
+        self.generator['convert'] = builder.Converter
+        self.generator['no-convert'] = builder.NoConverter
+
+        self.generator['file'] = builder.File
+
+        self.generator['path'] = builder.PathComposer
+        self.generator['freebsd-path'] = builder.FreeBSDPathComposer
+        self.generator['rtems-path'] = builder.RTEMSPathComposer
+        self.generator['cpu-path'] = builder.CPUDependentPathComposer
+        self.generator['target-src-cpu--path'] = builder.TargetSourceCPUDependentPathComposer
+
+        self.generator['source'] = SourceFileFragmentComposer
+        self.generator['test'] = TestFragementComposer
+        self.generator['kvm-symbols'] = KVMSymbolsFragmentComposer
+        self.generator['rpc-gen'] = RPCGENFragmentComposer
+        self.generator['route-keywords'] = RouteKeywordsFragmentComposer
+        self.generator['lex'] = LexFragmentComposer
+        self.generator['yacc'] = YaccFragmentComposer
+
+    def generate(self):
+
+        def _source_list(lhs, files, append = False):
+            if append:
+                adder = '+'
+                adder_space = ' '
+            else:
+                adder = ''
+                adder_space = ''
+            ll = len(lhs)
+            if len(files) == 1:
+                self.add('%s %s= [%r]' % (lhs, adder, files[0]))
+            elif len(files) == 2:
+                self.add('%s %s= [%r,' % (lhs, adder, files[0]))
+                self.add('%s %s   %r]' % (' ' * ll, adder_space, files[-1]))
+            elif len(files) > 0:
+                self.add('%s %s= [%r,' % (lhs, adder, files[0]))
+                for f in files[1:-1]:
+                    self.add('%s %s   %r,' % (' ' * ll, adder_space, f))
+                self.add('%s %s   %r]' % (' ' * ll, adder_space, files[-1]))
+
+        def _data_insert(data, cpu, frag):
+            #
+            # The default handler returns an empty string. Skip it.
+            #
+            if type(frag) is not str:
+                d = data
+                for p in frag[0]:
+                    if p not in d:
+                        d[p] = {}
+                    d = d[p]
+                if type(frag[1]) is list:
+                    if cpu not in d:
+                        d[cpu] = []
+                    d[cpu] += frag[1]
+                else:
+                    d[cpu] = frag[1]
+
+        data = { }
+
+        for mn in self.getModules():
+            m = self[mn]
+            if m.conditionalOn == "none":
+                for f in m.files:
+                    _data_insert(data, 'all', f.getFragment())
+            for cpu, files in sorted(m.cpuDependentSourceFiles.items()):
+                for f in files:
+                    _data_insert(data, cpu, f.getFragment())
+
+        if trace:
+            import pprint
+            pprint.pprint(data)
+
+        self.restart()
+
+        self.add('#')
+        self.add('# Generated waf script.')
+        self.add('#')
+        self.add('')
+        self.add('try:')
+        self.add('    import rtems_waf.rtems as rtems')
+        self.add('except:')
+        self.add('    print "error: no rtems_waf git submodule; see README.waf"')
+        self.add('    import sys')
+        self.add('    sys.exit(1)')
+        self.add('')
+        self.add('def init(ctx):')
+        self.add('    rtems.init(ctx)')
+        self.add('')
+        self.add('def options(opt):')
+        self.add('    rtems.options(opt)')
+        self.add('')
+        self.add('def configure(conf):')
+        self.add('    conf.find_program("lex", mandatory = True)')
+        self.add('    conf.find_program("rpcgen", mandatory = True)')
+        self.add('    conf.find_program("yacc", mandatory = True)')
+        self.add('    rtems.configure(conf)')
+        self.add('    if rtems.check_networking(conf):')
+        self.add('        conf.fatal("RTEMS kernel contains the old network support; configure RTEMS with --disable-networking")')
+        self.add('')
+        self.add('def build(bld):')
+        self.add('    rtems.build(bld)')
+        self.add('')
+        self.add('    # C/C++ flags')
+        self.add('    common_flags = []')
+        for f in builder.common_flags():
+            self.add('    common_flags += ["%s"]' % (f))
+        for f in builder.common_no_warnings():
+            self.add('    common_flags += ["%s"]' % (f))
+        self.add('    cflags = %r + common_flags' % (builder.cflags()))
+        self.add('    cxxflags = %r + common_flags' % (builder.cxxflags()))
+        self.add('')
+        self.add('    # Include paths')
+        self.add('    includes = []')
+        for i in builder.includes():
+            self.add('    includes += ["%s"]' % (i[2:]))
+        self.add('    for i in %r:' % (builder.cpu_includes()))
+        self.add('        includes += ["%s" % (i[2:].replace("@CPU@", bld.get_env()["RTEMS_ARCH"]))]')
+        self.add('')
+        self.add('    # Support dummy PIC IRQ includes')
+        self.add('    if bld.get_env()["RTEMS_ARCH"] not in ("arm", "i386", "lm32", "mips", "powerpc", "sparc", "m68k"):')
+        self.add('        includes += ["rtems-dummy-pic-irq/include"]')
+        self.add('')
+
+        self.add('    # Collect the libbsd uses')
+        self.add('    libbsd_use = []')
+        self.add('')
+
+        #
+        # Add the specific rule based builders for generating files.
+        #
+        if 'KVMSymbols' in data:
+            kvmsymbols = data['KVMSymbols']
+            self.add('    # KVM Symbols')
+            self.add('    bld(target = "%s",' % (kvmsymbols['files']['all'][0]))
+            self.add('        source = "rtemsbsd/rtems/generate_kvm_symbols",')
+            self.add('        rule = "./${SRC} > ${TGT}")')
+            self.add('    bld.objects(target = "kvmsymbols",')
+            self.add('                features = "c",')
+            self.add('                cflags = cflags,')
+            self.add('                includes = includes,')
+            self.add('                source = "%s")' % (kvmsymbols['files']['all'][0]))
+            self.add('    libbsd_use += ["kvmsymbols"]')
+            self.add('')
+
+        if 'RPCGen' in data:
+            rpcgen = data['RPCGen']
+            rpcname = rpcgen['files']['all'][0][:-2]
+            self.add('    # RPC Generation')
+            self.add('    bld(target = "%s.h",' % (rpcname))
+            self.add('        source = "%s.x",' % (rpcname))
+            self.add('        rule = "${RPCGEN} -h -o ${TGT} ${SRC}")')
+            self.add('')
+
+        if 'RouteKeywords' in data:
+            routekw = data['RouteKeywords']
+            rkwname = routekw['files']['all'][0]
+            self.add('    # Route keywords')
+            self.add('    rkw_rule = "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}"')
+            self.add('    bld(target = "%s.h",' % (rkwname))
+            self.add('        source = "%s",' % (rkwname))
+            self.add('        rule = rkw_rule)')
+            self.add('')
+
+        if 'lex' in data:
+            lexes = data['lex']
+            self.add('    # Lex')
+            for l in lexes:
+                lex = lexes[l]['all']
+                self.add('    bld(target = "%s.c",' % (lex['file'][:-2]))
+                self.add('        source = "%s",' % (lex['file']))
+                self.add('        rule = "${LEX} -P %s -t ${SRC} | ' % (lex['sym']) + \
+                         'sed -e \'/YY_BUF_SIZE/s/16384/1024/\' > ${TGT}")')
+                self.add('    bld.objects(target = "lex_%s",' % (lex['sym']))
+                self.add('                features = "c",')
+                self.add('                cflags = cflags,')
+                self.add('                includes = includes,')
+                self.add('                source = "%s.c")' % (lex['file'][:-2]))
+                self.add('    libbsd_use += ["lex_%s"]' % (lex['sym']))
+                self.add('')
+
+        if 'yacc' in data:
+            yaccs = data['yacc']
+            self.add('    # Yacc')
+            for y in yaccs:
+                yacc = yaccs[y]['all']
+                yacc_file = yacc['file']
+                yacc_sym = yacc['sym']
+                yacc_header = '%s/%s' % (os.path.dirname(yacc_file), yacc['header'])
+                self.add('    bld(target = "%s.c",' % (yacc_file[:-2]))
+                self.add('        source = "%s",' % (yacc_file))
+                self.add('        rule = "${YACC} -b %s -d -p %s ${SRC} && ' % (yacc_sym, yacc_sym) + \
+                         'sed -e \'/YY_BUF_SIZE/s/16384/1024/\' < %s.tab.c > ${TGT} && ' % (yacc_sym) + \
+                         'rm -f %s.tab.c && mv %s.tab.h %s")' % (yacc_sym, yacc_sym, yacc_header))
+                self.add('    bld.objects(target = "yacc_%s",' % (yacc_sym))
+                self.add('                features = "c",')
+                self.add('                cflags = cflags,')
+                self.add('                includes = includes,')
+                self.add('                source = "%s.c")' % (yacc_file[:-2]))
+                self.add('    libbsd_use += ["yacc_%s"]' % (yacc_sym))
+            self.add('')
+
+        #
+        # We have 'm' different sets of flags and there can be 'n' cpus
+        # specific files for those flags.
+        #
+        objs = 0
+        self.add('    # Objects built with different CFLAGS')
+        for cflags in sorted(data['sources']):
+            if cflags is not 'default':
+                objs += 1
+                _source_list('    objs%02d_source' % objs, sorted(data['sources'][cflags]['all']))
+                archs = sorted(data['sources'][cflags])
+                for arch in archs:
+                    if arch is not 'all':
+                        self.add('    if bld.get_env()["RTEMS_ARCH"] == "%s":' % arch)
+                        _source_list('        objs%02d_source' % objs,
+                                     sorted(data['sources'][cflags][arch]),
+                                     append = True)
+                defines = [d[2:] for d in cflags.split(' ')]
+                self.add('    bld.objects(target = "objs%02d",' % (objs))
+                self.add('                features = "c",')
+                self.add('                cflags = cflags,')
+                self.add('                includes = includes,')
+                self.add('                defines = %r,' % (defines))
+                self.add('                source = objs%02d_source)' % objs)
+                self.add('    libbsd_use += ["objs%02d"]' % (objs))
+                self.add('')
+
+        #
+        # We hold the 'default' cflags set of files to the end to create the
+        # static library with.
+        #
+        _source_list('    source', sorted(data['sources']['default']['all']))
+        archs = sorted(data['sources']['default'])
+        for arch in archs:
+            if arch is not 'all':
+                self.add('    if bld.get_env()["RTEMS_ARCH"] == "%s":' % arch)
+                _source_list('        source',
+                             sorted(data['sources']['default'][arch]),
+                             append = True)
+        self.add('    bld.stlib(target = "bsd",')
+        self.add('              features = "c cxx",')
+        self.add('              cflags = cflags,')
+        self.add('              cxxflags = cxxflags,')
+        self.add('              includes = includes,')
+        self.add('              source = source,')
+        self.add('              use = libbsd_use)')
+        self.add('')
+
+        self.add('    # Tests')
+        tests = data['tests']
+        for test_name in tests:
+            files = ['testsuite/%s/%s.c' % (test_name, f) for f in  data['tests'][test_name]['all']['files']]
+            _source_list('    test_%s' % (test_name), sorted(files))
+            self.add('    bld.program(target = "%s",' % (test_name))
+            self.add('                features = "cprogram",')
+            self.add('                cflags = cflags,')
+            self.add('                includes = includes,')
+            self.add('                source = test_%s,' % (test_name))
+            self.add('                use = ["bsd"],')
+            self.add('                lib = ["m", "z"])')
+            self.add('')
+
+        self.write()




More information about the vc mailing list