source: rtems-libbsd/builder.py @ 3d1e767

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 3d1e767 was 3d1e767, checked in by Sebastian Huber <sebastian.huber@…>, on 04/27/16 at 08:25:22

Directly use <sys/types.h> provided by Newlib

  • Property mode set to 100755
File size: 22.1 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 readFile(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 writeFile(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' % (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 commonFlags():
112    return ['-O2',
113            '-g',
114            '-fno-strict-aliasing',
115            '-ffreestanding',
116            '-fno-common']
117
118def commonWarnings():
119    return ['-Wall',
120            '-Wno-format']
121
122def commonNoWarnings():
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 cpuIncludes():
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 headerPaths():
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/cpuset.h>',   '#include <rtems/bsd/sys/cpuset.h>', data)
185    data = re.sub('#include <sys/errno.h>',    '#include <rtems/bsd/sys/errno.h>', data)
186    data = re.sub('#include <sys/param.h>',    '#include <rtems/bsd/sys/param.h>', data)
187    data = re.sub('#include <sys/resource.h>', '#include <rtems/bsd/sys/resource.h>', data)
188    data = re.sub('#include <sys/unistd.h>',   '#include <rtems/bsd/sys/unistd.h>', data)
189    data = re.sub('#include <sys/_types.h>',   '#include <rtems/bsd/sys/_types.h>', data)
190    return data
191
192# revert fixing the include paths inside a C or .h file
193def revertFixIncludes(data):
194    data = re.sub('#include <rtems/bsd/',  '#include <', data)
195    data = re.sub('#include <util.h>',     '#include <rtems/bsd/util.h>', data)
196    data = re.sub('#include <bsd.h>',      '#include <rtems/bsd/bsd.h>', data)
197    data = re.sub('#include <zerocopy.h>', '#include <rtems/bsd/zerocopy.h>', data)
198    return data
199
200# fix include paths inside a C or .h file
201def fixLocalIncludes(data):
202    data = re.sub('#include "opt_([^"]*)"',    '#include <rtems/bsd/local/opt_\\1>', data)
203    data = re.sub('#include "([^"]*)_if.h"',   '#include <rtems/bsd/local/\\1_if.h>', data)
204    data = re.sub('#include "miidevs([^"]*)"', '#include <rtems/bsd/local/miidevs\\1>', data)
205    data = re.sub('#include "usbdevs([^"]*)"', '#include <rtems/bsd/local/usbdevs\\1>', data)
206    return data
207
208# revert fixing the include paths inside a C or .h file
209def revertFixLocalIncludes(data):
210    data = re.sub('#include <rtems/bsd/local/([^>]*)>', '#include "\\1"', data)
211    return data
212
213def assertHeaderFile(path):
214    if path[-2] != '.' or path[-1] != 'h':
215        print("*** " + path + " does not end in .h")
216        print("*** Move it to a C source file list")
217        sys.exit(2)
218
219def assertSourceFile(path):
220    if path[-2] != '.' or (path[-1] != 'c' and path[-1] != 'S'):
221        print("*** " + path + " does not end in .c")
222        print("*** Move it to a header file list")
223        sys.exit(2)
224
225#
226# Converters provide a way to alter the various types of code. The conversion
227# process filters a file as it is copies from the source path to the
228# destination path. Specialised versions are provided for different types of
229# source.
230#
231class Converter(object):
232
233    def convert(self, src, dst, hasSource = True, sourceFilter = None, srcContents = None):
234
235        global filesProcessed, filesProcessedCount
236
237        if verbose(verboseDebug):
238            print("convert: filter:%s: %s -> %s" % \
239                  (['yes', 'no'][sourceFilter is None], src, dst))
240
241        #
242        # If there is no source raise an error if we expect source else print a
243        # warning and do not try and convert.
244        #
245        if srcContents is None:
246            if not os.path.exists(src):
247                if hasSource:
248                    raise error('source not found: %s' % (src))
249                else:
250                    print('warning: no source: %s' % (src))
251                    return
252
253            #
254            # Files read as a single string if not passed in.
255            #
256            srcContents = readFile(src)
257
258        if os.path.exists(dst):
259            dstContents = readFile(dst)
260        else:
261            print('warning: no destination: %s' % (dst))
262            dstContents = ''
263
264        #
265        # Filter the source.
266        #
267        if sourceFilter is not None:
268            srcContents = sourceFilter(srcContents)
269
270        #
271        # Split into a list of lines.
272        #
273        srcLines = srcContents.split(os.linesep)
274        dstLines = dstContents.split(os.linesep)
275
276        if verbose(verboseDebug):
277            print('Unified diff: %s (lines:%d)' % (src, len(srcLines)))
278
279        #
280        # Diff, note there is no line termination on each string.  Expand the
281        # generator to list because the generator is not reusable.
282        #
283        diff = list(difflib.unified_diff(dstLines,
284                                         srcLines,
285                                         fromfile = src,
286                                         tofile = dst,
287                                         n = 5,
288                                         lineterm = ''))
289
290        #
291        # The diff list is empty if the files are the same.
292        #
293        if len(diff) > 0:
294
295            if verbose(verboseDebug):
296                print('Unified diff length: %d' % len(diff))
297
298            filesProcessed += [dst]
299            filesProcessedCount += 1
300            if isDiffMode == False:
301                if verbose(verboseDetail):
302                    print("UPDATE: %s -> %s" % (src, dst))
303                if isDryRun == False:
304                    writeFile(dst, srcContents)
305            else:
306                print("diff -u %s %s" % (src, dst))
307                for l in diff:
308                    print(l)
309
310class NoConverter(Converter):
311    def convert(self, src, dst, hasSource = True, sourceFilter = None):
312        return '/* EMPTY */\n'
313
314class FromFreeBSDToRTEMSHeaderConverter(Converter):
315    def sourceFilter(self, data):
316        data = fixLocalIncludes(data)
317        data = fixIncludes(data)
318        return data
319
320    def convert(self, src, dst):
321        sconverter = super(FromFreeBSDToRTEMSHeaderConverter, self)
322        sconverter.convert(src, dst, sourceFilter = self.sourceFilter)
323
324class FromFreeBSDToRTEMSUserSpaceHeaderConverter(Converter):
325    def sourceFilter(self, data):
326        data = fixIncludes(data)
327        return data
328
329    def convert(self, src, dst):
330        sconverter = super(FromFreeBSDToRTEMSUserSpaceHeaderConverter, self)
331        sconverter.convert(src, dst, sourceFilter = self.sourceFilter)
332
333class FromFreeBSDToRTEMSSourceConverter(Converter):
334    def sourceFilter(self, data):
335        data = fixLocalIncludes(data)
336        data = fixIncludes(data)
337        data = '#include <machine/rtems-bsd-kernel-space.h>\n\n' + data
338        return data
339
340    def convert(self, src, dst):
341        sconverter = super(FromFreeBSDToRTEMSSourceConverter, self)
342        sconverter.convert(src, dst, sourceFilter = self.sourceFilter)
343
344class FromFreeBSDToRTEMSUserSpaceSourceConverter(Converter):
345    def sourceFilter(self, data):
346        data = fixIncludes(data)
347        data = '#include <machine/rtems-bsd-user-space.h>\n\n' + data
348        return data
349
350    def convert(self, src, dst):
351        sconverter = super(FromFreeBSDToRTEMSUserSpaceSourceConverter, self)
352        sconverter.convert(src, dst, sourceFilter = self.sourceFilter)
353
354class FromRTEMSToFreeBSDHeaderConverter(Converter):
355    def sourceFilter(self, data):
356        data = revertFixLocalIncludes(data)
357        data = revertFixIncludes(data)
358        return data
359
360    def convert(self, src, dst):
361        sconverter = super(FromRTEMSToFreeBSDHeaderConverter, self)
362        sconverter.convert(src, dst, hasSource = False,  sourceFilter = self.sourceFilter)
363
364class FromRTEMSToFreeBSDSourceConverter(Converter):
365    def sourceFilter(self, data):
366        data = re.sub('#include <machine/rtems-bsd-kernel-space.h>\n\n', '', data)
367        data = re.sub('#include <machine/rtems-bsd-user-space.h>\n\n', '', data)
368        return data
369
370    def convert(self, src, dst):
371        sconverter = super(FromRTEMSToFreeBSDSourceConverter, self)
372        sconverter.convert(src, dst, hasSource = False, sourceFilter = self.sourceFilter)
373
374#
375# Compose a path based for the various parts of the source tree.
376#
377class PathComposer(object):
378    def composeFreeBSDPath(self, path):
379        return path
380
381    def composeRTEMSPath(self, path, prefix):
382        return os.path.join(prefix, path)
383
384class FreeBSDPathComposer(PathComposer):
385    def composeFreeBSDPath(self, path):
386        return os.path.join(FreeBSD_DIR, path)
387
388    def composeRTEMSPath(self, path, prefix):
389        return os.path.join(prefix, 'freebsd', path)
390
391class RTEMSPathComposer(PathComposer):
392    def composeFreeBSDPath(self, path):
393        return path
394
395    def composeRTEMSPath(self, path, prefix):
396        return os.path.join(prefix, 'rtemsbsd', path)
397
398class CPUDependentPathComposer(FreeBSDPathComposer):
399    def composeRTEMSPath(self, path, prefix):
400        path = super(CPUDependentPathComposer, self).composeRTEMSPath(path, prefix)
401        path = mapCPUDependentPath(path)
402        return path
403
404class TargetSourceCPUDependentPathComposer(CPUDependentPathComposer):
405    def __init__(self, targetCPU, sourceCPU):
406        self.targetCPU = targetCPU
407        self.sourceCPU = sourceCPU
408
409    def composeRTEMSPath(self, path, prefix):
410        path = super(TargetSourceCPUDependentPathComposer, self).composeRTEMSPath(path, prefix)
411        path = path.replace(self.sourceCPU, self.targetCPU)
412        return path
413
414class BuildSystemFragmentComposer(object):
415    def __init__(self, includes = None):
416        if type(includes) is not list:
417            self.includes = [includes]
418        else:
419            self.includes = includes
420
421    def compose(self, path):
422        return ''
423
424#
425# File - a file in the source we move backwards and forwards.
426#
427class File(object):
428    def __init__(self, path, pathComposer,
429                 forwardConverter, reverseConverter, buildSystemComposer):
430        if verbose(verboseMoreDetail):
431            print("FILE: %-50s F:%-45s R:%-45s" % \
432                  (path,
433                   forwardConverter.__class__.__name__,
434                   reverseConverter.__class__.__name__))
435        self.path = path
436        self.pathComposer = pathComposer
437        self.freebsdPath = self.pathComposer.composeFreeBSDPath(self.path)
438        self.rtemsPath = self.pathComposer.composeRTEMSPath(self.path, RTEMS_DIR)
439        self.forwardConverter = forwardConverter
440        self.reverseConverter = reverseConverter
441        self.buildSystemComposer = buildSystemComposer
442
443    def processSource(self, forward):
444        if forward:
445            if verbose(verboseDetail):
446                print("process source: %s => %s" % (self.freebsdPath, self.rtemsPath))
447            self.forwardConverter.convert(self.freebsdPath, self.rtemsPath)
448        else:
449            if verbose(verboseDetail):
450                print("process source: %s => %s converter:%s" % \
451                      (self.rtemsPath, self.freebsdPath, self.reverseConverter.__class__.__name__))
452            self.reverseConverter.convert(self.rtemsPath, self.freebsdPath)
453
454    def getFragment(self):
455        return self.buildSystemComposer.compose(self.pathComposer.composeRTEMSPath(self.path, ''))
456
457#
458# Module - logical group of related files we can perform actions on
459#
460class Module:
461    def __init__(self, name):
462        self.name = name
463        self.conditionalOn = "none"
464        self.files = []
465        self.cpuDependentSourceFiles = {}
466        self.dependencies = []
467
468    def initCPUDependencies(self, cpu):
469        if cpu not in self.cpuDependentSourceFiles:
470            self.cpuDependentSourceFiles[cpu] = []
471
472    def processSource(self, direction):
473        if verbose(verboseDetail):
474            print("process module: %s" % (self.name))
475        for f in self.files:
476            f.processSource(direction)
477        for cpu, files in self.cpuDependentSourceFiles.items():
478            for f in files:
479                f.processSource(direction)
480
481    def addFiles(self, newFiles, buildSystemComposer = BuildSystemFragmentComposer()):
482        files = []
483        for newFile in newFiles:
484            assertFile(newFile)
485            files += [File(newFile, composers, buildSystemComposer)]
486        return files
487
488    def addFile(self, f):
489        self.files += [f]
490
491    def addFiles(self, newFiles,
492                 pathComposer, fromFreeBSDToRTEMSConverter, fromRTEMSToFreeBSDConverter,
493                 assertFile, buildSystemComposer = BuildSystemFragmentComposer()):
494        files = []
495        for newFile in newFiles:
496            assertFile(newFile)
497            files += [File(newFile, pathComposer, fromFreeBSDToRTEMSConverter,
498                           fromRTEMSToFreeBSDConverter, buildSystemComposer)]
499        return files
500
501    def addKernelSpaceHeaderFiles(self, files):
502        self.files += self.addFiles(files,
503                                    FreeBSDPathComposer(), FromFreeBSDToRTEMSHeaderConverter(),
504                                    FromRTEMSToFreeBSDHeaderConverter(), assertHeaderFile)
505
506    def addUserSpaceHeaderFiles(self, files):
507        self.files += self.addFiles(files,
508                                    FreeBSDPathComposer(), FromFreeBSDToRTEMSUserSpaceHeaderConverter(),
509                                    FromRTEMSToFreeBSDHeaderConverter(), assertHeaderFile)
510
511    def addRTEMSHeaderFiles(self, files):
512        self.files += self.addFiles(files, RTEMSPathComposer(),
513                                    NoConverter(), NoConverter(), assertHeaderFile)
514
515    def addCPUDependentHeaderFiles(self, files):
516        self.files += self.addFiles(files,
517                                    CPUDependentPathComposer(), FromFreeBSDToRTEMSHeaderConverter(),
518                                    FromRTEMSToFreeBSDHeaderConverter(), assertHeaderFile)
519
520    def addTargetSourceCPUDependentHeaderFiles(self, targetCPUs, sourceCPU, files):
521        for cpu in targetCPUs:
522            self.files += self.addFiles(files,
523                                        TargetSourceCPUDependentPathComposer(cpu, sourceCPU),
524                                        FromFreeBSDToRTEMSHeaderConverter(),
525                                        NoConverter(), assertHeaderFile)
526
527    def addSourceFiles(self, files, sourceFileFragmentComposer):
528        self.files += self.addFiles(files,
529                                    PathComposer(), NoConverter(), NoConverter(), assertSourceFile,
530                                    sourceFileFragmentComposer)
531
532    def addKernelSpaceSourceFiles(self, files, sourceFileFragmentComposer):
533        self.files += self.addFiles(files,
534                                    FreeBSDPathComposer(), FromFreeBSDToRTEMSSourceConverter(),
535                                    FromRTEMSToFreeBSDSourceConverter(), assertSourceFile,
536                                    sourceFileFragmentComposer)
537
538    def addUserSpaceSourceFiles(self, files, sourceFileFragmentComposer):
539        self.files += self.addFiles(files,
540                                    FreeBSDPathComposer(),
541                                    FromFreeBSDToRTEMSUserSpaceSourceConverter(),
542                                    FromRTEMSToFreeBSDSourceConverter(), assertSourceFile,
543                                    sourceFileFragmentComposer)
544
545    def addRTEMSSourceFiles(self, files, sourceFileFragmentComposer):
546        self.files += self.addFiles(files,
547                                    RTEMSPathComposer(), NoConverter(), NoConverter(),
548                                    assertSourceFile, sourceFileFragmentComposer)
549
550    def addCPUDependentSourceFiles(self, cpus, files, sourceFileFragmentComposer):
551        for cpu in cpus:
552            self.initCPUDependencies(cpu)
553            self.cpuDependentSourceFiles[cpu] += \
554                self.addFiles(files,
555                              CPUDependentPathComposer(), FromFreeBSDToRTEMSSourceConverter(),
556                              FromRTEMSToFreeBSDSourceConverter(), assertSourceFile,
557                              sourceFileFragmentComposer)
558
559    def addTest(self, testFragementComposer):
560        self.files += [File(testFragementComposer.testName,
561                            PathComposer(), NoConverter(), NoConverter(),
562                            testFragementComposer)]
563
564    def addDependency(self, dep):
565        self.dependencies += [dep]
566
567#
568# Manager - a collection of modules.
569#
570class ModuleManager:
571    def __init__(self):
572        self.modules = {}
573        self.generator = {}
574        self.setGenerators()
575
576    def __getitem__(self, key):
577        if key not in self.modules:
578            raise KeyError('module %s not found' % (key))
579        return self.modules[key]
580
581    def getModules(self):
582        return sorted(self.modules.keys())
583
584    def addModule(self, module):
585        self.modules[module.name] = module
586
587    def processSource(self, direction):
588        if verbose(verboseDetail):
589            print("process modules:")
590        for m in sorted(self.modules):
591            self.modules[m].processSource(direction)
Note: See TracBrowser for help on using the repository browser.