xref: /aosp_15_r20/external/angle/build/toolchain/wrapper_utils.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker# Copyright 2016 The Chromium Authors
2*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
3*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file.
4*8975f5c5SAndroid Build Coastguard Worker
5*8975f5c5SAndroid Build Coastguard Worker"""Helper functions for gcc_toolchain.gni wrappers."""
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Workerimport gzip
8*8975f5c5SAndroid Build Coastguard Workerimport os
9*8975f5c5SAndroid Build Coastguard Workerimport re
10*8975f5c5SAndroid Build Coastguard Workerimport subprocess
11*8975f5c5SAndroid Build Coastguard Workerimport shlex
12*8975f5c5SAndroid Build Coastguard Workerimport shutil
13*8975f5c5SAndroid Build Coastguard Workerimport sys
14*8975f5c5SAndroid Build Coastguard Workerimport threading
15*8975f5c5SAndroid Build Coastguard Worker
16*8975f5c5SAndroid Build Coastguard Workerimport whole_archive
17*8975f5c5SAndroid Build Coastguard Worker
18*8975f5c5SAndroid Build Coastguard Worker_BAT_PREFIX = 'cmd /c call '
19*8975f5c5SAndroid Build Coastguard Worker
20*8975f5c5SAndroid Build Coastguard Worker
21*8975f5c5SAndroid Build Coastguard Workerdef _GzipThenDelete(src_path, dest_path):
22*8975f5c5SAndroid Build Coastguard Worker  # Results for Android map file with GCC on a z620:
23*8975f5c5SAndroid Build Coastguard Worker  # Uncompressed: 207MB
24*8975f5c5SAndroid Build Coastguard Worker  # gzip -9: 16.4MB, takes 8.7 seconds.
25*8975f5c5SAndroid Build Coastguard Worker  # gzip -1: 21.8MB, takes 2.0 seconds.
26*8975f5c5SAndroid Build Coastguard Worker  # Piping directly from the linker via -print-map (or via -Map with a fifo)
27*8975f5c5SAndroid Build Coastguard Worker  # adds a whopping 30-45 seconds!
28*8975f5c5SAndroid Build Coastguard Worker  with open(src_path, 'rb') as f_in, gzip.GzipFile(dest_path, 'wb', 1) as f_out:
29*8975f5c5SAndroid Build Coastguard Worker    shutil.copyfileobj(f_in, f_out)
30*8975f5c5SAndroid Build Coastguard Worker  os.unlink(src_path)
31*8975f5c5SAndroid Build Coastguard Worker
32*8975f5c5SAndroid Build Coastguard Worker
33*8975f5c5SAndroid Build Coastguard Workerdef CommandToRun(command):
34*8975f5c5SAndroid Build Coastguard Worker  """Generates commands compatible with Windows.
35*8975f5c5SAndroid Build Coastguard Worker
36*8975f5c5SAndroid Build Coastguard Worker  When running on a Windows host and using a toolchain whose tools are
37*8975f5c5SAndroid Build Coastguard Worker  actually wrapper scripts (i.e. .bat files on Windows) rather than binary
38*8975f5c5SAndroid Build Coastguard Worker  executables, the |command| to run has to be prefixed with this magic.
39*8975f5c5SAndroid Build Coastguard Worker  The GN toolchain definitions take care of that for when GN/Ninja is
40*8975f5c5SAndroid Build Coastguard Worker  running the tool directly.  When that command is passed in to this
41*8975f5c5SAndroid Build Coastguard Worker  script, it appears as a unitary string but needs to be split up so that
42*8975f5c5SAndroid Build Coastguard Worker  just 'cmd' is the actual command given to Python's subprocess module.
43*8975f5c5SAndroid Build Coastguard Worker
44*8975f5c5SAndroid Build Coastguard Worker  Args:
45*8975f5c5SAndroid Build Coastguard Worker    command: List containing the UNIX style |command|.
46*8975f5c5SAndroid Build Coastguard Worker
47*8975f5c5SAndroid Build Coastguard Worker  Returns:
48*8975f5c5SAndroid Build Coastguard Worker    A list containing the Windows version of the |command|.
49*8975f5c5SAndroid Build Coastguard Worker  """
50*8975f5c5SAndroid Build Coastguard Worker  if command[0].startswith(_BAT_PREFIX):
51*8975f5c5SAndroid Build Coastguard Worker    command = command[0].split(None, 3) + command[1:]
52*8975f5c5SAndroid Build Coastguard Worker  return command
53*8975f5c5SAndroid Build Coastguard Worker
54*8975f5c5SAndroid Build Coastguard Worker
55*8975f5c5SAndroid Build Coastguard Workerdef RunLinkWithOptionalMapFile(command, env=None, map_file=None):
56*8975f5c5SAndroid Build Coastguard Worker  """Runs the given command, adding in -Wl,-Map when |map_file| is given.
57*8975f5c5SAndroid Build Coastguard Worker
58*8975f5c5SAndroid Build Coastguard Worker  Also takes care of gzipping when |map_file| ends with .gz.
59*8975f5c5SAndroid Build Coastguard Worker
60*8975f5c5SAndroid Build Coastguard Worker  Args:
61*8975f5c5SAndroid Build Coastguard Worker    command: List of arguments comprising the command.
62*8975f5c5SAndroid Build Coastguard Worker    env: Environment variables.
63*8975f5c5SAndroid Build Coastguard Worker    map_file: Path to output map_file.
64*8975f5c5SAndroid Build Coastguard Worker
65*8975f5c5SAndroid Build Coastguard Worker  Returns:
66*8975f5c5SAndroid Build Coastguard Worker    The exit code of running |command|.
67*8975f5c5SAndroid Build Coastguard Worker  """
68*8975f5c5SAndroid Build Coastguard Worker  tmp_map_path = None
69*8975f5c5SAndroid Build Coastguard Worker  if map_file and map_file.endswith('.gz'):
70*8975f5c5SAndroid Build Coastguard Worker    tmp_map_path = map_file + '.tmp'
71*8975f5c5SAndroid Build Coastguard Worker    command.append('-Wl,-Map,' + tmp_map_path)
72*8975f5c5SAndroid Build Coastguard Worker  elif map_file:
73*8975f5c5SAndroid Build Coastguard Worker    command.append('-Wl,-Map,' + map_file)
74*8975f5c5SAndroid Build Coastguard Worker
75*8975f5c5SAndroid Build Coastguard Worker  # We want to link rlibs as --whole-archive if they are part of a unit test
76*8975f5c5SAndroid Build Coastguard Worker  # target. This is determined by switch `-LinkWrapper,add-whole-archive`.
77*8975f5c5SAndroid Build Coastguard Worker  command = whole_archive.wrap_with_whole_archive(command)
78*8975f5c5SAndroid Build Coastguard Worker
79*8975f5c5SAndroid Build Coastguard Worker  result = subprocess.call(command, env=env)
80*8975f5c5SAndroid Build Coastguard Worker
81*8975f5c5SAndroid Build Coastguard Worker  if tmp_map_path and result == 0:
82*8975f5c5SAndroid Build Coastguard Worker    threading.Thread(
83*8975f5c5SAndroid Build Coastguard Worker        target=lambda: _GzipThenDelete(tmp_map_path, map_file)).start()
84*8975f5c5SAndroid Build Coastguard Worker  elif tmp_map_path and os.path.exists(tmp_map_path):
85*8975f5c5SAndroid Build Coastguard Worker    os.unlink(tmp_map_path)
86*8975f5c5SAndroid Build Coastguard Worker
87*8975f5c5SAndroid Build Coastguard Worker  return result
88*8975f5c5SAndroid Build Coastguard Worker
89*8975f5c5SAndroid Build Coastguard Worker
90*8975f5c5SAndroid Build Coastguard Workerdef CaptureCommandStderr(command, env=None):
91*8975f5c5SAndroid Build Coastguard Worker  """Returns the stderr of a command.
92*8975f5c5SAndroid Build Coastguard Worker
93*8975f5c5SAndroid Build Coastguard Worker  Args:
94*8975f5c5SAndroid Build Coastguard Worker    command: A list containing the command and arguments.
95*8975f5c5SAndroid Build Coastguard Worker    env: Environment variables for the new process.
96*8975f5c5SAndroid Build Coastguard Worker  """
97*8975f5c5SAndroid Build Coastguard Worker  child = subprocess.Popen(command, stderr=subprocess.PIPE, env=env)
98*8975f5c5SAndroid Build Coastguard Worker  _, stderr = child.communicate()
99*8975f5c5SAndroid Build Coastguard Worker  return child.returncode, stderr
100