1#!/usr/bin/env python3 2# 3# Copyright (C) 2023 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18""" 19This script is used as a replacement for the Rust linker. It converts a linker 20command line into a rspfile that can be used during the link phase. 21""" 22 23import os 24import shutil 25import subprocess 26import sys 27 28def create_archive(out, objects, archives): 29 mricmd = f'create {out}\n' 30 for o in objects: 31 mricmd += f'addmod {o}\n' 32 for a in archives: 33 mricmd += f'addlib {a}\n' 34 mricmd += 'save\nend\n' 35 subprocess.run([os.getenv('AR'), '-M'], encoding='utf-8', input=mricmd, check=True) 36 37objects = [] 38archives = [] 39linkdirs = [] 40libs = [] 41temp_archives = [] 42version_script = None 43 44for i, arg in enumerate(sys.argv): 45 if arg == '-o': 46 out = sys.argv[i+1] 47 if arg == '-L': 48 linkdirs.append(sys.argv[i+1]) 49 if arg.startswith('-l') or arg == '-shared': 50 libs.append(arg) 51 if arg.startswith('-Wl,--version-script='): 52 version_script = arg[21:] 53 if arg[0] == '-': 54 continue 55 if arg.endswith('.o') or arg.endswith('.rmeta'): 56 objects.append(arg) 57 if arg.endswith('.rlib'): 58 if arg.startswith(os.getenv('TMPDIR')): 59 temp_archives.append(arg) 60 else: 61 archives.append(arg) 62 63create_archive(f'{out}.whole.a', objects, []) 64create_archive(f'{out}.a', [], temp_archives) 65 66with open(out, 'w') as f: 67 print(f'-Wl,--whole-archive', file=f) 68 print(f'{out}.whole.a', file=f) 69 print(f'-Wl,--no-whole-archive', file=f) 70 print(f'{out}.a', file=f) 71 for a in archives: 72 print(a, file=f) 73 for linkdir in linkdirs: 74 print(f'-L{linkdir}', file=f) 75 for l in libs: 76 print(l, file=f) 77 if version_script: 78 shutil.copyfile(version_script, f'{out}.version_script') 79 print(f'-Wl,--version-script={out}.version_script', file=f) 80