Chromium Code Reviews| Index: pylib/gyp/win_tool.py |
| =================================================================== |
| --- pylib/gyp/win_tool.py (revision 1796) |
| +++ pylib/gyp/win_tool.py (working copy) |
| @@ -10,12 +10,17 @@ |
| """ |
| import os |
| +import re |
| import shutil |
| import subprocess |
| import sys |
| BASE_DIR = os.path.dirname(os.path.abspath(__file__)) |
| +# A regex matching an argument corresponding to a PDB filename passed as an |
| +# argument to link.exe. |
| +_LINK_EXE_PDB_ARG = re.compile('/PDB:(?P<pdb>.+\.exe\.pdb)', re.IGNORECASE) |
| +_MSPDBSRV_ENDPOINT_ENV_VAR = '_MSPDBSRV_ENDPOINT_' |
| def main(args): |
| executor = WinTool() |
| @@ -28,6 +33,67 @@ |
| """This class performs all the Windows tooling steps. The methods can either |
| be executed directly, or dispatched from an argument list.""" |
| + class MsPdbSrvHelper(object): |
| + """This is an helper class to use a unique instance of mspdbsrv.exe for the |
| + linkers linking an .exe target. This helps to reduce the memory pressure one |
| + the shared instance of mspdbsrv.exe.""" |
| + |
| + def __init__(self, env, args): |
| + self.env = env |
| + self.args = args |
| + |
| + def __enter__(self): |
| + self._MaybeStartMsPdbSrv() |
| + |
| + def __exit__(self, type, value, traceback): |
| + if _MSPDBSRV_ENDPOINT_ENV_VAR in self.env: |
| + self._StopMsPdbSrv() |
| + |
| + def _MaybeStartMsPdbSrv(self): |
| + """Starts an unique instance of mspdbsrv.exe if the given arguments are |
| + those of a linker linking a .exe target.""" |
| + if not os.environ.get('GYP_USE_SEPARATE_MSPDBSRV'): |
| + return |
| + |
| + if len(self.args) < 1: |
| + raise Exception("Not enough arguments") |
| + |
| + if self.args[0] != 'link.exe': |
| + return |
| + |
| + # Checks if this linker produces a PDB for an .exe target. If so use the |
| + # name of this PDB to generate an endpoint name for mspdbsrv.exe. |
| + endpoint_name = None |
| + for arg in self.args: |
| + m = _LINK_EXE_PDB_ARG.match(arg) |
| + if m: |
| + endpoint_name = '%s_%d' % (m.group('pdb'), os.getpid()) |
| + break |
| + |
| + if endpoint_name is None: |
| + return |
| + |
| + # Adds the appropriate environment variable. This will be read by link.exe |
| + # to know which instance of mspdbsrv.exe it should connect to (if it's |
| + # not set then the default endpoint is used). |
| + self.env[_MSPDBSRV_ENDPOINT_ENV_VAR] = endpoint_name |
| + |
| + # Starts the mspdbsrv.exe instance manually. We could specify the endpoint |
| + # in the command line but it's redundant with setting it in the |
| + # environment block. Starting this process manually allows us to wait for |
| + # its completion once the link step is finished. This is required to |
| + # respect the dependencies between the different targets. |
| + mspdbsrv_args = ('mspdbsrv.exe', '-start', '-spawn') |
| + subprocess.Popen(mspdbsrv_args, shell=True, env=self.env) |
| + |
| + def _StopMsPdbSrv(self): |
| + """Stop the instance of mspdbsrv.exe that has been started by this |
| + helper.""" |
| + mspdbsrv_stop_args = ('mspdbsrv.exe', '-stop') |
| + mspdbsrv_stop_process = subprocess.call(mspdbsrv_stop_args, |
| + shell=True, |
| + env=self.env) |
| + |
| def Dispatch(self, args): |
| """Dispatches a string command to a method.""" |
| if len(args) < 1: |
| @@ -71,13 +137,17 @@ |
| This happens when there are exports from the dll or exe. |
| """ |
| env = self._GetEnv(arch) |
| - popen = subprocess.Popen(args, shell=True, env=env, |
| - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| - out, _ = popen.communicate() |
| - for line in out.splitlines(): |
| - if not line.startswith(' Creating library '): |
| - print line |
| - return popen.returncode |
| + with WinTool.MsPdbSrvHelper(env, args): |
| + link_wrapper = subprocess.Popen(args, |
|
scottmg
2013/11/27 20:00:44
if you want to change this, it shouldn't be "link_
Sébastien Marchand
2013/11/27 20:29:55
Done.
|
| + shell=True, |
| + env=env, |
| + stdout=subprocess.PIPE, |
| + stderr=subprocess.STDOUT) |
| + out, _ = link_wrapper.communicate() |
| + for line in out.splitlines(): |
| + if not line.startswith(' Creating library '): |
| + print line |
| + return link_wrapper.returncode |
| def ExecManifestWrapper(self, arch, *args): |
| """Run manifest tool with environment set. Strip out undesirable warning |
| @@ -168,9 +238,7 @@ |
| env = self._GetEnv(arch) |
| args = open(rspfile).read() |
| dir = dir[0] if dir else None |
| - popen = subprocess.Popen(args, shell=True, env=env, cwd=dir) |
| - popen.wait() |
| - return popen.returncode |
| + return subprocess.call(args, shell=True, env=env, cwd=dir) |
| if __name__ == '__main__': |
| sys.exit(main(sys.argv[1:])) |