OLD | NEW |
1 # Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2016 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Helper functions for gcc_toolchain.gni wrappers.""" | 5 """Helper functions for gcc_toolchain.gni wrappers.""" |
6 | 6 |
| 7 import gzip |
7 import os | 8 import os |
8 import re | 9 import re |
9 import subprocess | 10 import subprocess |
10 import shlex | 11 import shlex |
| 12 import shutil |
11 import sys | 13 import sys |
| 14 import threading |
12 | 15 |
13 _BAT_PREFIX = 'cmd /c call ' | 16 _BAT_PREFIX = 'cmd /c call ' |
14 _WHITELIST_RE = re.compile('whitelisted_resource_(?P<resource_id>[0-9]+)') | 17 _WHITELIST_RE = re.compile('whitelisted_resource_(?P<resource_id>[0-9]+)') |
15 | 18 |
16 | 19 |
| 20 def _GzipThenDelete(src_path, dest_path): |
| 21 # Results for Android map file with GCC on a z620: |
| 22 # Uncompressed: 207MB |
| 23 # gzip -9: 16.4MB, takes 8.7 seconds. |
| 24 # gzip -1: 21.8MB, takes 2.0 seconds. |
| 25 # Piping directly from the linker via -print-map (or via -Map with a fifo) |
| 26 # adds a whopping 30-45 seconds! |
| 27 with open(src_path, 'rb') as f_in, gzip.GzipFile(dest_path, 'wb', 1) as f_out: |
| 28 shutil.copyfileobj(f_in, f_out) |
| 29 os.unlink(src_path) |
| 30 |
| 31 |
17 def CommandToRun(command): | 32 def CommandToRun(command): |
18 """Generates commands compatible with Windows. | 33 """Generates commands compatible with Windows. |
19 | 34 |
20 When running on a Windows host and using a toolchain whose tools are | 35 When running on a Windows host and using a toolchain whose tools are |
21 actually wrapper scripts (i.e. .bat files on Windows) rather than binary | 36 actually wrapper scripts (i.e. .bat files on Windows) rather than binary |
22 executables, the |command| to run has to be prefixed with this magic. | 37 executables, the |command| to run has to be prefixed with this magic. |
23 The GN toolchain definitions take care of that for when GN/Ninja is | 38 The GN toolchain definitions take care of that for when GN/Ninja is |
24 running the tool directly. When that command is passed in to this | 39 running the tool directly. When that command is passed in to this |
25 script, it appears as a unitary string but needs to be split up so that | 40 script, it appears as a unitary string but needs to be split up so that |
26 just 'cmd' is the actual command given to Python's subprocess module. | 41 just 'cmd' is the actual command given to Python's subprocess module. |
27 | 42 |
28 Args: | 43 Args: |
29 command: List containing the UNIX style |command|. | 44 command: List containing the UNIX style |command|. |
30 | 45 |
31 Returns: | 46 Returns: |
32 A list containing the Windows version of the |command|. | 47 A list containing the Windows version of the |command|. |
33 """ | 48 """ |
34 if command[0].startswith(_BAT_PREFIX): | 49 if command[0].startswith(_BAT_PREFIX): |
35 command = command[0].split(None, 3) + command[1:] | 50 command = command[0].split(None, 3) + command[1:] |
36 return command | 51 return command |
37 | 52 |
38 | 53 |
| 54 def RunLinkWithOptionalMapFile(command, env=None, map_file=None): |
| 55 """Runs the given command, adding in -Wl,-Map when |map_file| is given. |
| 56 |
| 57 Also takes care of gzipping when |map_file| ends with .gz. |
| 58 |
| 59 Args: |
| 60 command: List of arguments comprising the command. |
| 61 env: Environment variables. |
| 62 map_file: Path to output map_file. |
| 63 |
| 64 Returns: |
| 65 The exit code of running |command|. |
| 66 """ |
| 67 tmp_map_path = None |
| 68 if map_file and map_file.endswith('.gz'): |
| 69 tmp_map_path = map_file + '.tmp' |
| 70 command.append('-Wl,-Map,' + tmp_map_path) |
| 71 elif map_file: |
| 72 command.append('-Wl,-Map,' + map_file) |
| 73 |
| 74 result = subprocess.call(command, env=env) |
| 75 |
| 76 if tmp_map_path and result == 0: |
| 77 threading.Thread( |
| 78 target=lambda: _GzipThenDelete(tmp_map_path, map_file)).start() |
| 79 elif tmp_map_path and os.path.exists(tmp_map_path): |
| 80 os.unlink(tmp_map_path) |
| 81 |
| 82 return result |
| 83 |
| 84 |
39 def ResolveRspLinks(inputs): | 85 def ResolveRspLinks(inputs): |
40 """Return a list of files contained in a response file. | 86 """Return a list of files contained in a response file. |
41 | 87 |
42 Args: | 88 Args: |
43 inputs: A command containing rsp files. | 89 inputs: A command containing rsp files. |
44 | 90 |
45 Returns: | 91 Returns: |
46 A set containing the rsp file content.""" | 92 A set containing the rsp file content.""" |
47 rspfiles = [a[1:] for a in inputs if a.startswith('@')] | 93 rspfiles = [a[1:] for a in inputs if a.startswith('@')] |
48 resolved = set() | 94 resolved = set() |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 def CaptureCommandStderr(command, env=None): | 141 def CaptureCommandStderr(command, env=None): |
96 """Returns the stderr of a command. | 142 """Returns the stderr of a command. |
97 | 143 |
98 Args: | 144 Args: |
99 command: A list containing the command and arguments. | 145 command: A list containing the command and arguments. |
100 env: Environment variables for the new process. | 146 env: Environment variables for the new process. |
101 """ | 147 """ |
102 child = subprocess.Popen(command, stderr=subprocess.PIPE, env=env) | 148 child = subprocess.Popen(command, stderr=subprocess.PIPE, env=env) |
103 _, stderr = child.communicate() | 149 _, stderr = child.communicate() |
104 return child.returncode, stderr | 150 return child.returncode, stderr |
OLD | NEW |