source: rtems-libbsd/builder.py @ f478e3c

5-freebsd-12freebsd-9.3
Last change on this file since f478e3c was f478e3c, checked in by Chris Johns <chrisj@…>, on May 4, 2016 at 5:58:25 AM

Add sys/rpc so it is installed.

  • Property mode set to 100755
File size: 22.3 KB
Line 
1#
2#  Copyright (c) 2015-2016 Chris Johns <chrisj@rtems.org>. All rights reserved.
3#
4#  Copyright (c) 2009-2015 embedded brains GmbH.  All rights reserved.
5#
6#   embedded brains GmbH
7#   Dornierstr. 4
8#   82178 Puchheim
9#   Germany
10#   <info@embedded-brains.de>
11#
12#  Copyright (c) 2012 OAR Corporation. All rights reserved.
13#
14#  Redistribution and use in source and binary forms, with or without
15#  modification, are permitted provided that the following conditions
16#  are met:
17#  1. Redistributions of source code must retain the above copyright
18#     notice, this list of conditions and the following disclaimer.
19#  2. Redistributions in binary form must reproduce the above copyright
20#     notice, this list of conditions and the following disclaimer in the
21#     documentation and/or other materials provided with the distribution.
22#
23#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24#  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25#  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26#  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27#  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29#  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31#  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32#  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35# FreeBSD: http://svn.freebsd.org/base/releng/8.2/sys (revision 222485)
36
37from __future__ import print_function
38
39import shutil
40import os
41import re
42import sys
43import getopt
44import filecmp
45import difflib
46import codecs
47
48#
49# Global controls.
50#
51RTEMS_DIR = "."
52FreeBSD_DIR = "freebsd-org"
53verboseLevel = 0
54isDryRun = False
55isDiffMode = False
56filesProcessedCount = 0
57filesProcessed = []
58
59verboseInfo = 1
60verboseDetail = 2
61verboseMoreDetail = 3
62verboseDebug = 4
63
64def verbose(level = verboseInfo):
65    return verboseLevel >= level
66
67def changedFileSummary():
68    if isDiffMode == False:
69        print('%d file(s) were changed:' % (filesProcessedCount))
70        if verbose():
71            for f in sorted(filesProcessed):
72                print(' %s' % (f))
73
74def read_file(name):
75    try:
76        contents = codecs.open(name, mode = 'r', encoding = 'utf-8', errors = 'ignore').read()
77    except UnicodeDecodeError as ude:
78        print('error: reading: %s: %s' % (name, ude))
79        sys.exit(1)
80    return contents
81
82def write_file(name, contents):
83    path = os.path.dirname(name)
84    if not os.path.exists(path):
85        try:
86            os.makedirs(path)
87        except OSError as oe:
88            print('error: cannot create directory: %s: %s' % (dst_path, oe))
89            sys.exit(1)
90    try:
91        codecs.open(name, mode = 'w',  encoding = 'utf-8', errors = 'ignore').write(contents)
92    except UnicodeDecodeError as ude:
93        print('error: write: %s: %s' % (name, ude))
94        sys.exit(1)
95
96#
97# A builder error.
98#
99class error(Exception):
100    """Base class for exceptions."""
101    def __init__(self, msg):
102        self.msg = 'error: %s' % (msg)
103    def set_output(self, msg):
104        self.msg = msg
105    def __str__(self):
106        return self.msg
107
108#
109# This stuff needs to move to libbsd.py.
110#
111def common_flags():
112    return ['-O2',
113            '-g',
114            '-fno-strict-aliasing',
115            '-ffreestanding',
116            '-fno-common']
117
118def common_warnings():
119    return ['-Wall',
120            '-Wno-format']
121
122def common_no_warnings():
123    return ['-w']
124
125def includes():
126    return ['-Irtemsbsd/include',
127            '-Ifreebsd/sys',
128            '-Ifreebsd/sys/contrib/altq',
129            '-Ifreebsd/sys/contrib/pf',
130            '-Ifreebsd/include',
131            '-Ifreebsd/lib/libc/include',
132            '-Ifreebsd/lib/libc/isc/include',
133            '-Ifreebsd/lib/libc/resolv',
134            '-Ifreebsd/lib/libutil',
135            '-Ifreebsd/lib/libkvm',
136            '-Ifreebsd/lib/libmemstat',
137            '-Ifreebsd/lib/libipsec',
138            '-Ifreebsd/contrib/libpcap',
139            '-Irtemsbsd/sys',
140            '-ImDNSResponder/mDNSCore',
141            '-ImDNSResponder/mDNSShared',
142            '-ImDNSResponder/mDNSPosix',
143            '-Itestsuite/include']
144
145def cpu_includes():
146    return ['-Irtemsbsd/@CPU@/include',
147            '-Ifreebsd/sys/@CPU@/include']
148
149def cflags():
150    return ['-std=gnu11']
151
152def cxxflags():
153    return ['-std=gnu++11']
154
155def header_paths():
156    #         local path                      wildcard             dest path
157    return [('rtemsbsd/include',              '*.h',               ''),
158            ('rtemsbsd/mghttpd',              'mongoose.h',        'mghttpd'),
159            ('freebsd/include',               '*.h',               ''),
160            ('freebsd/sys/contrib/altq/altq', '*.h',               'altq'),
161            ('freebsd/sys/bsm',               '*.h',               'bsm'),
162            ('freebsd/sys/cam',               '*.h',               'cam'),
163            ('freebsd/sys/net',               '*.h',               'net'),
164            ('freebsd/sys/net80211',          '*.h',               'net80211'),
165            ('freebsd/sys/netatalk',          '*.h',               'netatalk'),
166            ('freebsd/sys/netinet',           '*.h',               'netinet'),
167            ('freebsd/sys/netinet6',          '*.h',               'netinet6'),
168            ('freebsd/sys/netipsec',          '*.h',               'netipsec'),
169            ('freebsd/sys/rpc',               '*.h',               'rpc'),
170            ('freebsd/sys/sys',               '*.h',               'sys'),
171            ('freebsd/sys/vm',                '*.h',               'vm'),
172            ('freebsd/sys/dev/mii',           '*.h',               'dev/mii'),
173            ('mDNSResponder/mDNSCore',        'mDNSDebug.h',       ''),
174            ('mDNSResponder/mDNSCore',        'mDNSEmbeddedAPI.h', ''),
175            ('mDNSResponder/mDNSShared',      'dns_sd.h',          ''),
176            ('mDNSResponder/mDNSPosix',       'mDNSPosix.h',       '')]
177
178# Move target dependent files under a machine directory
179def mapCPUDependentPath(path):
180  return path.replace("include/", "include/machine/")
181
182def fixIncludes(data):
183    data = re.sub('#include <sys/lock.h>',     '#include <rtems/bsd/sys/lock.h>', data)
184    data = re.sub('#include <sys/time.h>',     '#include <rtems/bsd/sys/time.h>', data)
185    data = re.sub('#include <sys/cpuset.h>',   '#include <rtems/bsd/sys/cpuset.h>', data)
186    data = re.sub('#include <sys/errno.h>',    '#include <rtems/bsd/sys/errno.h>', data)
187    data = re.sub('#include <sys/param.h>',    '#include <rtems/bsd/sys/param.h>', data)
188    data = re.sub('#include <sys/types.h>',    '#include <rtems/bsd/sys/types.h>', data)
189    data = re.sub('#include <sys/resource.h>', '#include <rtems/bsd/sys/resource.h>', data)
190    data = re.sub('#include <sys/unistd.h>',   '#include <rtems/bsd/sys/unistd.h>', data)
191    data = re.sub('#include <sys/_types.h>',   '#include <rtems/bsd/sys/_types.h>', data)
192    return data
193
194# revert fixing the include paths inside a C or .h file
195def revertFixIncludes(data):
196    data = re.sub('#include <rtems/bsd/',  '#include <', data)
197    data = re.sub('#include <util.h>',     '#include <rtems/bsd/util.h>', data)
198    data = re.sub('#include <bsd.h>',      '#include <rtems/bsd/bsd.h>', data)
199    data = re.sub('#include <zerocopy.h>', '#include <rtems/bsd/zerocopy.h>', data)
200    return data
201
202# fix include paths inside a C or .h file
203def fixLocalIncludes(data):
204    data = re.sub('#include "opt_([^"]*)"',    '#include <rtems/bsd/local/opt_\\1>', data)
205    data = re.sub('#include "([^"]*)_if.h"',   '#include <rtems/bsd/local/\\1_if.h>', data)
206    data = re.sub('#include "miidevs([^"]*)"', '#include <rtems/bsd/local/miidevs\\1>', data)
207    data = re.sub('#include "usbdevs([^"]*)"', '#include <rtems/bsd/local/usbdevs\\1>', data)
208    return data
209
210# revert fixing the include paths inside a C or .h file
211def revertFixLocalIncludes(data):
212    data = re.sub('#include <rtems/bsd/local/([^>]*)>', '#include "\\1"', data)
213    return data
214
215def assertHeaderFile(path):
216    if path[-2] != '.' or path[-1] != 'h':
217        print("*** " + path + " does not end in .h")
218        print("*** Move it to a C source file list")
219        sys.exit(2)
220
221def assertSourceFile(path):
222    if path[-2] != '.' or (path[-1] != 'c' and path[-1] != 'S'):
223        print("*** " + path + " does not end in .c")
224        print("*** Move it to a header file list")
225        sys.exit(2)
226
227#
228# Converters provide a way to alter the various types of code. The conversion
229# process filters a file as it is copies from the source path to the
230# destination path. Specialised versions are provided for different types of
231# source.
232#
233class Converter(object):
234
235    def convert(self, src, dst, has_source = True, source_filter = None, src_contents = None):
236
237        global filesProcessed, filesProcessedCount
238
239        if verbose(verboseDebug):
240            print("convert: filter:%s: %s -> %s" % \
241                  (['yes', 'no'][source_filter is None], src, dst))
242
243        #
244        # If there is no source raise an error if we expect source else print a
245        # warning and do not try and convert.
246        #
247        if src_contents is None:
248            if not os.path.exists(src):
249                if has_source:
250                    raise error('source not found: %s' % (src))
251                else:
252                    print('warning: no source: %s' % (src))
253                    return
254
255            #
256            # Files read as a single string if not passed in.
257            #
258            src_contents = read_file(src)
259
260        if os.path.exists(dst):
261            dst_contents = read_file(dst)
262        else:
263            print('warning: no destination: %s' % (dst))
264            dst_contents = ''
265
266        #
267        # Filter the source.
268        #
269        if source_filter is not None:
270            src_contents = source_filter(src_contents)
271
272        #
273        # Split into a list of lines.
274        #
275        src_lines = src_contents.split(os.linesep)
276        dst_lines = dst_contents.split(os.linesep)
277
278        if verbose(verboseDebug):
279            print('Unified diff: %s (lines:%d)' % (src, len(src_lines)))
280
281        #
282        # Diff, note there is no line termination on each string.  Expand the
283        # generator to list because the generator is not reusable.
284        #
285        diff = list(difflib.unified_diff(dst_lines,
286                                         src_lines,
287                                         fromfile = src,
288                                         tofile = dst,
289                                         n = 5,
290                                         lineterm = ''))
291
292        #
293        # The diff list is empty if the files are the same.
294        #
295        if len(diff) > 0:
296
297            if verbose(verboseDebug):
298                print('Unified diff length: %d' % len(diff))
299
300            filesProcessed += [dst]
301            filesProcessedCount += 1
302            if isDiffMode == False:
303                if verbose(verboseDetail):
304                    print("UPDATE: %s -> %s" % (src, dst))
305                if isDryRun == False:
306                    write_file(dst, src_contents)
307            else:
308                print("diff -u %s %s" % (src, dst))
309                for l in diff:
310                    print(l)
311
312class NoConverter(Converter):
313    def convert(self, src, dst, has_source = True, source_filter = None):
314        return '/* EMPTY */\n'
315
316class FromFreeBSDToRTEMSHeaderConverter(Converter):
317    def source_filter(self, data):
318        data = fixLocalIncludes(data)
319        data = fixIncludes(data)
320        return data
321
322    def convert(self, src, dst):
323        sconverter = super(FromFreeBSDToRTEMSHeaderConverter, self)
324        sconverter.convert(src, dst, source_filter = self.source_filter)
325
326class FromFreeBSDToRTEMSUserSpaceHeaderConverter(Converter):
327    def source_filter(self, data):
328        data = fixIncludes(data)
329        return data
330
331    def convert(self, src, dst):
332        sconverter = super(FromFreeBSDToRTEMSUserSpaceHeaderConverter, self)
333        sconverter.convert(src, dst, source_filter = self.source_filter)
334
335class FromFreeBSDToRTEMSSourceConverter(Converter):
336    def source_filter(self, data):
337        data = fixLocalIncludes(data)
338        data = fixIncludes(data)
339        data = '#include <machine/rtems-bsd-kernel-space.h>\n\n' + data
340        return data
341
342    def convert(self, src, dst):
343        sconverter = super(FromFreeBSDToRTEMSSourceConverter, self)
344        sconverter.convert(src, dst, source_filter = self.source_filter)
345
346class FromFreeBSDToRTEMSUserSpaceSourceConverter(Converter):
347    def source_filter(self, data):
348        data = fixIncludes(data)
349        data = '#include <machine/rtems-bsd-user-space.h>\n\n' + data
350        return data
351
352    def convert(self, src, dst):
353        sconverter = super(FromFreeBSDToRTEMSUserSpaceSourceConverter, self)
354        sconverter.convert(src, dst, source_filter = self.source_filter)
355
356class FromRTEMSToFreeBSDHeaderConverter(Converter):
357    def source_filter(self, data):
358        data = revertFixLocalIncludes(data)
359        data = revertFixIncludes(data)
360        return data
361
362    def convert(self, src, dst):
363        sconverter = super(FromRTEMSToFreeBSDHeaderConverter, self)
364        sconverter.convert(src, dst, has_source = False,  source_filter = self.source_filter)
365
366class FromRTEMSToFreeBSDSourceConverter(Converter):
367    def source_filter(self, data):
368        data = re.sub('#include <machine/rtems-bsd-kernel-space.h>\n\n', '', data)
369        data = re.sub('#include <machine/rtems-bsd-user-space.h>\n\n', '', data)
370        return data
371
372    def convert(self, src, dst):
373        sconverter = super(FromRTEMSToFreeBSDSourceConverter, self)
374        sconverter.convert(src, dst, has_source = False, source_filter = self.source_filter)
375
376#
377# Compose a path based for the various parts of the source tree.
378#
379class PathComposer(object):
380    def composeFreeBSDPath(self, path):
381        return path
382
383    def composeRTEMSPath(self, path, prefix):
384        return os.path.join(prefix, path)
385
386class FreeBSDPathComposer(PathComposer):
387    def composeFreeBSDPath(self, path):
388        return os.path.join(FreeBSD_DIR, path)
389
390    def composeRTEMSPath(self, path, prefix):
391        return os.path.join(prefix, 'freebsd', path)
392
393class RTEMSPathComposer(PathComposer):
394    def composeFreeBSDPath(self, path):
395        return path
396
397    def composeRTEMSPath(self, path, prefix):
398        return os.path.join(prefix, 'rtemsbsd', path)
399
400class CPUDependentPathComposer(FreeBSDPathComposer):
401    def composeRTEMSPath(self, path, prefix):
402        path = super(CPUDependentPathComposer, self).composeRTEMSPath(path, prefix)
403        path = mapCPUDependentPath(path)
404        return path
405
406class TargetSourceCPUDependentPathComposer(CPUDependentPathComposer):
407    def __init__(self, targetCPU, sourceCPU):
408        self.targetCPU = targetCPU
409        self.sourceCPU = sourceCPU
410
411    def composeRTEMSPath(self, path, prefix):
412        path = super(TargetSourceCPUDependentPathComposer, self).composeRTEMSPath(path, prefix)
413        path = path.replace(self.sourceCPU, self.targetCPU)
414        return path
415
416class BuildSystemFragmentComposer(object):
417    def __init__(self, includes = None):
418        if type(includes) is not list:
419            self.includes = [includes]
420        else:
421            self.includes = includes
422
423    def compose(self, path):
424        return ''
425
426#
427# File - a file in the source we move backwards and forwards.
428#
429class File(object):
430    def __init__(self, path, pathComposer,
431                 forwardConverter, reverseConverter, buildSystemComposer):
432        if verbose(verboseMoreDetail):
433            print("FILE: %-50s F:%-45s R:%-45s" % \
434                  (path,
435                   forwardConverter.__class__.__name__,
436                   reverseConverter.__class__.__name__))
437        self.path = path
438        self.pathComposer = pathComposer
439        self.freebsdPath = self.pathComposer.composeFreeBSDPath(self.path)
440        self.rtemsPath = self.pathComposer.composeRTEMSPath(self.path, RTEMS_DIR)
441        self.forwardConverter = forwardConverter
442        self.reverseConverter = reverseConverter
443        self.buildSystemComposer = buildSystemComposer
444
445    def processSource(self, forward):
446        if forward:
447            if verbose(verboseDetail):
448                print("process source: %s => %s" % (self.freebsdPath, self.rtemsPath))
449            self.forwardConverter.convert(self.freebsdPath, self.rtemsPath)
450        else:
451            if verbose(verboseDetail):
452                print("process source: %s => %s converter:%s" % \
453                      (self.rtemsPath, self.freebsdPath, self.reverseConverter.__class__.__name__))
454            self.reverseConverter.convert(self.rtemsPath, self.freebsdPath)
455
456    def getFragment(self):
457        return self.buildSystemComposer.compose(self.pathComposer.composeRTEMSPath(self.path, ''))
458
459#
460# Module - logical group of related files we can perform actions on
461#
462class Module:
463    def __init__(self, name):
464        self.name = name
465        self.conditionalOn = "none"
466        self.files = []
467        self.cpuDependentSourceFiles = {}
468        self.dependencies = []
469
470    def initCPUDependencies(self, cpu):
471        if cpu not in self.cpuDependentSourceFiles:
472            self.cpuDependentSourceFiles[cpu] = []
473
474    def processSource(self, direction):
475        if verbose(verboseDetail):
476            print("process module: %s" % (self.name))
477        for f in self.files:
478            f.processSource(direction)
479        for cpu, files in self.cpuDependentSourceFiles.items():
480            for f in files:
481                f.processSource(direction)
482
483    def addFiles(self, newFiles, buildSystemComposer = BuildSystemFragmentComposer()):
484        files = []
485        for newFile in newFiles:
486            assertFile(newFile)
487            files += [File(newFile, composers, buildSystemComposer)]
488        return files
489
490    def addFile(self, f):
491        self.files += [f]
492
493    def addFiles(self, newFiles,
494                 pathComposer, fromFreeBSDToRTEMSConverter, fromRTEMSToFreeBSDConverter,
495                 assertFile, buildSystemComposer = BuildSystemFragmentComposer()):
496        files = []
497        for newFile in newFiles:
498            assertFile(newFile)
499            files += [File(newFile, pathComposer, fromFreeBSDToRTEMSConverter,
500                           fromRTEMSToFreeBSDConverter, buildSystemComposer)]
501        return files
502
503    def addKernelSpaceHeaderFiles(self, files):
504        self.files += self.addFiles(files,
505                                    FreeBSDPathComposer(), FromFreeBSDToRTEMSHeaderConverter(),
506                                    FromRTEMSToFreeBSDHeaderConverter(), assertHeaderFile)
507
508    def addUserSpaceHeaderFiles(self, files):
509        self.files += self.addFiles(files,
510                                    FreeBSDPathComposer(), FromFreeBSDToRTEMSUserSpaceHeaderConverter(),
511                                    FromRTEMSToFreeBSDHeaderConverter(), assertHeaderFile)
512
513    def addRTEMSHeaderFiles(self, files):
514        self.files += self.addFiles(files, RTEMSPathComposer(),
515                                    NoConverter(), NoConverter(), assertHeaderFile)
516
517    def addCPUDependentHeaderFiles(self, files):
518        self.files += self.addFiles(files,
519                                    CPUDependentPathComposer(), FromFreeBSDToRTEMSHeaderConverter(),
520                                    FromRTEMSToFreeBSDHeaderConverter(), assertHeaderFile)
521
522    def addTargetSourceCPUDependentHeaderFiles(self, targetCPUs, sourceCPU, files):
523        for cpu in targetCPUs:
524            self.files += self.addFiles(files,
525                                        TargetSourceCPUDependentPathComposer(cpu, sourceCPU),
526                                        FromFreeBSDToRTEMSHeaderConverter(),
527                                        NoConverter(), assertHeaderFile)
528
529    def addSourceFiles(self, files, sourceFileFragmentComposer):
530        self.files += self.addFiles(files,
531                                    PathComposer(), NoConverter(), NoConverter(), assertSourceFile,
532                                    sourceFileFragmentComposer)
533
534    def addKernelSpaceSourceFiles(self, files, sourceFileFragmentComposer):
535        self.files += self.addFiles(files,
536                                    FreeBSDPathComposer(), FromFreeBSDToRTEMSSourceConverter(),
537                                    FromRTEMSToFreeBSDSourceConverter(), assertSourceFile,
538                                    sourceFileFragmentComposer)
539
540    def addUserSpaceSourceFiles(self, files, sourceFileFragmentComposer):
541        self.files += self.addFiles(files,
542                                    FreeBSDPathComposer(),
543                                    FromFreeBSDToRTEMSUserSpaceSourceConverter(),
544                                    FromRTEMSToFreeBSDSourceConverter(), assertSourceFile,
545                                    sourceFileFragmentComposer)
546
547    def addRTEMSSourceFiles(self, files, sourceFileFragmentComposer):
548        self.files += self.addFiles(files,
549                                    RTEMSPathComposer(), NoConverter(), NoConverter(),
550                                    assertSourceFile, sourceFileFragmentComposer)
551
552    def addCPUDependentSourceFiles(self, cpus, files, sourceFileFragmentComposer):
553        for cpu in cpus:
554            self.initCPUDependencies(cpu)
555            self.cpuDependentSourceFiles[cpu] += \
556                self.addFiles(files,
557                              CPUDependentPathComposer(), FromFreeBSDToRTEMSSourceConverter(),
558                              FromRTEMSToFreeBSDSourceConverter(), assertSourceFile,
559                              sourceFileFragmentComposer)
560
561    def addTest(self, testFragementComposer):
562        self.files += [File(testFragementComposer.testName,
563                            PathComposer(), NoConverter(), NoConverter(),
564                            testFragementComposer)]
565
566    def addDependency(self, dep):
567        self.dependencies += [dep]
568
569#
570# Manager - a collection of modules.
571#
572class ModuleManager:
573    def __init__(self):
574        self.modules = {}
575        self.generator = {}
576        self.setGenerators()
577
578    def __getitem__(self, key):
579        if key not in self.modules:
580            raise KeyError('module %s not found' % (key))
581        return self.modules[key]
582
583    def getModules(self):
584        return sorted(self.modules.keys())
585
586    def addModule(self, module):
587        self.modules[module.name] = module
588
589    def processSource(self, direction):
590        if verbose(verboseDetail):
591            print("process modules:")
592        for m in sorted(self.modules):
593            self.modules[m].processSource(direction)
Note: See TracBrowser for help on using the repository browser.