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