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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
# ===- 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(
"-i",
"--libsfile",
help="file with list of libs, new line separated",
action="store",
default=None,
)
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()
libs = ns.libs
# Add if we where given a libsfile add it to the libs.
if ns.libsfile:
with open(ns.libsfile) as f:
libs.extend(f.read().splitlines())
gen_llvm_c_export(ns.output, ns.underscore, libs, ns.nm)
if __name__ == "__main__":
main()
|