1# Copyright 2023 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import re 6 7 8def wrap_with_whole_archive(command, is_apple=False): 9 """Modify and return `command` such that -LinkWrapper,add-whole-archive=X 10 becomes a linking inclusion X (-lX) but wrapped in whole-archive 11 modifiers.""" 12 13 # We want to link rlibs as --whole-archive if they are part of a unit test 14 # target. This is determined by switch `-LinkWrapper,add-whole-archive`. 15 # 16 # TODO(danakj): If the linking command line gets too large we could move 17 # {{rlibs}} into the rsp file, but then this script needs to modify the rsp 18 # file instead of the command line. 19 def extract_libname(s): 20 m = re.match(r'-LinkWrapper,add-whole-archive=(.+)', s) 21 return m.group(1) 22 23 # The set of libraries we want to apply `--whole-archive`` to. 24 whole_archive_libs = [ 25 extract_libname(x) for x in command 26 if x.startswith("-LinkWrapper,add-whole-archive=") 27 ] 28 29 # Remove the arguments meant for consumption by this LinkWrapper script. 30 command = [x for x in command if not x.startswith("-LinkWrapper,")] 31 32 def has_any_suffix(string, suffixes): 33 for suffix in suffixes: 34 if string.endswith(suffix): 35 return True 36 return False 37 38 def wrap_libs_with(command, libnames, before, after): 39 out = [] 40 for arg in command: 41 # The arg is a full path to a library, we look if the the library name (a 42 # suffix of the full arg) is one of `libnames`. 43 if has_any_suffix(arg, libnames): 44 out.extend([before, arg]) 45 if after: 46 out.append(after) 47 else: 48 out.append(arg) 49 return out 50 51 if is_apple: 52 # Apply -force_load to the libraries that desire it. 53 return wrap_libs_with(command, whole_archive_libs, "-Wl,-force_load", None) 54 else: 55 # Apply --whole-archive to the libraries that desire it. 56 return wrap_libs_with(command, whole_archive_libs, "-Wl,--whole-archive", 57 "-Wl,--no-whole-archive") 58