summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-shlib/gen-msvc-exports.py
blob: 2b7291de28b272ab55bb6f9fd0ddd67ec13b804f (plain)
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
95
96
97
98
99
100
101
102
103
104
105
#===- gen-msvc-exports.py - Generate C API export file -------*- python -*--===#
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===------------------------------------------------------------------------===#
#
# Generate an export file from a list of given LIB files. This only exports symbols
# that start with LLVM, so it only exports the LLVM C API.
#
# To have CMake run this, set LLVM_BUILD_LLVM_C_DYLIB to on while
# building on Windows.
#
# To run manually, build LLVM with Visual Studio, use a Command prompt
# to navigate to the directory with the .lib files (Debug\lib etc). Then run
#     python C:\Path\To\gen-msvc-exports.py --nm ..\bin\llvm-nm.exe LLVM*.lib
#
# If you're generating a 32 bit DLL, use the `--underscore` flag.
# If you want to use a different `llvm-nm` executable, pass the path
# with the `--nm` flag.
#
# You can use the --output flag to set the name of the export file.
#
#===------------------------------------------------------------------------===#
from tempfile import mkstemp
from contextlib import contextmanager
from subprocess import check_call
import argparse
import os
import re


_UNDERSCORE_REGEX = {
    False: re.compile(r"^\w+\s+T\s+(LLVM.*)$"),
    True:  re.compile(r"^\w+\s+T\s+_(LLVM.*)$")
}


@contextmanager
def removing(path):
    try:
        yield path
    finally:
        os.unlink(path)


def touch_tempfile(*args, **kwargs):
    fd, name = mkstemp(*args, **kwargs)
    os.close(fd)
    return name


def gen_llvm_c_export(output, underscore, libs, nm):
    """Generate the export file for the LLVM-C DLL.

    Run `nm` for each lib in `libs`, and output an export file
    to `output`. If `underscore` is true, symbols will
    be assumed to be prefixed with an underscore.
    """
    with removing(touch_tempfile(prefix='dumpout', suffix='.txt')) as dumpout:

        # Get the right regex.
        p = _UNDERSCORE_REGEX[underscore]

        with open(output, 'w+t') as output_f:

            # For each lib get the LLVM* functions it exports.
            for lib in libs:
                # Call dumpbin.
                with open(dumpout, 'w+t') as dumpout_f:
                    check_call([nm, '-g', lib], stdout=dumpout_f)

                # Get the matching lines.
                with open(dumpout) as dumpbin:
                    for line in dumpbin:
                        m = p.match(line)
                        if m is not None:
                            output_f.write(m.group(1) + '\n')


def main():
    parser = argparse.ArgumentParser('gen-msvc-exports')

    parser.add_argument(
        '-o', '--output', help='output filename', default='LLVM-C.exports'
    )
    parser.add_argument('-u', '--underscore',
        help='labels are prefixed with an underscore (use for 32 bit DLLs)',
        action='store_true'
    )
    parser.add_argument(
        '--nm', help='path to the llvm-nm executable', default='llvm-nm'
    )
    parser.add_argument(
        'libs', metavar='LIBS', nargs='+', help='list of libraries to generate export from'
    )

    ns = parser.parse_args()

    gen_llvm_c_export(ns.output, ns.underscore, ns.libs, ns.nm)


if __name__ == '__main__':
    main()
OpenPOWER on IntegriCloud