File: swift-abi-symbol-checker.py

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (94 lines) | stat: -rwxr-xr-x 3,100 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/usr/bin/env python3

import argparse
import sys


def getAdditionsAndRemovals(changesFile):
    changesF = open(changesFile)
    changes = changesF.read()
    changesF.close()

    # Get rid of lines that start with either '//' or a newline
    changes = [c for c in changes.splitlines() if not c.startswith('//') and c != '']

    # Filter the changes for lines that start with Added
    additions = [a for a in changes if a.startswith('Added')]
    # Filter the changes for lines that start with Removed
    removals = [r for r in changes if r.startswith('Removed')]

    # Map the additions by removing the 'Added: ' prefix to get just the symbol
    additions = list(map(lambda a: a.removeprefix('Added: '), additions))
    # Map the removals by removing the 'Removed: ' prefix to get just the symbol
    removals = list(map(lambda r: r.removeprefix('Removed: '), removals))

    return (additions, removals)


def checkSymbols(args):
    # If we were passed a base file, read those changes first. This most likely
    # occurs in assert configurations getting the non-assert base.
    baseAdditions = []
    baseRemovals = []

    if args.base:
        (baseAdditions, baseRemovals) = getAdditionsAndRemovals(args.base)

    (additions, removals) = getAdditionsAndRemovals(args.changes)

    # Append the base additions and removals to ours.
    additions.extend(baseAdditions)
    removals.extend(baseRemovals)

    # We need to write back to the temporary symbol file for diffing
    symbolsF = open(args.symbols, 'r+')

    symbols = symbolsF.read().splitlines()

    # Check for added symbols that are not actually in the just built dylib.
    notInDylib = [a for a in additions if a not in symbols]

    # If there were symbols marked as 'Added' in the changes file, but they didn't
    # actually appear in the dylib then print those symbols out and fail.
    if notInDylib:
        for symbol in notInDylib:
            symbols.append('<MISSING ADDITION> {}'.format(symbol))

    # Filter the built symbols for the additions because we're removing them to
    # get back to the baseline
    symbols = [s for s in symbols if s not in additions]

    # Append the removals into the symbol list to get back to the baseline
    symbols.extend(removals)

    # Sort the end result to write back
    symbols.sort()

    # Go back to beginning of the file and purge everything
    symbolsF.seek(0)
    symbolsF.truncate()

    # Append a newline to each symbol (because writelines doesn't do that for us)
    symbols = list(map(lambda s: s + '\n', symbols))

    # Write all of our symbols back into the symbols file
    symbolsF.writelines(symbols)

    # Done
    symbolsF.close()


def main(arguments):
    parser = argparse.ArgumentParser(
        description='Change absolute install names to use @rpath')

    parser.add_argument('changes', help='the changes file')
    parser.add_argument('symbols', help='the symbols file')
    parser.add_argument('--base', help='the base changes file')

    args = parser.parse_args(arguments)

    checkSymbols(args)


sys.exit(main(sys.argv[1:]))