xref: /llvm-project/llvm/tools/llvm-shlib/gen-msvc-exports.py (revision b71edfaa4ec3c998aadb35255ce2f60bba2940b0)
1# ===- gen-msvc-exports.py - Generate C API export file -------*- python -*--===#
2#
3# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4# See https://llvm.org/LICENSE.txt for license information.
5# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6#
7# ===------------------------------------------------------------------------===#
8#
9# Generate an export file from a list of given LIB files. This only exports symbols
10# that start with LLVM, so it only exports the LLVM C API.
11#
12# To have CMake run this, set LLVM_BUILD_LLVM_C_DYLIB to on while
13# building on Windows.
14#
15# To run manually, build LLVM with Visual Studio, use a Command prompt
16# to navigate to the directory with the .lib files (Debug\lib etc). Then run
17#     python C:\Path\To\gen-msvc-exports.py --nm ..\bin\llvm-nm.exe LLVM*.lib
18#
19# If you're generating a 32 bit DLL, use the `--underscore` flag.
20# If you want to use a different `llvm-nm` executable, pass the path
21# with the `--nm` flag.
22#
23# You can use the --output flag to set the name of the export file.
24#
25# ===------------------------------------------------------------------------===#
26from tempfile import mkstemp
27from contextlib import contextmanager
28from subprocess import check_call
29import argparse
30import os
31import re
32
33
34_UNDERSCORE_REGEX = {
35    False: re.compile(r"^\w+\s+T\s+(LLVM.*)$"),
36    True: re.compile(r"^\w+\s+T\s+_(LLVM.*)$"),
37}
38
39
40@contextmanager
41def removing(path):
42    try:
43        yield path
44    finally:
45        os.unlink(path)
46
47
48def touch_tempfile(*args, **kwargs):
49    fd, name = mkstemp(*args, **kwargs)
50    os.close(fd)
51    return name
52
53
54def gen_llvm_c_export(output, underscore, libs, nm):
55    """Generate the export file for the LLVM-C DLL.
56
57    Run `nm` for each lib in `libs`, and output an export file
58    to `output`. If `underscore` is true, symbols will
59    be assumed to be prefixed with an underscore.
60    """
61    with removing(touch_tempfile(prefix="dumpout", suffix=".txt")) as dumpout:
62
63        # Get the right regex.
64        p = _UNDERSCORE_REGEX[underscore]
65
66        with open(output, "w+t") as output_f:
67
68            # For each lib get the LLVM* functions it exports.
69            for lib in libs:
70                # Call dumpbin.
71                with open(dumpout, "w+t") as dumpout_f:
72                    check_call([nm, "-g", lib], stdout=dumpout_f)
73
74                # Get the matching lines.
75                with open(dumpout) as dumpbin:
76                    for line in dumpbin:
77                        m = p.match(line)
78                        if m is not None:
79                            output_f.write(m.group(1) + "\n")
80
81
82def main():
83    parser = argparse.ArgumentParser("gen-msvc-exports")
84
85    parser.add_argument(
86        "-i",
87        "--libsfile",
88        help="file with list of libs, new line separated",
89        action="store",
90        default=None,
91    )
92    parser.add_argument(
93        "-o", "--output", help="output filename", default="LLVM-C.exports"
94    )
95    parser.add_argument(
96        "-u",
97        "--underscore",
98        help="labels are prefixed with an underscore (use for 32 bit DLLs)",
99        action="store_true",
100    )
101    parser.add_argument(
102        "--nm", help="path to the llvm-nm executable", default="llvm-nm"
103    )
104    parser.add_argument(
105        "libs",
106        metavar="LIBS",
107        nargs="*",
108        help="list of libraries to generate export from",
109    )
110
111    ns = parser.parse_args()
112
113    libs = ns.libs
114
115    # Add if we where given a libsfile add it to the libs.
116    if ns.libsfile:
117        with open(ns.libsfile) as f:
118            libs.extend(f.read().splitlines())
119
120    gen_llvm_c_export(ns.output, ns.underscore, libs, ns.nm)
121
122
123if __name__ == "__main__":
124    main()
125