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