Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: build/win/importlibs/create_importlib_win.py

Issue 12295040: Stop delay loading user32.dll from chrome.dll on x86/Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Reduce scope to chrome.dll/x86. Address review comments. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5 #
6 """Creates an import library from an import description file."""
7 import ast
8 import logging
9 import optparse
10 import os
11 import os.path
12 import shutil
13 import subprocess
14 import sys
15 import tempfile
16
17
18 _USAGE = """\
19 Usage: %prog [options] [imports-file]
20
21 Creates an import library from imports-file.
22
23 Note: this script uses the microsoft assembler (ml.exe) and the library tool
24 (lib.exe), both of which must be in path.
25 """
26
27
28 _ASM_STUB_HEADER = """\
29 ; This file is autogenerated, do not edit.
M-A Ruel 2013/03/26 12:59:14 ; This file is autogenerated by create_importlib_w
Sigurður Ásgeirsson 2013/03/26 15:35:35 Done.
30 .386
31 .MODEL FLAT, C
32 .CODE
33
34 ; Stubs to provide mangled names to lib.exe for the
35 ; correct generation of import libs.
36 """
37
38
39 _DEF_STUB_HEADER = """\
40 ; This file is autogenerated, do not edit.
M-A Ruel 2013/03/26 12:59:14 same
Sigurður Ásgeirsson 2013/03/26 15:35:35 Done.
41
42 ; Export declarations for generating import libs.
43 """
44
45
46 _LOGGER = logging.getLogger()
47
48
49
50 class _Error(Exception):
51 pass
52
53
54 class _ImportLibraryGenerator(object):
55 def __init__(self, temp_dir):
56 self._temp_dir = temp_dir
57
58 def _Shell(self, cmd, **kw):
59 ret = subprocess.call(cmd, **kw)
60 _LOGGER.info('Running "%s" returned %d.', cmd, ret)
61 if ret != 0:
62 raise _Error('Command "%s" returned %d.' % (cmd, ret))
63
64 def _ReadImportsFile(self, imports_file):
65 # Slurp the imports file.
66 return ast.literal_eval(open(imports_file).read())
67
68 def _WriteStubsFile(self, import_names, output_file):
69 output_file.write(_ASM_STUB_HEADER)
70
71 for name in import_names:
72 output_file.write('%s PROC\n' % name)
73 output_file.write('%s ENDP\n' % name)
74
75 output_file.write('END\n')
76
77 def _WriteDefFile(self, dll_name, import_names, output_file):
78 output_file.write(_DEF_STUB_HEADER)
79 output_file.write('NAME %s\n' % dll_name)
80 output_file.write('EXPORTS\n')
81 for name in import_names:
82 name = name.split('@')[0]
83 output_file.write(' %s\n' % name)
84
85
M-A Ruel 2013/03/26 12:59:14 remove one line
Sigurður Ásgeirsson 2013/03/26 15:35:35 Done.
86 def _CreateObj(self, dll_name, imports):
87 """Writes an assembly file containing empty declarations.
88
89 For each imported function of the form:
90
91 AddClipboardFormatListener@4 PROC
92 AddClipboardFormatListener@4 ENDP
93
94 The resulting object file is then supplied to lib.exe with a .def file
95 declaring the corresponding non-adorned exports as they appear on the
96 exporting DLL, e.g.
97
98 EXPORTS
99 AddClipboardFormatListener
100
101 In combination, the .def file and the .obj file cause lib.exe to generate
102 an x86 import lib with public symbols named like
103 "__imp__AddClipboardFormatListener@4", binding to exports named like
104 "AddClipboardFormatListener".
105
106 All of this is perpetrated in a temporary directory, as the intermediate
107 artifacts are quick and easy to produce, and of no interest to anyone
108 after the fact."""
109
110 # Create an .asm file to provide stdcall-like stub names to lib.exe.
111 asm_name = dll_name + '.asm'
112 _LOGGER.info('Writing asm file "%s".', asm_name)
113 with open(os.path.join(self._temp_dir, asm_name), 'w') as stubs_file:
M-A Ruel 2013/03/26 12:59:14 We always use 'wb' for consistency. Unless you act
Sigurður Ásgeirsson 2013/03/26 15:35:35 Done.
114 self._WriteStubsFile(imports, stubs_file)
115
116 # Invoke on the assembler to compile it to .obj.
117 obj_name = dll_name + '.obj'
118 cmdline = ['ml.exe', '/nologo', '/c', asm_name, '/Fo', obj_name]
119 self._Shell(cmdline, cwd=self._temp_dir)
120
121 return obj_name
122
123 def _CreateImportLib(self, dll_name, imports, architecture, output_file):
124 """Creates an import lib binding imports to dll_name for architecture.
125
126 On success, writes the import library to output file.
127 """
128 obj_file = None
129
130 # For x86 architecture we have to provide an object file for correct
131 # name mangling between the import stubs and the exported functions.
132 if architecture == 'x86':
133 obj_file = self._CreateObj(dll_name, imports)
134
135 print "architecture", architecture
136 print "Obj file", obj_file # DO NOT SUBMIT
M-A Ruel 2013/03/26 12:59:14 I guess you won't submit this :)
Sigurður Ásgeirsson 2013/03/26 15:35:35 Ooops - I'm used to the presubmit check (in Syzygy
M-A Ruel 2013/03/26 15:44:37 Yes but only on commit.
137
138 # Create the corresponding .def file. This file has the non stdcall-adorned
139 # names, as exported by the destination DLL.
140 def_name = dll_name + '.def'
141 _LOGGER.info('Writing def file "%s".', def_name)
142 with open(os.path.join(self._temp_dir, def_name), 'w') as def_file:
143 self._WriteDefFile(dll_name, imports, def_file)
144
145 # Invoke on lib.exe to create the import library.
146 # We generate everything into the temporary directory, as the .exp export
147 # files will be generated at the same path as the import library, and we
148 # don't want those files potentially gunking the works.
149 dll_base_name, ext = os.path.splitext(dll_name)
150 lib_name = dll_base_name + '.lib'
151 cmdline = ['lib.exe',
152 '/machine:%s' % architecture,
153 '/def:%s' % def_name,
154 '/out:%s' % lib_name]
155 if obj_file:
156 cmdline.append(obj_file)
157
158 self._Shell(cmdline, cwd=self._temp_dir)
159
160 # Copy the .lib file to the output directory.
161 shutil.copyfile(os.path.join(self._temp_dir, lib_name), output_file)
162 _LOGGER.info('Created "%s".', output_file)
163
164 def CreateImportLib(self, imports_file, output_file):
165 # Read the imports file.
166 imports = self._ReadImportsFile(imports_file)
167
168 # Creates the requested import library in the output directory.
169 self._CreateImportLib(imports['dll_name'],
170 imports['imports'],
171 imports.get('architecture', 'x86'),
172 output_file)
173
174
175 def main():
176 parser = optparse.OptionParser(usage=_USAGE)
177 parser.add_option('-o', '--output-file',
178 help='Specifies the output file path.')
179 parser.add_option('-k', '--keep-temp-dir',
180 action='store_true',
181 help='Keep the temporary directory.')
182 parser.add_option('-v', '--verbose',
183 action='store_true',
184 help='Verbose logging.')
185
186 options, args = parser.parse_args()
187
188 print args
189 if len(args) != 1:
190 parser.error('You must provide an imports file.')
191
192 if not options.output_file:
193 parser.error('You must provide an output file.')
194
195 options.output_file = os.path.abspath(options.output_file)
196
197 if options.verbose:
198 logging.basicConfig(level=logging.INFO)
199 else:
200 logging.basicConfig(level=logging.WARN)
201
202
203 temp_dir = tempfile.mkdtemp()
204 _LOGGER.info('Created temporary directory "%s."', temp_dir)
205 try:
206 # Create a generator and create the import lib.
207 generator = _ImportLibraryGenerator(temp_dir)
208
209 ret = generator.CreateImportLib(args[0], options.output_file)
210 except Exception, e:
211 _LOGGER.exception('Failed to create imports.')
212 ret = 1
213 finally:
214 if not options.keep_temp_dir:
215 shutil.rmtree(temp_dir)
216 _LOGGER.info('Deleted temporary directory "%s."', temp_dir)
217
218 return ret
219
220
221 if __name__ == '__main__':
222 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698