OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 | 2 |
3 # Copyright (c) 2012 Google Inc. All rights reserved. | 3 # Copyright (c) 2012 Google Inc. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 """Utility functions for Windows builds. | 7 """Utility functions for Windows builds. |
8 | 8 |
9 These functions are executed via gyp-win-tool when using the ninja generator. | 9 These functions are executed via gyp-win-tool when using the ninja generator. |
10 """ | 10 """ |
11 | 11 |
12 import os | 12 import os |
13 import re | |
13 import shutil | 14 import shutil |
14 import subprocess | 15 import subprocess |
15 import sys | 16 import sys |
16 | 17 |
17 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) | 18 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) |
18 | 19 |
20 # A regex matching an argument corresponding to a PDB filename passed as an | |
21 # argument to link.exe. | |
22 _LINK_EXE_PDB_ARG = re.compile('/PDB:(?P<pdb>.+\.exe\.pdb)', re.IGNORECASE) | |
23 _MSPDBSRV_ENDPOINT_ENV_VAR = '_MSPDBSRV_ENDPOINT_' | |
19 | 24 |
20 def main(args): | 25 def main(args): |
21 executor = WinTool() | 26 executor = WinTool() |
22 exit_code = executor.Dispatch(args) | 27 exit_code = executor.Dispatch(args) |
23 if exit_code is not None: | 28 if exit_code is not None: |
24 sys.exit(exit_code) | 29 sys.exit(exit_code) |
25 | 30 |
26 | 31 |
27 class WinTool(object): | 32 class WinTool(object): |
28 """This class performs all the Windows tooling steps. The methods can either | 33 """This class performs all the Windows tooling steps. The methods can either |
29 be executed directly, or dispatched from an argument list.""" | 34 be executed directly, or dispatched from an argument list.""" |
30 | 35 |
36 class MsPdbSrvHelper(object): | |
37 """This is an helper class to use a unique instance of mspdbsrv.exe for the | |
38 linkers linking an .exe target. This helps to reduce the memory pressure one | |
39 the shared instance of mspdbsrv.exe.""" | |
40 | |
41 def __init__(self, env, args): | |
42 self.env = env | |
43 self.args = args | |
44 self._MaybeStartMsPdbSrv() | |
45 | |
46 def _MaybeStartMsPdbSrv(self): | |
47 """Starts an unique instance of mspdbsrv.exe if the given arguments are | |
48 those of a linker linking a .exe target.""" | |
49 if not os.environ.get('GYP_USE_SEPARATE_MSPDBSRV'): | |
50 return | |
51 | |
52 if len(self.args) < 1: | |
53 raise Exception("Not enough arguments") | |
54 | |
55 if self.args[0] != 'link.exe': | |
56 return | |
57 | |
58 # Checks if this linker produces a PDB for an .exe target. If so use the | |
59 # name of this PDB to generate an endpoint name for mspdbsrv.exe. | |
60 endpoint_name = None | |
61 for arg in self.args: | |
62 m = _LINK_EXE_PDB_ARG.match(arg) | |
63 if m: | |
64 endpoint_name = '%s_%d' % (m.group('pdb'), os.getpid()) | |
65 break | |
66 | |
67 if endpoint_name is None: | |
68 return | |
69 | |
70 # Adds the appropriate environment variable. This will be read by link.exe | |
71 # to know which instance of mspdbsrv.exe it should connect to (if it's | |
72 # not set then the default endpoint is used). | |
73 self.env[_MSPDBSRV_ENDPOINT_ENV_VAR] = endpoint_name | |
74 | |
31 def Dispatch(self, args): | 75 def Dispatch(self, args): |
32 """Dispatches a string command to a method.""" | 76 """Dispatches a string command to a method.""" |
33 if len(args) < 1: | 77 if len(args) < 1: |
34 raise Exception("Not enough arguments") | 78 raise Exception("Not enough arguments") |
35 | 79 |
36 method = "Exec%s" % self._CommandifyName(args[0]) | 80 method = "Exec%s" % self._CommandifyName(args[0]) |
37 return getattr(self, method)(*args[1:]) | 81 return getattr(self, method)(*args[1:]) |
38 | 82 |
39 def _CommandifyName(self, name_string): | 83 def _CommandifyName(self, name_string): |
40 """Transforms a tool name like recursive-mirror to RecursiveMirror.""" | 84 """Transforms a tool name like recursive-mirror to RecursiveMirror.""" |
(...skipping 23 matching lines...) Expand all Loading... | |
64 shutil.copytree(source, dest) | 108 shutil.copytree(source, dest) |
65 else: | 109 else: |
66 shutil.copy2(source, dest) | 110 shutil.copy2(source, dest) |
67 | 111 |
68 def ExecLinkWrapper(self, arch, *args): | 112 def ExecLinkWrapper(self, arch, *args): |
69 """Filter diagnostic output from link that looks like: | 113 """Filter diagnostic output from link that looks like: |
70 ' Creating library ui.dll.lib and object ui.dll.exp' | 114 ' Creating library ui.dll.lib and object ui.dll.exp' |
71 This happens when there are exports from the dll or exe. | 115 This happens when there are exports from the dll or exe. |
72 """ | 116 """ |
73 env = self._GetEnv(arch) | 117 env = self._GetEnv(arch) |
74 popen = subprocess.Popen(args, shell=True, env=env, | 118 mspdbsrv_helper = WinTool.MsPdbSrvHelper(env, args) |
scottmg
2013/11/27 20:33:41
this can just be a function now (and it doesn't ac
Sébastien Marchand
2013/11/27 20:53:43
Of course ! It's much simpler now that we know how
| |
75 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | 119 link_wrapper = subprocess.Popen(args, |
76 out, _ = popen.communicate() | 120 shell=True, |
121 env=env, | |
122 stdout=subprocess.PIPE, | |
123 stderr=subprocess.STDOUT) | |
124 out, _ = link_wrapper.communicate() | |
77 for line in out.splitlines(): | 125 for line in out.splitlines(): |
78 if not line.startswith(' Creating library '): | 126 if not line.startswith(' Creating library '): |
79 print line | 127 print line |
80 return popen.returncode | 128 return link_wrapper.returncode |
81 | 129 |
82 def ExecManifestWrapper(self, arch, *args): | 130 def ExecManifestWrapper(self, arch, *args): |
83 """Run manifest tool with environment set. Strip out undesirable warning | 131 """Run manifest tool with environment set. Strip out undesirable warning |
84 (some XML blocks are recognized by the OS loader, but not the manifest | 132 (some XML blocks are recognized by the OS loader, but not the manifest |
85 tool).""" | 133 tool).""" |
86 env = self._GetEnv(arch) | 134 env = self._GetEnv(arch) |
87 popen = subprocess.Popen(args, shell=True, env=env, | 135 popen = subprocess.Popen(args, shell=True, env=env, |
88 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | 136 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
89 out, _ = popen.communicate() | 137 out, _ = popen.communicate() |
90 for line in out.splitlines(): | 138 for line in out.splitlines(): |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
161 line): | 209 line): |
162 print line | 210 print line |
163 return popen.returncode | 211 return popen.returncode |
164 | 212 |
165 def ExecActionWrapper(self, arch, rspfile, *dir): | 213 def ExecActionWrapper(self, arch, rspfile, *dir): |
166 """Runs an action command line from a response file using the environment | 214 """Runs an action command line from a response file using the environment |
167 for |arch|. If |dir| is supplied, use that as the working directory.""" | 215 for |arch|. If |dir| is supplied, use that as the working directory.""" |
168 env = self._GetEnv(arch) | 216 env = self._GetEnv(arch) |
169 args = open(rspfile).read() | 217 args = open(rspfile).read() |
170 dir = dir[0] if dir else None | 218 dir = dir[0] if dir else None |
171 popen = subprocess.Popen(args, shell=True, env=env, cwd=dir) | 219 return subprocess.call(args, shell=True, env=env, cwd=dir) |
172 popen.wait() | |
173 return popen.returncode | |
174 | 220 |
175 if __name__ == '__main__': | 221 if __name__ == '__main__': |
176 sys.exit(main(sys.argv[1:])) | 222 sys.exit(main(sys.argv[1:])) |
OLD | NEW |