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

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: Build config sketch, mostly works for x86 and x64. Move the hook back to base." 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 # A utility script to create import libs from an import description file.
M-A Ruel 2013/03/03 01:48:02 """Creates import libs from an import description
Sigurður Ásgeirsson 2013/03/25 20:43:29 Done.
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.
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.
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/03 01:48:02 remove one line
Sigurður Ásgeirsson 2013/03/25 20:43:29 Done.
86 def _CreateObj(self, dll_name, imports):
87 """Write an assembly file containing empty declarations.
M-A Ruel 2013/03/03 01:48:02 Writes
Sigurður Ásgeirsson 2013/03/25 20:43:29 Done.
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:
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
M-A Ruel 2013/03/03 01:48:02 Remove one line
Sigurður Ásgeirsson 2013/03/25 20:43:29 Done.
123
124 def _CreateImportLib(self, dll_name, imports, architecture, output_file):
125 """Creates an import lib binding imports to dll_name for architecture.
126
127 On success, writes the import library to output file.
128 """
129 obj_file = None
130
131 # For x86 architecture we have to provide an object file for correct
132 # name mangling between the import stubs and the exported functions.
133 if architecture == 'x86':
134 obj_file = self._CreateObj(dll_name, imports)
135
136 print "architecture", architecture
137 print "Obj file", obj_file # DO NOT SUBMIT
138
139 # Create the corresponding .def file. This file has the non stdcall-adorned
140 # names, as exported by the destination DLL.
141 def_name = dll_name + '.def'
142 _LOGGER.info('Writing def file "%s".', def_name)
143 with open(os.path.join(self._temp_dir, def_name), 'w') as def_file:
144 self._WriteDefFile(dll_name, imports, def_file)
145
146 # Invoke on lib.exe to create the import library.
147 # We generate everything into the temporary directory, as the .exp export
148 # files will be generated at the same path as the import library, and we
149 # don't want those files potentially gunking the works.
150 dll_base_name, ext = os.path.splitext(dll_name)
151 lib_name = dll_base_name + '.lib'
152 cmdline = ['lib.exe',
153 '/machine:%s' % architecture,
154 '/def:%s' % def_name,
155 '/out:%s' % lib_name]
156 if obj_file:
157 cmdline.append(obj_file)
158
159 self._Shell(cmdline, cwd=self._temp_dir)
160
161 # Copy the .lib file to the output directory.
162 shutil.copyfile(os.path.join(self._temp_dir, lib_name), output_file)
163 _LOGGER.info('Created "%s".', output_file)
164
165 def CreateImportLib(self, imports_file, output_dir):
166 # Read the imports file.
167 imports = self._ReadImportsFile(imports_file)
168
169 # Creates the requested import library in the output directory.
170 self._CreateImportLib(imports['dll_name'],
171 imports['imports'],
172 imports.get('architecture', 'x86'),
173 os.path.join(output_dir, imports['importlib_name']))
174
175
176 def main():
177 parser = optparse.OptionParser(usage=_USAGE)
178 parser.add_option('-o', '--output-dir',
179 dest='output_dir',
M-A Ruel 2013/03/03 01:48:02 Remove 'dest' and 'default=False' everywhere, they
Sigurður Ásgeirsson 2013/03/25 20:43:29 Done.
180 help='Specifies the output directory.')
181 parser.add_option('-k', '--keep-temp-dir',
182 dest='keep_temp_dir',
183 action='store_true',
184 default=False,
185 help='Keep the temporary directory.')
186 parser.add_option('-v', '--verbose',
187 dest='verbose',
188 action='store_true',
189 default=False,
190 help='Verbose logging.')
191
192 options, args = parser.parse_args()
193
194 print args
195 if len(args) != 1:
196 parser.error('Must provide an imports file.')
197
198 if not options.output_dir:
199 parser.error('Must provide an output directory.')
200
201 options.output_dir = os.path.abspath(options.output_dir)
202
203 if options.verbose:
204 logging.basicConfig(level=logging.INFO)
205 else:
206 logging.basicConfig(level=logging.WARN)
207
208
209 temp_dir = tempfile.mkdtemp()
210 _LOGGER.info('Created temporary directory "%s."', temp_dir)
211 try:
212 # Create a generator and create the import lib.
213 generator = _ImportLibraryGenerator(temp_dir)
214
215 ret = generator.CreateImportLib(args[0], options.output_dir)
216 except Exception, e:
217 _LOGGER.exception('Failed to create imports.')
218 ret = 1
219 finally:
220 if not options.keep_temp_dir:
221 shutil.rmtree(temp_dir)
222 _LOGGER.info('Deleted temporary directory "%s."', temp_dir)
223
224 return ret
225
226
227 if __name__ == '__main__':
228 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698