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