Chromium Code Reviews| 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 """ |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 executor = WinTool() | 21 executor = WinTool() |
| 22 exit_code = executor.Dispatch(args) | 22 exit_code = executor.Dispatch(args) |
| 23 if exit_code is not None: | 23 if exit_code is not None: |
| 24 sys.exit(exit_code) | 24 sys.exit(exit_code) |
| 25 | 25 |
| 26 | 26 |
| 27 class WinTool(object): | 27 class WinTool(object): |
| 28 """This class performs all the Windows tooling steps. The methods can either | 28 """This class performs all the Windows tooling steps. The methods can either |
| 29 be executed directly, or dispatched from an argument list.""" | 29 be executed directly, or dispatched from an argument list.""" |
| 30 | 30 |
| 31 class MsPdbSrvHelper(object): | |
| 32 """This is an helper class to use a unique instance of mspdbsrv.exe for the | |
| 33 linkers linking a .exe target. This helps to reduce the memory pressure one | |
|
Sigurður Ásgeirsson
2013/11/25 16:29:57
nit: a->an .exe
Is this factual, though? You also
Sébastien Marchand
2013/11/25 19:24:40
my first goal was to only use the mspdbsrv shardin
| |
| 34 the shared instance of mspdbsrv.exe.""" | |
| 35 | |
| 36 def __init__(self, env, args): | |
| 37 self._is_started = self._MaybeStartMsPdbSrv(env, args) | |
|
scottmg
2013/11/23 00:07:26
no _ prefix on member variables
initialize the va
Sébastien Marchand
2013/11/23 04:30:14
Yeah, if I initialize the members here then is_sta
| |
| 38 | |
| 39 def __del__(self): | |
|
scottmg
2013/11/23 00:07:26
__del__ isn't good as it's when it happens to get
Sébastien Marchand
2013/11/23 04:30:14
Good to know, thanks. I'll do this.
| |
| 40 if self._is_started: | |
| 41 self._StopMsPdbSrv() | |
| 42 | |
| 43 def _MaybeStartMsPdbSrv(self, env, args): | |
| 44 """Starts an unique instance of mspdbsrv.exe if the given arguments are | |
| 45 those of a linker linking a .exe target.""" | |
| 46 if os.environ.get('GYP_USE_SEPARATE_MSPDBSRV'): | |
| 47 return False | |
| 48 | |
| 49 if len(args) < 1: | |
| 50 raise Exception("Not enough arguments") | |
| 51 | |
| 52 if args[0] != 'link.exe': | |
| 53 return False | |
| 54 | |
| 55 # Checks if this linker produce a PDB for an .exe target. If so use the | |
|
Sigurður Ásgeirsson
2013/11/25 16:29:57
nit: produces
Sébastien Marchand
2013/11/26 00:37:56
Done.
| |
| 56 # name of this PDB to generate an endpoint name for mspdbsrv.exe. | |
| 57 endpoint_name = None | |
| 58 for arg in args: | |
| 59 if arg.endswith('exe.pdb'): | |
|
Sigurður Ásgeirsson
2013/11/25 16:29:57
interesting, why only .exes? I'd think DLLs are ju
Sigurður Ásgeirsson
2013/11/25 16:29:57
Maybe use a regexp to match the argument and the p
Sébastien Marchand
2013/11/25 19:24:40
For now I'm only doing this for the .exe because I
Sébastien Marchand
2013/11/26 00:37:56
Done.
| |
| 60 endpoint_name = arg[arg.rfind(':') + 1:] + '_mspdbsrv_endpoint' | |
|
scottmg
2013/11/23 00:07:26
is the ':' the drive separator? i know i suggested
Sébastien Marchand
2013/11/23 04:30:14
No, it's the beginning of the PDB filename. There'
| |
| 61 break | |
| 62 | |
| 63 if endpoint_name is None: | |
| 64 return False | |
| 65 | |
| 66 # Adds the appropriate environment variable. This will be read by link.exe | |
| 67 # to know which instance of mspdbsrv.exe it should connect to (if it's | |
| 68 # not set then the default endpoint is used). | |
|
Sigurður Ásgeirsson
2013/11/25 16:29:57
nit: you might as well go properly unique here and
Sébastien Marchand
2013/11/25 19:24:40
Good point, will do.
| |
| 69 env['_MSPDBSRV_ENDPOINT_'] = endpoint_name | |
| 70 self._env = env | |
| 71 | |
| 72 # Starts the mspdbsrv.exe instance manually. We could specify the endpoint | |
| 73 # in the command line but it's redundant with setting it in the | |
| 74 # environment block. Starting this process manually allows us to wait for | |
| 75 # its completion once the link step is finished. This is required to | |
| 76 # respect the dependencies between the different targets. | |
| 77 mspdbsrv_args = ('mspdbsrv.exe', | |
| 78 '-start', | |
| 79 '-spawn') | |
|
scottmg
2013/11/23 00:07:26
when i run "mspdbsrv -start -spawn -endpoint abcd"
Sébastien Marchand
2013/11/23 04:30:14
Yeah it's blocking, but Popen spawn a child proces
| |
| 80 self._mspdbsrv_process = subprocess.Popen(mspdbsrv_args, | |
| 81 shell=True, | |
| 82 env=env, | |
| 83 stdout=subprocess.PIPE, | |
| 84 stderr=subprocess.STDOUT) | |
|
scottmg
2013/11/23 00:07:26
i don't think there's any stdout/stderr, but just
Sébastien Marchand
2013/11/23 04:30:14
Good point. Thanks.
| |
| 85 return True | |
| 86 | |
| 87 def _StopMsPdbSrv(self): | |
| 88 """Stop the instance of mspdbsrv.exe that has been started by this | |
| 89 helper.""" | |
| 90 mspdbsrv_stop_args = ('mspdbsrv.exe', | |
| 91 '-stop') | |
| 92 mspdbsrv_stop_process = subprocess.Popen(mspdbsrv_stop_args, | |
| 93 shell=True, | |
| 94 env=self._env, | |
| 95 stdout=subprocess.PIPE, | |
| 96 stderr=subprocess.STDOUT) | |
| 97 _, _ = mspdbsrv_stop_process.communicate() | |
|
scottmg
2013/11/23 00:07:26
and these can just be .wait() instead of .communic
Sébastien Marchand
2013/11/23 04:30:14
I'll also use call instead of Popen/communicate fo
| |
| 98 _, _ = self._mspdbsrv_process.communicate() | |
| 99 return | |
| 100 | |
| 31 def Dispatch(self, args): | 101 def Dispatch(self, args): |
| 32 """Dispatches a string command to a method.""" | 102 """Dispatches a string command to a method.""" |
| 33 if len(args) < 1: | 103 if len(args) < 1: |
| 34 raise Exception("Not enough arguments") | 104 raise Exception("Not enough arguments") |
| 35 | 105 |
| 36 method = "Exec%s" % self._CommandifyName(args[0]) | 106 method = "Exec%s" % self._CommandifyName(args[0]) |
| 37 return getattr(self, method)(*args[1:]) | 107 return getattr(self, method)(*args[1:]) |
| 38 | 108 |
| 39 def _CommandifyName(self, name_string): | 109 def _CommandifyName(self, name_string): |
| 40 """Transforms a tool name like recursive-mirror to RecursiveMirror.""" | 110 """Transforms a tool name like recursive-mirror to RecursiveMirror.""" |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 64 shutil.copytree(source, dest) | 134 shutil.copytree(source, dest) |
| 65 else: | 135 else: |
| 66 shutil.copy2(source, dest) | 136 shutil.copy2(source, dest) |
| 67 | 137 |
| 68 def ExecLinkWrapper(self, arch, *args): | 138 def ExecLinkWrapper(self, arch, *args): |
| 69 """Filter diagnostic output from link that looks like: | 139 """Filter diagnostic output from link that looks like: |
| 70 ' Creating library ui.dll.lib and object ui.dll.exp' | 140 ' Creating library ui.dll.lib and object ui.dll.exp' |
| 71 This happens when there are exports from the dll or exe. | 141 This happens when there are exports from the dll or exe. |
| 72 """ | 142 """ |
| 73 env = self._GetEnv(arch) | 143 env = self._GetEnv(arch) |
| 144 mspdbsrv_helper = MsPdbSrvHelper(args, env) | |
|
scottmg
2013/11/23 00:07:26
i'm still concerned that there's a race between th
Sébastien Marchand
2013/11/23 04:30:14
I've tried this but it was really crashy, as we're
scottmg
2013/11/23 04:44:12
Hmm, OK. :( See what Siggi thinks, but I'm worried
Sigurður Ásgeirsson
2013/11/25 16:29:57
Well, it's either safe or it isn't. It's safe iff:
Sébastien Marchand
2013/11/25 19:24:40
Ok, so I've used procmon to look at what happen in
| |
| 74 popen = subprocess.Popen(args, shell=True, env=env, | 145 popen = subprocess.Popen(args, shell=True, env=env, |
| 75 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | 146 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| 76 out, _ = popen.communicate() | 147 out, _ = popen.communicate() |
| 77 for line in out.splitlines(): | 148 for line in out.splitlines(): |
| 78 if not line.startswith(' Creating library '): | 149 if not line.startswith(' Creating library '): |
| 79 print line | 150 print line |
| 80 return popen.returncode | 151 return popen.returncode |
| 81 | 152 |
| 82 def ExecManifestWrapper(self, arch, *args): | 153 def ExecManifestWrapper(self, arch, *args): |
| 83 """Run manifest tool with environment set. Strip out undesirable warning | 154 """Run manifest tool with environment set. Strip out undesirable warning |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 167 for |arch|. If |dir| is supplied, use that as the working directory.""" | 238 for |arch|. If |dir| is supplied, use that as the working directory.""" |
| 168 env = self._GetEnv(arch) | 239 env = self._GetEnv(arch) |
| 169 args = open(rspfile).read() | 240 args = open(rspfile).read() |
| 170 dir = dir[0] if dir else None | 241 dir = dir[0] if dir else None |
| 171 popen = subprocess.Popen(args, shell=True, env=env, cwd=dir) | 242 popen = subprocess.Popen(args, shell=True, env=env, cwd=dir) |
| 172 popen.wait() | 243 popen.wait() |
| 173 return popen.returncode | 244 return popen.returncode |
| 174 | 245 |
| 175 if __name__ == '__main__': | 246 if __name__ == '__main__': |
| 176 sys.exit(main(sys.argv[1:])) | 247 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |