1*8975f5c5SAndroid Build Coastguard Worker# Copyright 2020 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"""Strip arm64e architecture from a binary if present.""" 5*8975f5c5SAndroid Build Coastguard Worker 6*8975f5c5SAndroid Build Coastguard Workerimport argparse 7*8975f5c5SAndroid Build Coastguard Workerimport os 8*8975f5c5SAndroid Build Coastguard Workerimport shutil 9*8975f5c5SAndroid Build Coastguard Workerimport subprocess 10*8975f5c5SAndroid Build Coastguard Workerimport sys 11*8975f5c5SAndroid Build Coastguard Worker 12*8975f5c5SAndroid Build Coastguard Worker 13*8975f5c5SAndroid Build Coastguard Workerdef check_output(command): 14*8975f5c5SAndroid Build Coastguard Worker """Returns the output from |command| or propagates error, quitting script.""" 15*8975f5c5SAndroid Build Coastguard Worker process = subprocess.Popen( 16*8975f5c5SAndroid Build Coastguard Worker command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 17*8975f5c5SAndroid Build Coastguard Worker outs, errs = process.communicate() 18*8975f5c5SAndroid Build Coastguard Worker if process.returncode: 19*8975f5c5SAndroid Build Coastguard Worker sys.stderr.write('error: command failed with retcode %d: %s\n\n' % 20*8975f5c5SAndroid Build Coastguard Worker (process.returncode, ' '.join(map(repr, command)))) 21*8975f5c5SAndroid Build Coastguard Worker sys.stderr.write(errs.decode('UTF-8', errors='ignore')) 22*8975f5c5SAndroid Build Coastguard Worker sys.exit(process.returncode) 23*8975f5c5SAndroid Build Coastguard Worker return outs.decode('UTF-8') 24*8975f5c5SAndroid Build Coastguard Worker 25*8975f5c5SAndroid Build Coastguard Worker 26*8975f5c5SAndroid Build Coastguard Workerdef check_call(command): 27*8975f5c5SAndroid Build Coastguard Worker """Invokes |command| or propagates error.""" 28*8975f5c5SAndroid Build Coastguard Worker check_output(command) 29*8975f5c5SAndroid Build Coastguard Worker 30*8975f5c5SAndroid Build Coastguard Worker 31*8975f5c5SAndroid Build Coastguard Workerdef parse_args(args): 32*8975f5c5SAndroid Build Coastguard Worker """Parses the command-line.""" 33*8975f5c5SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 34*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--input', required=True, help='Path to input binary') 35*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--output', required=True, help='Path to output binary') 36*8975f5c5SAndroid Build Coastguard Worker parser.add_argument('--xcode-version', required=True, help='Version of Xcode') 37*8975f5c5SAndroid Build Coastguard Worker return parser.parse_args(args) 38*8975f5c5SAndroid Build Coastguard Worker 39*8975f5c5SAndroid Build Coastguard Worker 40*8975f5c5SAndroid Build Coastguard Workerdef get_archs(path): 41*8975f5c5SAndroid Build Coastguard Worker """Extracts the architectures present in binary at |path|.""" 42*8975f5c5SAndroid Build Coastguard Worker outputs = check_output(["xcrun", "lipo", "-info", os.path.abspath(path)]) 43*8975f5c5SAndroid Build Coastguard Worker return outputs.split(': ')[-1].split() 44*8975f5c5SAndroid Build Coastguard Worker 45*8975f5c5SAndroid Build Coastguard Worker 46*8975f5c5SAndroid Build Coastguard Workerdef main(args): 47*8975f5c5SAndroid Build Coastguard Worker parsed = parse_args(args) 48*8975f5c5SAndroid Build Coastguard Worker 49*8975f5c5SAndroid Build Coastguard Worker outdir = os.path.dirname(parsed.output) 50*8975f5c5SAndroid Build Coastguard Worker if not os.path.isdir(outdir): 51*8975f5c5SAndroid Build Coastguard Worker os.makedirs(outdir) 52*8975f5c5SAndroid Build Coastguard Worker 53*8975f5c5SAndroid Build Coastguard Worker if os.path.exists(parsed.output): 54*8975f5c5SAndroid Build Coastguard Worker os.unlink(parsed.output) 55*8975f5c5SAndroid Build Coastguard Worker 56*8975f5c5SAndroid Build Coastguard Worker # As "lipo" fails with an error if asked to remove an architecture that is 57*8975f5c5SAndroid Build Coastguard Worker # not included, only use it if "arm64e" is present in the binary. Otherwise 58*8975f5c5SAndroid Build Coastguard Worker # simply copy the file. 59*8975f5c5SAndroid Build Coastguard Worker if 'arm64e' in get_archs(parsed.input): 60*8975f5c5SAndroid Build Coastguard Worker check_output([ 61*8975f5c5SAndroid Build Coastguard Worker "xcrun", "lipo", "-remove", "arm64e", "-output", 62*8975f5c5SAndroid Build Coastguard Worker os.path.abspath(parsed.output), 63*8975f5c5SAndroid Build Coastguard Worker os.path.abspath(parsed.input) 64*8975f5c5SAndroid Build Coastguard Worker ]) 65*8975f5c5SAndroid Build Coastguard Worker else: 66*8975f5c5SAndroid Build Coastguard Worker shutil.copy(parsed.input, parsed.output) 67*8975f5c5SAndroid Build Coastguard Worker 68*8975f5c5SAndroid Build Coastguard Worker 69*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__': 70*8975f5c5SAndroid Build Coastguard Worker main(sys.argv[1:]) 71