# ===- 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()