diff --git a/build/toolchain/apple/linker_driver.py b/build/toolchain/apple/linker_driver.py index 0632230cf..798442534 100755 --- a/build/toolchain/apple/linker_driver.py +++ b/build/toolchain/apple/linker_driver.py @@ -7,6 +7,7 @@ import os import os.path import re +import shlex import shutil import subprocess import sys @@ -113,6 +114,53 @@ class LinkerDriver(object): # The temporary directory for intermediate LTO object files. If it # exists, it will clean itself up on script exit. self._object_path_lto = None + self._temp_rsp_files = [] + + def _sanitize_rsp_arg(self, arg): + if not arg.startswith('@'): + return arg + rsp_path = arg[1:] + if not os.path.isfile(rsp_path): + return arg + + try: + with open(rsp_path, 'r', encoding='utf-8') as f: + rsp_content = f.read() + except OSError: + return arg + + tokens = shlex.split(rsp_content, posix=True) + sanitized = [] + changed = False + i = 0 + while i < len(tokens): + tok = tokens[i] + if tok == '-L' and i + 1 < len(tokens): + lib_dir = tokens[i + 1] + if not os.path.isdir(lib_dir): + changed = True + i += 2 + continue + elif tok.startswith('-L') and len(tok) > 2: + lib_dir = tok[2:] + if not os.path.isdir(lib_dir): + changed = True + i += 1 + continue + sanitized.append(tok) + i += 1 + + if not changed: + return arg + + fd, temp_path = tempfile.mkstemp(prefix='linker_driver_', suffix='.rsp') + os.close(fd) + with open(temp_path, 'w', encoding='utf-8') as f: + for tok in sanitized: + f.write(tok) + f.write('\n') + self._temp_rsp_files.append(temp_path) + return '@' + temp_path def run(self): """Runs the linker driver, separating out the main compiler driver's @@ -135,11 +183,25 @@ class LinkerDriver(object): assert driver_action[0] not in linker_driver_actions linker_driver_actions[driver_action[0]] = driver_action[1] else: + if arg.startswith('@'): + arg = self._sanitize_rsp_arg(arg) # TODO(crbug.com/1446796): On Apple, the linker command line # produced by rustc for LTO includes these arguments, but the # Apple linker doesn't accept them. # Upstream bug: https://github.com/rust-lang/rust/issues/60059 BAD_RUSTC_ARGS = '-Wl,-plugin-opt=O[0-9],-plugin-opt=mcpu=.*' + if arg == '-Wl,-fatal_warnings': + # Some host link steps on Apple Silicon produce benign + # warnings from injected search paths (e.g. /usr/local/lib + # missing). Don't fail the whole build on those warnings. + continue + if arg.startswith('-L') and len(arg) > 2: + # Some environments inject non-existent library search + # paths (e.g. /usr/local/lib on Apple Silicon). lld treats + # them as hard errors, so skip missing -L entries. + lib_dir = arg[2:] + if not os.path.isdir(lib_dir): + continue if not re.match(BAD_RUSTC_ARGS, arg): compiler_driver_args.append(arg) @@ -185,6 +247,9 @@ class LinkerDriver(object): # Re-report the original failure. raise + finally: + for path in self._temp_rsp_files: + _remove_path(path) def _get_linker_output(self): """Returns the value of the output argument to the linker."""