blob: 671faf115281241369132b83b4aca60d9c190b00 [file] [log] [blame]
David Bolvanskyab2cbad2018-08-07 15:54:50 +00001#===- gen-msvc-exports.py - Generate C API export file -------*- python -*--===#
2#
Chandler Carruth2946cd72019-01-19 08:50:56 +00003# 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
David Bolvanskyab2cbad2018-08-07 15:54:50 +00006#
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(
Serge Gueltond2f2f332019-03-19 09:14:09 +000086 '-i', '--libsfile', help='file with list of libs, new line separated',
87 action='store', default=None
88 )
89 parser.add_argument(
David Bolvanskyab2cbad2018-08-07 15:54:50 +000090 '-o', '--output', help='output filename', default='LLVM-C.exports'
91 )
92 parser.add_argument('-u', '--underscore',
93 help='labels are prefixed with an underscore (use for 32 bit DLLs)',
94 action='store_true'
95 )
96 parser.add_argument(
97 '--nm', help='path to the llvm-nm executable', default='llvm-nm'
98 )
99 parser.add_argument(
Serge Gueltond2f2f332019-03-19 09:14:09 +0000100 'libs', metavar='LIBS', nargs='*', help='list of libraries to generate export from'
David Bolvanskyab2cbad2018-08-07 15:54:50 +0000101 )
102
103 ns = parser.parse_args()
104
Serge Gueltond2f2f332019-03-19 09:14:09 +0000105 libs = ns.libs
106
107 # Add if we where given a libsfile add it to the libs.
108 if ns.libsfile:
109 with open(ns.libsfile) as f:
110 libs.extend(f.read().splitlines())
111
112 gen_llvm_c_export(ns.output, ns.underscore, libs, ns.nm)
David Bolvanskyab2cbad2018-08-07 15:54:50 +0000113
114
115if __name__ == '__main__':
116 main()