source: rtems-libbsd/builder.py @ 238e275

5-freebsd-12
Last change on this file since 238e275 was 238e275, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 6, 2017 at 1:09:42 PM

scripts: Support CPU-dependent RTEMS source files

  • Property mode set to 100755
File size: 32.2 KB
Line 
1#
2#  Copyright (c) 2015-2016 Chris Johns <chrisj@rtems.org>. All rights reserved.
3#
4#  Copyright (c) 2009, 2017 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#
51LIBBSD_DIR = "."
52FreeBSD_DIR = "freebsd-org"
53Linux_DIR = "linux-org"
54verboseLevel = 0
55isDryRun = False
56isDiffMode = False
57filesProcessedCount = 0
58filesProcessed = []
59filesTotal = 0
60filesTotalLines = 0
61filesTotalInserts = 0
62filesTotalDeletes = 0
63diffDetails = { }
64
65verboseInfo = 1
66verboseDetail = 2
67verboseMoreDetail = 3
68verboseDebug = 4
69
70def verbose(level = verboseInfo):
71    return verboseLevel >= level
72
73def changedFileSummary(statsReport = False):
74
75    global filesTotal, filesTotalLines, filesTotalInserts, filesTotalDeletes
76
77    if isDiffMode == False:
78        if verbose():
79            print('%d file(s) were changed:' % (filesProcessedCount))
80            for f in sorted(filesProcessed):
81                print(' %s' % (f))
82        else:
83            print('%d file(s) were changed.' % (filesProcessedCount))
84    if statsReport:
85        print('Stats Report:')
86        transparent = filesTotal - len(diffDetails)
87        changes = filesTotalInserts + filesTotalDeletes
88        opacity = (float(changes) / (filesTotalLines + changes)) * 100.0
89        print(' Total File(s):%d  Unchanged:%d (%.1f%%)  Changed:%d' \
90              '   Opacity:%5.1f%% Lines:%d Edits:%d (+):%d (-):%d'  % \
91              (filesTotal, transparent, (float(transparent) / filesTotal) * 100.0, len(diffDetails), \
92               opacity, filesTotalLines, changes, filesTotalInserts, filesTotalDeletes))
93        #
94        # Sort by opacity.
95        #
96        ordered_diffs = sorted(diffDetails.items(), key = lambda diff: diff[1].opacity, reverse = True)
97        for f in ordered_diffs:
98            print(%s' % (diffDetails[f[0]].status()))
99
100def readFile(name):
101    try:
102        contents = codecs.open(name, mode = 'r', encoding = 'utf-8', errors = 'ignore').read()
103    except UnicodeDecodeError as ude:
104        print('error: reading: %s: %s' % (name, ude))
105        sys.exit(1)
106    return contents
107
108def writeFile(name, contents):
109    path = os.path.dirname(name)
110    if not os.path.exists(path):
111        try:
112            os.makedirs(path)
113        except OSError as oe:
114            print('error: cannot create directory: %s: %s' % (path, oe))
115            sys.exit(1)
116    try:
117        codecs.open(name, mode = 'w',  encoding = 'utf-8', errors = 'ignore').write(contents)
118    except UnicodeDecodeError as ude:
119        print('error: write: %s: %s' % (name, ude))
120        sys.exit(1)
121
122#
123# A builder error.
124#
125class error(Exception):
126    """Base class for exceptions."""
127    def __init__(self, msg):
128        self.msg = 'error: %s' % (msg)
129    def set_output(self, msg):
130        self.msg = msg
131    def __str__(self):
132        return self.msg
133
134#
135# Diff Record
136#
137class diffRecord:
138    def __init__(self, src, dst, orig, diff, inserts, deletes):
139        self.src = src
140        self.dst = dst
141        self.orig = orig
142        self.diff = diff
143        self.lines = len(orig)
144        self.inserts = inserts
145        self.deletes = deletes
146        self.changes = inserts + deletes
147        self.opacity = (float(self.changes) / (self.lines + self.changes)) * 100.0
148
149    def __repr__(self):
150        return self.src
151
152    def status(self):
153        return 'opacity:%5.1f%% edits:%4d (+):%-4d (-):%-4d %s' % \
154            (self.opacity, self.changes, self.inserts, self.deletes, self.src)
155
156#
157# This stuff needs to move to libbsd.py.
158#
159def commonFlags():
160    return ['-g',
161            '-fno-strict-aliasing',
162            '-ffreestanding',
163            '-fno-common']
164
165def commonWarnings():
166    return ['-Wall',
167            '-Wno-format',
168            '-Wno-pointer-sign']
169
170def commonNoWarnings():
171    return ['-w']
172
173def includes():
174    return ['-Irtemsbsd/include',
175            '-Ifreebsd/sys',
176            '-Ifreebsd/sys/contrib/pf',
177            '-Ifreebsd/sys/net',
178            '-Ifreebsd/include',
179            '-Ifreebsd/lib',
180            '-Ifreebsd/lib/libbsdstat',
181            '-Ifreebsd/lib/libc/include',
182            '-Ifreebsd/lib/libc/isc/include',
183            '-Ifreebsd/lib/libc/resolv',
184            '-Ifreebsd/lib/libutil',
185            '-Ifreebsd/lib/libkvm',
186            '-Ifreebsd/lib/libmemstat',
187            '-Ifreebsd/lib/libipsec',
188            '-Ifreebsd/contrib/expat/lib',
189            '-Ifreebsd/contrib/libpcap',
190            '-Ifreebsd/contrib/libxo',
191            '-Irtemsbsd/sys',
192            '-ImDNSResponder/mDNSCore',
193            '-ImDNSResponder/mDNSShared',
194            '-ImDNSResponder/mDNSPosix',
195            '-Itestsuite/include']
196
197def buildInclude():
198    """ Returns the path where headers will be copied during build. """
199    return 'build-include'
200
201def cpuIncludes():
202    return ['-Irtemsbsd/@CPU@/include',
203            '-Ifreebsd/sys/@CPU@/include']
204
205def cflags():
206    return []
207
208def cxxflags():
209    return []
210
211def headerPaths():
212    """ Returns a list of information about what header files should be
213    installed.
214
215    The list is also used to find headers with a local path that doesn't match
216    it's dest path. Due to the difference in the path name such files are
217    problematic during the build if they are included using their later
218    installation path (dest path) name. Therefore they are copied into a
219    sub-directory of the build path so that they can be included with their
220    normal installation path. """
221
222    #         local path                      wildcard             dest path
223    return [('rtemsbsd/include',              '**/*.h',            ''),
224            ('rtemsbsd/mghttpd',              'mongoose.h',        'mghttpd'),
225            ('freebsd/include',               '**/*.h',            ''),
226            ('freebsd/sys/bsm',               '**/*.h',            'bsm'),
227            ('freebsd/sys/cam',               '**/*.h',            'cam'),
228            ('freebsd/sys/net',               '**/*.h',            'net'),
229            ('freebsd/sys/net80211',          '**/*.h',            'net80211'),
230            ('freebsd/sys/netinet',           '**/*.h',            'netinet'),
231            ('freebsd/sys/netinet6',          '**/*.h',            'netinet6'),
232            ('freebsd/sys/netipsec',          '**/*.h',            'netipsec'),
233            ('freebsd/contrib/libpcap',       '*.h',               ''),
234            ('freebsd/contrib/libpcap/pcap',  '*.h',               'pcap'),
235            ('freebsd/crypto/openssl',        '*.h',               'openssl'),
236            ('freebsd/crypto/openssl/crypto', '*.h',               'openssl'),
237            ('freebsd/crypto/openssl/ssl',    '(ssl|kssl|ssl2).h', 'openssl'),
238            ('freebsd/crypto/openssl/crypto/aes', 'aes.h',         'openssl'),
239            ('freebsd/crypto/openssl/crypto/err', 'err.h',         'openssl'),
240            ('freebsd/crypto/openssl/crypto/bio', '*.h',           'openssl'),
241            ('freebsd/crypto/openssl/crypto/dsa', '*.h',           'openssl'),
242            ('freebsd/crypto/openssl/ssl',        '*.h',           'openssl'),
243            ('freebsd/crypto/openssl/crypto/bn',  'bn.h',          'openssl'),
244            ('freebsd/crypto/openssl/crypto/x509',  'x509.h',      'openssl'),
245            ('freebsd/crypto/openssl/crypto/cast',  'cast.h',      'openssl'),
246            ('freebsd/crypto/openssl/crypto/lhash', 'lhash.h',     'openssl'),
247            ('freebsd/crypto/openssl/crypto/ecdh',  'ecdh.h',      'openssl'),
248            ('freebsd/crypto/openssl/crypto/ecdsa', 'ecdsa.h',     'openssl'),
249            ('freebsd/crypto/openssl/crypto/idea',  'idea.h',      'openssl'),
250            ('freebsd/crypto/openssl/crypto/mdc2',  'mdc2.h',      'openssl'),
251            ('freebsd/crypto/openssl/crypto/md4',   'md4.h',       'openssl'),
252            ('freebsd/crypto/openssl/crypto/md5',   'md5.h',       'openssl'),
253            ('freebsd/crypto/openssl/crypto/rc2',   'rc2.h',       'openssl'),
254            ('freebsd/crypto/openssl/crypto/rc4',   'rc4.h',       'openssl'),
255            ('freebsd/crypto/openssl/crypto/ripemd','ripemd.h',    'openssl'),
256            ('freebsd/crypto/openssl/crypto/seed',  'seed.h',      'openssl'),
257            ('freebsd/crypto/openssl/crypto/sha',   'sha.h',       'openssl'),
258            ('freebsd/crypto/openssl/crypto/x509v3','x509v3.h',    'openssl'),
259            ('freebsd/crypto/openssl/crypto/x509',  'x509_vfy.h',  'openssl'),
260            ('freebsd/crypto/openssl/crypto/buffer','buffer.h',    'openssl'),
261            ('freebsd/crypto/openssl/crypto/comp',  'comp.h',      'openssl'),
262            ('freebsd/crypto/openssl/crypto/asn1',  'asn1_mac.h',  'openssl'),
263            ('freebsd/crypto/openssl/crypto/pem',  '(pem|pem2).h', 'openssl'),
264            ('freebsd/crypto/openssl/crypto/rsa',   'rsa.h',       'openssl'),
265            ('freebsd/crypto/openssl/crypto/evp',   'evp.h',       'openssl'),
266            ('freebsd/crypto/openssl/crypto/ec',    'ec.h',        'openssl'),
267            ('freebsd/crypto/openssl/crypto/engine', 'engine.h',   'openssl'),
268            ('freebsd/crypto/openssl/crypto/pkcs7', 'pkcs7.h',     'openssl'),
269            ('freebsd/crypto/openssl/crypto/hmac',  'hmac.h',      'openssl'),
270            ('freebsd/crypto/openssl/crypto/pqueue', 'pqueue.h',   'openssl'),
271            ('freebsd/crypto/openssl/crypto/ocsp',  'ocsp.h',      'openssl'),
272            ('freebsd/crypto/openssl/crypto/rand',  'rand.h',      'openssl'),
273            ('freebsd/crypto/openssl/crypto/srp',   'srp.h',       'openssl'),
274            ('freebsd/crypto/openssl/crypto/dh',    'dh.h',        'openssl'),
275            ('freebsd/crypto/openssl/crypto/dso',   'dso.h',       'openssl'),
276            ('freebsd/crypto/openssl/crypto/krb5',  'krb5_asn.h',  'openssl'),
277            ('freebsd/crypto/openssl/crypto/cms',   'cms.h',       'openssl'),
278            ('freebsd/crypto/openssl/crypto/txt_db', 'txt_db.h',   'openssl'),
279            ('freebsd/crypto/openssl/crypto/ts',    'ts.h',        'openssl'),
280            ('freebsd/crypto/openssl/crypto/modes', 'modes.h',     'openssl'),
281            ('freebsd/crypto/openssl/crypto/pkcs12', 'pkcs12.h',   'openssl'),
282            ('freebsd/crypto/openssl/crypto/bf',    'blowfish.h',  'openssl'),
283            ('freebsd/crypto/openssl/crypto/cmac',  'cmac.h',      'openssl'),
284            ('freebsd/crypto/openssl/crypto/asn1',  '(asn1|asn1t).h',            'openssl'),
285            ('freebsd/crypto/openssl/crypto/camellia', 'camellia.h',             'openssl'),
286            ('freebsd/crypto/openssl/crypto/objects',  '(objects|obj_mac).h',    'openssl'),
287            ('freebsd/crypto/openssl/crypto/conf',     '(conf|conf_api).h',      'openssl'),
288            ('freebsd/crypto/openssl/crypto/des',      '(des|des_old).h',        'openssl'),
289            ('freebsd/crypto/openssl/crypto/ui',       '(ui_compat|ui).h',       'openssl'),
290            ('freebsd/crypto/openssl/crypto/whrlpool', 'whrlpool.h',             'openssl'),
291            ('freebsd/crypto/openssl/crypto/stack',    '(stack|safestack).h',    'openssl'),
292            ('freebsd/crypto/openssl/crypto', '(opensslconf|opensslv|crypto).h', 'openssl'),
293            ('freebsd/sys/rpc',               '**/*.h',            'rpc'),
294            ('freebsd/sys/sys',               '**/*.h',            'sys'),
295            ('freebsd/sys/vm',                '**/*.h',            'vm'),
296            ('freebsd/sys/dev/mii',           '**/*.h',            'dev/mii'),
297            ('mDNSResponder/mDNSCore',        'mDNSDebug.h',       ''),
298            ('mDNSResponder/mDNSCore',        'mDNSEmbeddedAPI.h', ''),
299            ('mDNSResponder/mDNSShared',      'dns_sd.h',          ''),
300            ('mDNSResponder/mDNSPosix',       'mDNSPosix.h',       '')]
301
302# Move target dependent files under a machine directory
303def mapCPUDependentPath(path):
304  return path.replace("include/", "include/machine/")
305
306def fixIncludes(data):
307    data = re.sub('#include <sys/resource.h>', '#include <rtems/bsd/sys/resource.h>', data)
308    data = re.sub('#include <sys/unistd.h>',   '#include <rtems/bsd/sys/unistd.h>', data)
309    return data
310
311# revert fixing the include paths inside a C or .h file
312def revertFixIncludes(data):
313    data = re.sub('#include <rtems/bsd/',  '#include <', data)
314    data = re.sub('#include <util.h>',     '#include <rtems/bsd/util.h>', data)
315    data = re.sub('#include <bsd.h>',      '#include <rtems/bsd/bsd.h>', data)
316    data = re.sub('#include <zerocopy.h>', '#include <rtems/bsd/zerocopy.h>', data)
317    return data
318
319# fix include paths inside a C or .h file
320def fixLocalIncludes(data):
321    data = re.sub('#include "opt_([^"]*)"',    '#include <rtems/bsd/local/opt_\\1>', data)
322    data = re.sub('#include "([^"]*)_if.h"',   '#include <rtems/bsd/local/\\1_if.h>', data)
323    data = re.sub('#include "miidevs([^"]*)"', '#include <rtems/bsd/local/miidevs\\1>', data)
324    data = re.sub('#include "usbdevs([^"]*)"', '#include <rtems/bsd/local/usbdevs\\1>', data)
325    return data
326
327# revert fixing the include paths inside a C or .h file
328def revertFixLocalIncludes(data):
329    data = re.sub('#include <rtems/bsd/local/([^>]*)>', '#include "\\1"', data)
330    return data
331
332def assertHeaderFile(path):
333    if path[-2] != '.' or path[-1] != 'h':
334        print("*** " + path + " does not end in .h")
335        print("*** Move it to a C source file list")
336        sys.exit(2)
337
338def assertSourceFile(path):
339    if path[-2] != '.' or (path[-1] != 'c' and path[-1] != 'S'):
340        print("*** " + path + " does not end in .c")
341        print("*** Move it to a header file list")
342        sys.exit(2)
343
344def diffSource(dstLines, srcLines, src, dst):
345    global filesTotal, filesTotalLines, filesTotalInserts, filesTotalDeletes
346    #
347    # Diff, note there is no line termination on each string.  Expand the
348    # generator to list because the generator is not reusable.
349    #
350    diff = list(difflib.unified_diff(dstLines,
351                                     srcLines,
352                                     fromfile = src,
353                                     tofile = dst,
354                                     n = 5,
355                                     lineterm = ''))
356    inserts = 0
357    deletes = 0
358    if len(diff) > 0:
359        if src in diffDetails and \
360           diffDetails[src].dst != dst and diffDetails[src].diff != diff:
361            raise error('repeated diff of file different: src:%s dst:%s' % (src, dst))
362        for l in diff:
363            if l[0] == '-':
364                deletes += 1
365            elif l[0] == '+':
366                inserts += 1
367        diffDetails[src] = diffRecord(src, dst, srcLines, diff, inserts, deletes)
368
369    #
370    # Count the total files, lines and the level of changes.
371    #
372    filesTotal += 1
373    filesTotalLines += len(srcLines)
374    filesTotalInserts += inserts
375    filesTotalDeletes += deletes
376
377    return diff
378
379#
380# Converters provide a way to alter the various types of code. The conversion
381# process filters a file as it is copies from the source path to the
382# destination path. Specialised versions are provided for different types of
383# source.
384#
385class Converter(object):
386
387    def convert(self, src, dst, hasSource = True, sourceFilter = None, srcContents = None):
388
389        global filesProcessed, filesProcessedCount
390
391        if verbose(verboseDebug):
392            print("convert: filter:%s: %s -> %s" % \
393                  (['yes', 'no'][sourceFilter is None], src, dst))
394
395        #
396        # If there is no source raise an error if we expect source else print a
397        # warning and do not try and convert.
398        #
399        if srcContents is None:
400            if not os.path.exists(src):
401                if hasSource:
402                    raise error('source not found: %s' % (src))
403                else:
404                    print('warning: no source: %s' % (src))
405                    return
406
407            #
408            # Files read as a single string if not passed in.
409            #
410            srcContents = readFile(src)
411
412        if os.path.exists(dst):
413            dstContents = readFile(dst)
414        else:
415            print('warning: no destination: %s' % (dst))
416            dstContents = ''
417
418        #
419        # Filter the source.
420        #
421        if sourceFilter is not None:
422            srcContents = sourceFilter(srcContents)
423
424        #
425        # Split into a list of lines.
426        #
427        srcLines = srcContents.split(os.linesep)
428        dstLines = dstContents.split(os.linesep)
429
430        if verbose(verboseDebug):
431            print('Unified diff: %s (lines:%d)' % (src, len(srcLines)))
432
433        #
434        # Diff, note there is no line termination on each string.
435        #
436        diff = diffSource(dstLines, srcLines, src, dst)
437
438        #
439        # The diff list is empty if the files are the same.
440        #
441        if len(diff) > 0:
442
443            if verbose(verboseDebug):
444                print('Unified diff length: %d' % len(diff))
445
446            filesProcessed += [dst]
447            filesProcessedCount += 1
448            if isDiffMode == False:
449                if verbose(verboseDetail):
450                    print("UPDATE: %s -> %s" % (src, dst))
451                if isDryRun == False:
452                    writeFile(dst, srcContents)
453            else:
454                print("diff -u %s %s" % (src, dst))
455                for l in diff:
456                    print(l)
457
458class NoConverter(Converter):
459    def convert(self, src, dst, hasSource = True, sourceFilter = None):
460        return '/* EMPTY */\n'
461
462class FromFreeBSDToRTEMSHeaderConverter(Converter):
463    def sourceFilter(self, data):
464        data = fixLocalIncludes(data)
465        data = fixIncludes(data)
466        return data
467
468    def convert(self, src, dst):
469        sconverter = super(FromFreeBSDToRTEMSHeaderConverter, self)
470        sconverter.convert(src, dst, sourceFilter = self.sourceFilter)
471
472class FromFreeBSDToRTEMSUserSpaceHeaderConverter(Converter):
473    def sourceFilter(self, data):
474        data = fixIncludes(data)
475        return data
476
477    def convert(self, src, dst):
478        sconverter = super(FromFreeBSDToRTEMSUserSpaceHeaderConverter, self)
479        sconverter.convert(src, dst, sourceFilter = self.sourceFilter)
480
481class FromFreeBSDToRTEMSSourceConverter(Converter):
482    def sourceFilter(self, data):
483        data = fixLocalIncludes(data)
484        data = fixIncludes(data)
485        data = '#include <machine/rtems-bsd-kernel-space.h>\n\n' + data
486        return data
487
488    def convert(self, src, dst):
489        sconverter = super(FromFreeBSDToRTEMSSourceConverter, self)
490        sconverter.convert(src, dst, sourceFilter = self.sourceFilter)
491
492class FromFreeBSDToRTEMSUserSpaceSourceConverter(Converter):
493    def sourceFilter(self, data):
494        data = fixIncludes(data)
495        data = '#include <machine/rtems-bsd-user-space.h>\n\n' + data
496        return data
497
498    def convert(self, src, dst):
499        sconverter = super(FromFreeBSDToRTEMSUserSpaceSourceConverter, self)
500        sconverter.convert(src, dst, sourceFilter = self.sourceFilter)
501
502class FromRTEMSToFreeBSDHeaderConverter(Converter):
503    def sourceFilter(self, data):
504        data = revertFixLocalIncludes(data)
505        data = revertFixIncludes(data)
506        return data
507
508    def convert(self, src, dst):
509        sconverter = super(FromRTEMSToFreeBSDHeaderConverter, self)
510        sconverter.convert(src, dst, hasSource = False,  sourceFilter = self.sourceFilter)
511
512class FromRTEMSToFreeBSDSourceConverter(Converter):
513    def sourceFilter(self, data):
514        data = re.sub('#include <machine/rtems-bsd-kernel-space.h>\n\n', '', data)
515        data = re.sub('#include <machine/rtems-bsd-user-space.h>\n\n', '', data)
516        data = revertFixLocalIncludes(data)
517        data = revertFixIncludes(data)
518        return data
519
520    def convert(self, src, dst):
521        sconverter = super(FromRTEMSToFreeBSDSourceConverter, self)
522        sconverter.convert(src, dst, hasSource = False, sourceFilter = self.sourceFilter)
523
524#
525# Compose a path based for the various parts of the source tree.
526#
527class PathComposer(object):
528    def composeOriginPath(self, path):
529        return path
530
531    def composeLibBSDPath(self, path, prefix):
532        return os.path.join(prefix, path)
533
534class FreeBSDPathComposer(PathComposer):
535    def composeOriginPath(self, path):
536        return os.path.join(FreeBSD_DIR, path)
537
538    def composeLibBSDPath(self, path, prefix):
539        return os.path.join(prefix, 'freebsd', path)
540
541class RTEMSPathComposer(PathComposer):
542    def composeOriginPath(self, path):
543        return path
544
545    def composeLibBSDPath(self, path, prefix):
546        return os.path.join(prefix, 'rtemsbsd', path)
547
548class LinuxPathComposer(PathComposer):
549    def composeOriginPath(self, path):
550        return os.path.join(Linux_DIR, path)
551
552    def composeLibBSDPath(self, path, prefix):
553        return os.path.join(prefix, 'linux', path)
554
555class CPUDependentFreeBSDPathComposer(FreeBSDPathComposer):
556    def composeLibBSDPath(self, path, prefix):
557        path = super(CPUDependentFreeBSDPathComposer, self).composeLibBSDPath(path, prefix)
558        path = mapCPUDependentPath(path)
559        return path
560
561class CPUDependentRTEMSPathComposer(RTEMSPathComposer):
562    def composeLibBSDPath(self, path, prefix):
563        path = super(CPUDependentRTEMSPathComposer, self).composeLibBSDPath(path, prefix)
564        path = mapCPUDependentPath(path)
565        return path
566
567class CPUDependentLinuxPathComposer(LinuxPathComposer):
568    def composeLibBSDPath(self, path, prefix):
569        path = super(CPUDependentLinuxPathComposer, self).composeLibBSDPath(path, prefix)
570        path = mapCPUDependentPath(path)
571        return path
572
573class TargetSourceCPUDependentPathComposer(CPUDependentFreeBSDPathComposer):
574    def __init__(self, targetCPU, sourceCPU):
575        self.targetCPU = targetCPU
576        self.sourceCPU = sourceCPU
577
578    def composeLibBSDPath(self, path, prefix):
579        path = super(TargetSourceCPUDependentPathComposer, self).composeLibBSDPath(path, prefix)
580        path = path.replace(self.sourceCPU, self.targetCPU)
581        return path
582
583class BuildSystemFragmentComposer(object):
584    def __init__(self, includes = None):
585        if type(includes) is not list:
586            self.includes = [includes]
587        else:
588            self.includes = includes
589
590    def compose(self, path):
591        return ''
592
593#
594# File - a file in the source we move backwards and forwards.
595#
596class File(object):
597    def __init__(self, path, pathComposer,
598                 forwardConverter, reverseConverter, buildSystemComposer):
599        if verbose(verboseMoreDetail):
600            print("FILE: %-50s F:%-45s R:%-45s" % \
601                  (path,
602                   forwardConverter.__class__.__name__,
603                   reverseConverter.__class__.__name__))
604        self.path = path
605        self.pathComposer = pathComposer
606        self.originPath = self.pathComposer.composeOriginPath(self.path)
607        self.libbsdPath = self.pathComposer.composeLibBSDPath(self.path, LIBBSD_DIR)
608        self.forwardConverter = forwardConverter
609        self.reverseConverter = reverseConverter
610        self.buildSystemComposer = buildSystemComposer
611
612    def processSource(self, forward):
613        if forward:
614            if verbose(verboseDetail):
615                print("process source: %s => %s" % (self.originPath, self.libbsdPath))
616            self.forwardConverter.convert(self.originPath, self.libbsdPath)
617        else:
618            if verbose(verboseDetail):
619                print("process source: %s => %s converter:%s" % \
620                      (self.libbsdPath, self.originPath, self.reverseConverter.__class__.__name__))
621            self.reverseConverter.convert(self.libbsdPath, self.originPath)
622
623    def getFragment(self):
624        return self.buildSystemComposer.compose(self.pathComposer.composeLibBSDPath(self.path, ''))
625
626#
627# Module - logical group of related files we can perform actions on
628#
629class Module:
630    def __init__(self, name):
631        self.name = name
632        self.conditionalOn = "none"
633        self.files = []
634        self.cpuDependentSourceFiles = {}
635        self.dependencies = []
636
637    def initCPUDependencies(self, cpu):
638        if cpu not in self.cpuDependentSourceFiles:
639            self.cpuDependentSourceFiles[cpu] = []
640
641    def processSource(self, direction):
642        if verbose(verboseDetail):
643            print("process module: %s" % (self.name))
644        for f in self.files:
645            f.processSource(direction)
646        for cpu, files in self.cpuDependentSourceFiles.items():
647            for f in files:
648                f.processSource(direction)
649
650    def addFiles(self, newFiles, buildSystemComposer = BuildSystemFragmentComposer()):
651        files = []
652        for newFile in newFiles:
653            assertFile(newFile)
654            files += [File(newFile, composers, buildSystemComposer)]
655        return files
656
657    def addFile(self, f):
658        self.files += [f]
659
660    def addFiles(self, newFiles,
661                 pathComposer, forwardConverter, reverseConverter,
662                 assertFile, buildSystemComposer = BuildSystemFragmentComposer()):
663        files = []
664        for newFile in newFiles:
665            assertFile(newFile)
666            files += [File(newFile, pathComposer, forwardConverter,
667                           reverseConverter, buildSystemComposer)]
668        return files
669
670    def addKernelSpaceHeaderFiles(self, files):
671        self.files += self.addFiles(files,
672                                    FreeBSDPathComposer(), FromFreeBSDToRTEMSHeaderConverter(),
673                                    FromRTEMSToFreeBSDHeaderConverter(), assertHeaderFile)
674
675    def addUserSpaceHeaderFiles(self, files):
676        self.files += self.addFiles(files,
677                                    FreeBSDPathComposer(), FromFreeBSDToRTEMSUserSpaceHeaderConverter(),
678                                    FromRTEMSToFreeBSDHeaderConverter(), assertHeaderFile)
679
680    def addRTEMSHeaderFiles(self, files):
681        self.files += self.addFiles(files, RTEMSPathComposer(),
682                                    NoConverter(), NoConverter(), assertHeaderFile)
683
684    def addLinuxHeaderFiles(self, files):
685        self.files += self.addFiles(files,
686                                    LinuxPathComposer(), FromFreeBSDToRTEMSHeaderConverter(),
687                                    FromRTEMSToFreeBSDHeaderConverter(), assertHeaderFile)
688
689    def addCPUDependentFreeBSDHeaderFiles(self, files):
690        self.files += self.addFiles(files,
691                                    CPUDependentFreeBSDPathComposer(), FromFreeBSDToRTEMSHeaderConverter(),
692                                    FromRTEMSToFreeBSDHeaderConverter(), assertHeaderFile)
693
694    def addCPUDependentLinuxHeaderFiles(self, files):
695        self.files += self.addFiles(files,
696                                    CPUDependentLinuxPathComposer(), FromFreeBSDToRTEMSHeaderConverter(),
697                                    FromRTEMSToFreeBSDHeaderConverter(), assertHeaderFile)
698
699    def addTargetSourceCPUDependentHeaderFiles(self, targetCPUs, sourceCPU, files):
700        for cpu in targetCPUs:
701            self.files += self.addFiles(files,
702                                        TargetSourceCPUDependentPathComposer(cpu, sourceCPU),
703                                        FromFreeBSDToRTEMSHeaderConverter(),
704                                        NoConverter(), assertHeaderFile)
705
706    def addSourceFiles(self, files, sourceFileFragmentComposer):
707        self.files += self.addFiles(files,
708                                    PathComposer(), NoConverter(), NoConverter(), assertSourceFile,
709                                    sourceFileFragmentComposer)
710
711    def addKernelSpaceSourceFiles(self, files, sourceFileFragmentComposer):
712        self.files += self.addFiles(files,
713                                    FreeBSDPathComposer(), FromFreeBSDToRTEMSSourceConverter(),
714                                    FromRTEMSToFreeBSDSourceConverter(), assertSourceFile,
715                                    sourceFileFragmentComposer)
716
717    def addUserSpaceSourceFiles(self, files, sourceFileFragmentComposer):
718        self.files += self.addFiles(files,
719                                    FreeBSDPathComposer(),
720                                    FromFreeBSDToRTEMSUserSpaceSourceConverter(),
721                                    FromRTEMSToFreeBSDSourceConverter(), assertSourceFile,
722                                    sourceFileFragmentComposer)
723
724    def addRTEMSSourceFiles(self, files, sourceFileFragmentComposer):
725        self.files += self.addFiles(files,
726                                    RTEMSPathComposer(), NoConverter(), NoConverter(),
727                                    assertSourceFile, sourceFileFragmentComposer)
728
729    def addLinuxSourceFiles(self, files, sourceFileFragmentComposer):
730        self.files += self.addFiles(files,
731                                    LinuxPathComposer(), FromFreeBSDToRTEMSSourceConverter(),
732                                    FromRTEMSToFreeBSDSourceConverter(), assertSourceFile,
733                                    sourceFileFragmentComposer)
734
735    def addCPUDependentFreeBSDSourceFiles(self, cpus, files, sourceFileFragmentComposer):
736        for cpu in cpus:
737            self.initCPUDependencies(cpu)
738            self.cpuDependentSourceFiles[cpu] += \
739                self.addFiles(files,
740                              CPUDependentFreeBSDPathComposer(), FromFreeBSDToRTEMSSourceConverter(),
741                              FromRTEMSToFreeBSDSourceConverter(), assertSourceFile,
742                              sourceFileFragmentComposer)
743
744    def addCPUDependentRTEMSSourceFiles(self, cpus, files, sourceFileFragmentComposer):
745        for cpu in cpus:
746            self.initCPUDependencies(cpu)
747            self.cpuDependentSourceFiles[cpu] += \
748                self.addFiles(files,
749                              CPUDependentRTEMSPathComposer(), NoConverter(),
750                              NoConverter(), assertSourceFile,
751                              sourceFileFragmentComposer)
752
753    def addCPUDependentLinuxSourceFiles(self, cpus, files, sourceFileFragmentComposer):
754        for cpu in cpus:
755            self.initCPUDependencies(cpu)
756            self.cpuDependentSourceFiles[cpu] += \
757                self.addFiles(files,
758                              CPUDependentLinuxPathComposer(), FromFreeBSDToRTEMSSourceConverter(),
759                              FromRTEMSToFreeBSDSourceConverter(), assertSourceFile,
760                              sourceFileFragmentComposer)
761
762    def addTest(self, testFragementComposer):
763        self.files += [File(testFragementComposer.testName,
764                            PathComposer(), NoConverter(), NoConverter(),
765                            testFragementComposer)]
766
767    def addDependency(self, dep):
768        self.dependencies += [dep]
769
770#
771# Manager - a collection of modules.
772#
773class ModuleManager:
774    def __init__(self):
775        self.modules = {}
776        self.generator = {}
777        self.setGenerators()
778
779    def __getitem__(self, key):
780        if key not in self.modules:
781            raise KeyError('module %s not found' % (key))
782        return self.modules[key]
783
784    def getModules(self):
785        return sorted(self.modules.keys())
786
787    def addModule(self, module):
788        self.modules[module.name] = module
789
790    def processSource(self, direction):
791        if verbose(verboseDetail):
792            print("process modules:")
793        for m in sorted(self.modules):
794            self.modules[m].processSource(direction)
Note: See TracBrowser for help on using the repository browser.