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 shutil | 13 import shutil |
14 import subprocess | 14 import subprocess |
15 import sys | 15 import sys |
| 16 import win32con |
| 17 import win32file |
| 18 import pywintypes |
16 | 19 |
17 | 20 |
18 def main(args): | 21 def main(args): |
19 executor = WinTool() | 22 executor = WinTool() |
20 exit_code = executor.Dispatch(args) | 23 exit_code = executor.Dispatch(args) |
21 if exit_code is not None: | 24 if exit_code is not None: |
22 sys.exit(exit_code) | 25 sys.exit(exit_code) |
23 | 26 |
24 | 27 |
| 28 class LinkLock(object): |
| 29 """A flock-style lock to limit the number of concurrent links to one. Based on |
| 30 http://code.activestate.com/recipes/65203-portalocker-cross-platform-posixnt-a
pi-for-flock-s/ |
| 31 """ |
| 32 def __enter__(self): |
| 33 self.file = open('LinkLock', 'w+') |
| 34 self.file_handle = win32file._get_osfhandle(self.file.fileno()) |
| 35 win32file.LockFileEx(self.file_handle, win32con.LOCKFILE_EXCLUSIVE_LOCK, |
| 36 0, -0x10000, pywintypes.OVERLAPPED()) |
| 37 |
| 38 def __exit__(self, type, value, traceback): |
| 39 win32file.UnlockFileEx( |
| 40 self.file_handle, 0, -0x10000, pywintypes.OVERLAPPED()) |
| 41 self.file.close() |
| 42 |
| 43 |
25 class WinTool(object): | 44 class WinTool(object): |
26 """This class performs all the Windows tooling steps. The methods can either | 45 """This class performs all the Windows tooling steps. The methods can either |
27 be executed directly, or dispatched from an argument list.""" | 46 be executed directly, or dispatched from an argument list.""" |
28 | 47 |
29 def Dispatch(self, args): | 48 def Dispatch(self, args): |
30 """Dispatches a string command to a method.""" | 49 """Dispatches a string command to a method.""" |
31 if len(args) < 1: | 50 if len(args) < 1: |
32 raise Exception("Not enough arguments") | 51 raise Exception("Not enough arguments") |
33 | 52 |
34 method = "Exec%s" % self._CommandifyName(args[0]) | 53 method = "Exec%s" % self._CommandifyName(args[0]) |
(...skipping 26 matching lines...) Expand all Loading... |
61 if os.path.isdir(source): | 80 if os.path.isdir(source): |
62 shutil.copytree(source, dest) | 81 shutil.copytree(source, dest) |
63 else: | 82 else: |
64 shutil.copy2(source, dest) | 83 shutil.copy2(source, dest) |
65 | 84 |
66 def ExecLinkWrapper(self, arch, *args): | 85 def ExecLinkWrapper(self, arch, *args): |
67 """Filter diagnostic output from link that looks like: | 86 """Filter diagnostic output from link that looks like: |
68 ' Creating library ui.dll.lib and object ui.dll.exp' | 87 ' Creating library ui.dll.lib and object ui.dll.exp' |
69 This happens when there are exports from the dll or exe. | 88 This happens when there are exports from the dll or exe. |
70 """ | 89 """ |
71 env = self._GetEnv(arch) | 90 with LinkLock(): |
72 popen = subprocess.Popen(args, shell=True, env=env, | 91 env = self._GetEnv(arch) |
73 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | 92 popen = subprocess.Popen(args, shell=True, env=env, |
74 out, _ = popen.communicate() | 93 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
75 for line in out.splitlines(): | 94 out, _ = popen.communicate() |
76 if not line.startswith(' Creating library '): | 95 for line in out.splitlines(): |
77 print line | 96 if not line.startswith(' Creating library '): |
78 return popen.returncode | 97 print line |
| 98 return popen.returncode |
79 | 99 |
80 def ExecManifestWrapper(self, arch, *args): | 100 def ExecManifestWrapper(self, arch, *args): |
81 """Run manifest tool with environment set. Strip out undesirable warning | 101 """Run manifest tool with environment set. Strip out undesirable warning |
82 (some XML blocks are recognized by the OS loader, but not the manifest | 102 (some XML blocks are recognized by the OS loader, but not the manifest |
83 tool).""" | 103 tool).""" |
84 env = self._GetEnv(arch) | 104 env = self._GetEnv(arch) |
85 popen = subprocess.Popen(args, shell=True, env=env, | 105 popen = subprocess.Popen(args, shell=True, env=env, |
86 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | 106 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
87 out, _ = popen.communicate() | 107 out, _ = popen.communicate() |
88 for line in out.splitlines(): | 108 for line in out.splitlines(): |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 for |arch|. If |dir| is supplied, use that as the working directory.""" | 185 for |arch|. If |dir| is supplied, use that as the working directory.""" |
166 env = self._GetEnv(arch) | 186 env = self._GetEnv(arch) |
167 args = open(rspfile).read() | 187 args = open(rspfile).read() |
168 dir = dir[0] if dir else None | 188 dir = dir[0] if dir else None |
169 popen = subprocess.Popen(args, shell=True, env=env, cwd=dir) | 189 popen = subprocess.Popen(args, shell=True, env=env, cwd=dir) |
170 popen.wait() | 190 popen.wait() |
171 return popen.returncode | 191 return popen.returncode |
172 | 192 |
173 if __name__ == '__main__': | 193 if __name__ == '__main__': |
174 sys.exit(main(sys.argv[1:])) | 194 sys.exit(main(sys.argv[1:])) |
OLD | NEW |