1*333d2b36SAndroid Build Coastguard Worker#!/usr/bin/env python 2*333d2b36SAndroid Build Coastguard Worker# 3*333d2b36SAndroid Build Coastguard Worker# Copyright (C) 2020 The Android Open Source Project 4*333d2b36SAndroid Build Coastguard Worker# 5*333d2b36SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*333d2b36SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*333d2b36SAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*333d2b36SAndroid Build Coastguard Worker# 9*333d2b36SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*333d2b36SAndroid Build Coastguard Worker# 11*333d2b36SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*333d2b36SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*333d2b36SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*333d2b36SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*333d2b36SAndroid Build Coastguard Worker# limitations under the License. 16*333d2b36SAndroid Build Coastguard Worker""" A tool to convert json file into pb with linker config format.""" 17*333d2b36SAndroid Build Coastguard Worker 18*333d2b36SAndroid Build Coastguard Workerimport argparse 19*333d2b36SAndroid Build Coastguard Workerimport collections 20*333d2b36SAndroid Build Coastguard Workerimport json 21*333d2b36SAndroid Build Coastguard Workerimport os 22*333d2b36SAndroid Build Coastguard Workerimport sys 23*333d2b36SAndroid Build Coastguard Worker 24*333d2b36SAndroid Build Coastguard Workerimport linker_config_pb2 #pylint: disable=import-error 25*333d2b36SAndroid Build Coastguard Workerfrom google.protobuf.descriptor import FieldDescriptor 26*333d2b36SAndroid Build Coastguard Workerfrom google.protobuf.json_format import ParseDict 27*333d2b36SAndroid Build Coastguard Workerfrom google.protobuf.text_format import MessageToString 28*333d2b36SAndroid Build Coastguard Worker 29*333d2b36SAndroid Build Coastguard Worker 30*333d2b36SAndroid Build Coastguard Workerdef LoadJsonMessage(path): 31*333d2b36SAndroid Build Coastguard Worker """ 32*333d2b36SAndroid Build Coastguard Worker Loads a message from a .json file with `//` comments strippedfor convenience. 33*333d2b36SAndroid Build Coastguard Worker """ 34*333d2b36SAndroid Build Coastguard Worker json_content = '' 35*333d2b36SAndroid Build Coastguard Worker with open(path) as f: 36*333d2b36SAndroid Build Coastguard Worker for line in f: 37*333d2b36SAndroid Build Coastguard Worker if not line.lstrip().startswith('//'): 38*333d2b36SAndroid Build Coastguard Worker json_content += line 39*333d2b36SAndroid Build Coastguard Worker obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict) 40*333d2b36SAndroid Build Coastguard Worker return ParseDict(obj, linker_config_pb2.LinkerConfig()) 41*333d2b36SAndroid Build Coastguard Worker 42*333d2b36SAndroid Build Coastguard Worker 43*333d2b36SAndroid Build Coastguard Workerdef Proto(args): 44*333d2b36SAndroid Build Coastguard Worker """ 45*333d2b36SAndroid Build Coastguard Worker Merges input json files (--source) into a protobuf message (--output). 46*333d2b36SAndroid Build Coastguard Worker Fails if the output file exists. Set --force or --append to deal with the existing 47*333d2b36SAndroid Build Coastguard Worker output file. 48*333d2b36SAndroid Build Coastguard Worker --force to overwrite the output file with the input (.json files). 49*333d2b36SAndroid Build Coastguard Worker --append to append the input to the output file. 50*333d2b36SAndroid Build Coastguard Worker """ 51*333d2b36SAndroid Build Coastguard Worker pb = linker_config_pb2.LinkerConfig() 52*333d2b36SAndroid Build Coastguard Worker if os.path.isfile(args.output): 53*333d2b36SAndroid Build Coastguard Worker if args.force: 54*333d2b36SAndroid Build Coastguard Worker pass 55*333d2b36SAndroid Build Coastguard Worker elif args.append: 56*333d2b36SAndroid Build Coastguard Worker with open(args.output, 'rb') as f: 57*333d2b36SAndroid Build Coastguard Worker pb.ParseFromString(f.read()) 58*333d2b36SAndroid Build Coastguard Worker else: 59*333d2b36SAndroid Build Coastguard Worker sys.stderr.write(f'Error: {args.output} exists. Use --force or --append.\n') 60*333d2b36SAndroid Build Coastguard Worker sys.exit(1) 61*333d2b36SAndroid Build Coastguard Worker 62*333d2b36SAndroid Build Coastguard Worker if args.source: 63*333d2b36SAndroid Build Coastguard Worker for input in args.source.split(':'): 64*333d2b36SAndroid Build Coastguard Worker pb.MergeFrom(LoadJsonMessage(input)) 65*333d2b36SAndroid Build Coastguard Worker 66*333d2b36SAndroid Build Coastguard Worker ValidateAndWriteAsPbFile(pb, args.output) 67*333d2b36SAndroid Build Coastguard Worker 68*333d2b36SAndroid Build Coastguard Worker 69*333d2b36SAndroid Build Coastguard Workerdef Print(args): 70*333d2b36SAndroid Build Coastguard Worker with open(args.source, 'rb') as f: 71*333d2b36SAndroid Build Coastguard Worker pb = linker_config_pb2.LinkerConfig() 72*333d2b36SAndroid Build Coastguard Worker pb.ParseFromString(f.read()) 73*333d2b36SAndroid Build Coastguard Worker print(MessageToString(pb)) 74*333d2b36SAndroid Build Coastguard Worker 75*333d2b36SAndroid Build Coastguard Worker 76*333d2b36SAndroid Build Coastguard Workerdef SystemProvide(args): 77*333d2b36SAndroid Build Coastguard Worker pb = linker_config_pb2.LinkerConfig() 78*333d2b36SAndroid Build Coastguard Worker with open(args.source, 'rb') as f: 79*333d2b36SAndroid Build Coastguard Worker pb.ParseFromString(f.read()) 80*333d2b36SAndroid Build Coastguard Worker libraries = args.value.split() 81*333d2b36SAndroid Build Coastguard Worker 82*333d2b36SAndroid Build Coastguard Worker def IsInLibPath(lib_name): 83*333d2b36SAndroid Build Coastguard Worker lib_path = os.path.join(args.system, 'lib', lib_name) 84*333d2b36SAndroid Build Coastguard Worker lib64_path = os.path.join(args.system, 'lib64', lib_name) 85*333d2b36SAndroid Build Coastguard Worker return os.path.exists(lib_path) or os.path.islink( 86*333d2b36SAndroid Build Coastguard Worker lib_path) or os.path.exists(lib64_path) or os.path.islink( 87*333d2b36SAndroid Build Coastguard Worker lib64_path) 88*333d2b36SAndroid Build Coastguard Worker 89*333d2b36SAndroid Build Coastguard Worker installed_libraries = [lib for lib in libraries if IsInLibPath(lib)] 90*333d2b36SAndroid Build Coastguard Worker for item in installed_libraries: 91*333d2b36SAndroid Build Coastguard Worker if item not in getattr(pb, 'provideLibs'): 92*333d2b36SAndroid Build Coastguard Worker getattr(pb, 'provideLibs').append(item) 93*333d2b36SAndroid Build Coastguard Worker 94*333d2b36SAndroid Build Coastguard Worker ValidateAndWriteAsPbFile(pb, args.output) 95*333d2b36SAndroid Build Coastguard Worker 96*333d2b36SAndroid Build Coastguard Worker 97*333d2b36SAndroid Build Coastguard Workerdef Append(args): 98*333d2b36SAndroid Build Coastguard Worker pb = linker_config_pb2.LinkerConfig() 99*333d2b36SAndroid Build Coastguard Worker with open(args.source, 'rb') as f: 100*333d2b36SAndroid Build Coastguard Worker pb.ParseFromString(f.read()) 101*333d2b36SAndroid Build Coastguard Worker 102*333d2b36SAndroid Build Coastguard Worker if getattr(type(pb), 103*333d2b36SAndroid Build Coastguard Worker args.key).DESCRIPTOR.label == FieldDescriptor.LABEL_REPEATED: 104*333d2b36SAndroid Build Coastguard Worker for value in args.value.split(): 105*333d2b36SAndroid Build Coastguard Worker getattr(pb, args.key).append(value) 106*333d2b36SAndroid Build Coastguard Worker else: 107*333d2b36SAndroid Build Coastguard Worker setattr(pb, args.key, args.value) 108*333d2b36SAndroid Build Coastguard Worker 109*333d2b36SAndroid Build Coastguard Worker ValidateAndWriteAsPbFile(pb, args.output) 110*333d2b36SAndroid Build Coastguard Worker 111*333d2b36SAndroid Build Coastguard Worker 112*333d2b36SAndroid Build Coastguard Worker 113*333d2b36SAndroid Build Coastguard Workerdef Merge(args): 114*333d2b36SAndroid Build Coastguard Worker pb = linker_config_pb2.LinkerConfig() 115*333d2b36SAndroid Build Coastguard Worker for other in args.input: 116*333d2b36SAndroid Build Coastguard Worker with open(other, 'rb') as f: 117*333d2b36SAndroid Build Coastguard Worker pb.MergeFromString(f.read()) 118*333d2b36SAndroid Build Coastguard Worker 119*333d2b36SAndroid Build Coastguard Worker ValidateAndWriteAsPbFile(pb, args.output) 120*333d2b36SAndroid Build Coastguard Worker 121*333d2b36SAndroid Build Coastguard Worker 122*333d2b36SAndroid Build Coastguard Workerdef Validate(args): 123*333d2b36SAndroid Build Coastguard Worker if os.path.isdir(args.input): 124*333d2b36SAndroid Build Coastguard Worker config_file = os.path.join(args.input, 'etc/linker.config.pb') 125*333d2b36SAndroid Build Coastguard Worker if os.path.exists(config_file): 126*333d2b36SAndroid Build Coastguard Worker args.input = config_file 127*333d2b36SAndroid Build Coastguard Worker Validate(args) 128*333d2b36SAndroid Build Coastguard Worker # OK if there's no linker config file. 129*333d2b36SAndroid Build Coastguard Worker return 130*333d2b36SAndroid Build Coastguard Worker 131*333d2b36SAndroid Build Coastguard Worker if not os.path.isfile(args.input): 132*333d2b36SAndroid Build Coastguard Worker sys.exit(f"{args.input} is not a file") 133*333d2b36SAndroid Build Coastguard Worker 134*333d2b36SAndroid Build Coastguard Worker pb = linker_config_pb2.LinkerConfig() 135*333d2b36SAndroid Build Coastguard Worker with open(args.input, 'rb') as f: 136*333d2b36SAndroid Build Coastguard Worker pb.ParseFromString(f.read()) 137*333d2b36SAndroid Build Coastguard Worker 138*333d2b36SAndroid Build Coastguard Worker if args.type == 'apex': 139*333d2b36SAndroid Build Coastguard Worker # Shouldn't use provideLibs/requireLibs in APEX linker.config.pb 140*333d2b36SAndroid Build Coastguard Worker if getattr(pb, 'provideLibs'): 141*333d2b36SAndroid Build Coastguard Worker sys.exit(f'{args.input}: provideLibs is set. Use provideSharedLibs in apex_manifest') 142*333d2b36SAndroid Build Coastguard Worker if getattr(pb, 'requireLibs'): 143*333d2b36SAndroid Build Coastguard Worker sys.exit(f'{args.input}: requireLibs is set. Use requireSharedLibs in apex_manifest') 144*333d2b36SAndroid Build Coastguard Worker elif args.type == 'system': 145*333d2b36SAndroid Build Coastguard Worker if getattr(pb, 'visible'): 146*333d2b36SAndroid Build Coastguard Worker sys.exit(f'{args.input}: do not use visible, which is for APEX') 147*333d2b36SAndroid Build Coastguard Worker if getattr(pb, 'permittedPaths'): 148*333d2b36SAndroid Build Coastguard Worker sys.exit(f'{args.input}: do not use permittedPaths, which is for APEX') 149*333d2b36SAndroid Build Coastguard Worker else: 150*333d2b36SAndroid Build Coastguard Worker sys.exit(f'Unknown type: {args.type}') 151*333d2b36SAndroid Build Coastguard Worker 152*333d2b36SAndroid Build Coastguard Worker # Reject contributions field at build time while keeping the runtime behavior for GRF. 153*333d2b36SAndroid Build Coastguard Worker if getattr(pb, 'contributions'): 154*333d2b36SAndroid Build Coastguard Worker sys.exit(f"{args.input}: 'contributions' is set. " 155*333d2b36SAndroid Build Coastguard Worker "It's deprecated. Instead, make the APEX 'visible' and use android_dlopen_ext().") 156*333d2b36SAndroid Build Coastguard Worker 157*333d2b36SAndroid Build Coastguard Worker 158*333d2b36SAndroid Build Coastguard Workerdef ValidateAndWriteAsPbFile(pb, output_path): 159*333d2b36SAndroid Build Coastguard Worker ValidateConfiguration(pb) 160*333d2b36SAndroid Build Coastguard Worker with open(output_path, 'wb') as f: 161*333d2b36SAndroid Build Coastguard Worker f.write(pb.SerializeToString()) 162*333d2b36SAndroid Build Coastguard Worker 163*333d2b36SAndroid Build Coastguard Worker 164*333d2b36SAndroid Build Coastguard Workerdef ValidateConfiguration(pb): 165*333d2b36SAndroid Build Coastguard Worker """ 166*333d2b36SAndroid Build Coastguard Worker Validate if the configuration is valid to be used as linker configuration 167*333d2b36SAndroid Build Coastguard Worker """ 168*333d2b36SAndroid Build Coastguard Worker 169*333d2b36SAndroid Build Coastguard Worker # Validate if provideLibs and requireLibs have common module 170*333d2b36SAndroid Build Coastguard Worker provideLibs = set(getattr(pb, 'provideLibs')) 171*333d2b36SAndroid Build Coastguard Worker requireLibs = set(getattr(pb, 'requireLibs')) 172*333d2b36SAndroid Build Coastguard Worker 173*333d2b36SAndroid Build Coastguard Worker intersectLibs = provideLibs.intersection(requireLibs) 174*333d2b36SAndroid Build Coastguard Worker 175*333d2b36SAndroid Build Coastguard Worker if intersectLibs: 176*333d2b36SAndroid Build Coastguard Worker for lib in intersectLibs: 177*333d2b36SAndroid Build Coastguard Worker print(f'{lib} exists both in requireLibs and provideLibs', file=sys.stderr) 178*333d2b36SAndroid Build Coastguard Worker sys.exit(1) 179*333d2b36SAndroid Build Coastguard Worker 180*333d2b36SAndroid Build Coastguard Worker 181*333d2b36SAndroid Build Coastguard Workerdef GetArgParser(): 182*333d2b36SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 183*333d2b36SAndroid Build Coastguard Worker subparsers = parser.add_subparsers() 184*333d2b36SAndroid Build Coastguard Worker 185*333d2b36SAndroid Build Coastguard Worker parser_proto = subparsers.add_parser( 186*333d2b36SAndroid Build Coastguard Worker 'proto', 187*333d2b36SAndroid Build Coastguard Worker help='Convert the input JSON configuration file into protobuf.') 188*333d2b36SAndroid Build Coastguard Worker parser_proto.add_argument( 189*333d2b36SAndroid Build Coastguard Worker '-s', 190*333d2b36SAndroid Build Coastguard Worker '--source', 191*333d2b36SAndroid Build Coastguard Worker nargs='?', 192*333d2b36SAndroid Build Coastguard Worker type=str, 193*333d2b36SAndroid Build Coastguard Worker help='Colon-separated list of linker configuration files in JSON.') 194*333d2b36SAndroid Build Coastguard Worker parser_proto.add_argument( 195*333d2b36SAndroid Build Coastguard Worker '-o', 196*333d2b36SAndroid Build Coastguard Worker '--output', 197*333d2b36SAndroid Build Coastguard Worker required=True, 198*333d2b36SAndroid Build Coastguard Worker type=str, 199*333d2b36SAndroid Build Coastguard Worker help='Target path to create protobuf file.') 200*333d2b36SAndroid Build Coastguard Worker option_for_existing_output = parser_proto.add_mutually_exclusive_group() 201*333d2b36SAndroid Build Coastguard Worker option_for_existing_output.add_argument( 202*333d2b36SAndroid Build Coastguard Worker '-f', 203*333d2b36SAndroid Build Coastguard Worker '--force', 204*333d2b36SAndroid Build Coastguard Worker action='store_true', 205*333d2b36SAndroid Build Coastguard Worker help='Overwrite if the output file exists.') 206*333d2b36SAndroid Build Coastguard Worker option_for_existing_output.add_argument( 207*333d2b36SAndroid Build Coastguard Worker '-a', 208*333d2b36SAndroid Build Coastguard Worker '--append', 209*333d2b36SAndroid Build Coastguard Worker action='store_true', 210*333d2b36SAndroid Build Coastguard Worker help='Append the input to the output file if the output file exists.') 211*333d2b36SAndroid Build Coastguard Worker parser_proto.set_defaults(func=Proto) 212*333d2b36SAndroid Build Coastguard Worker 213*333d2b36SAndroid Build Coastguard Worker print_proto = subparsers.add_parser( 214*333d2b36SAndroid Build Coastguard Worker 'print', help='Print configuration in human-readable text format.') 215*333d2b36SAndroid Build Coastguard Worker print_proto.add_argument( 216*333d2b36SAndroid Build Coastguard Worker '-s', 217*333d2b36SAndroid Build Coastguard Worker '--source', 218*333d2b36SAndroid Build Coastguard Worker required=True, 219*333d2b36SAndroid Build Coastguard Worker type=str, 220*333d2b36SAndroid Build Coastguard Worker help='Source linker configuration file in protobuf.') 221*333d2b36SAndroid Build Coastguard Worker print_proto.set_defaults(func=Print) 222*333d2b36SAndroid Build Coastguard Worker 223*333d2b36SAndroid Build Coastguard Worker system_provide_libs = subparsers.add_parser( 224*333d2b36SAndroid Build Coastguard Worker 'systemprovide', 225*333d2b36SAndroid Build Coastguard Worker help='Append system provide libraries into the configuration.') 226*333d2b36SAndroid Build Coastguard Worker system_provide_libs.add_argument( 227*333d2b36SAndroid Build Coastguard Worker '-s', 228*333d2b36SAndroid Build Coastguard Worker '--source', 229*333d2b36SAndroid Build Coastguard Worker required=True, 230*333d2b36SAndroid Build Coastguard Worker type=str, 231*333d2b36SAndroid Build Coastguard Worker help='Source linker configuration file in protobuf.') 232*333d2b36SAndroid Build Coastguard Worker system_provide_libs.add_argument( 233*333d2b36SAndroid Build Coastguard Worker '-o', 234*333d2b36SAndroid Build Coastguard Worker '--output', 235*333d2b36SAndroid Build Coastguard Worker required=True, 236*333d2b36SAndroid Build Coastguard Worker type=str, 237*333d2b36SAndroid Build Coastguard Worker help='Target linker configuration file to write in protobuf.') 238*333d2b36SAndroid Build Coastguard Worker system_provide_libs.add_argument( 239*333d2b36SAndroid Build Coastguard Worker '--value', 240*333d2b36SAndroid Build Coastguard Worker required=True, 241*333d2b36SAndroid Build Coastguard Worker type=str, 242*333d2b36SAndroid Build Coastguard Worker help='Values of the libraries to append. If there are more than one ' 243*333d2b36SAndroid Build Coastguard Worker 'it should be separated by empty space' 244*333d2b36SAndroid Build Coastguard Worker ) 245*333d2b36SAndroid Build Coastguard Worker system_provide_libs.add_argument( 246*333d2b36SAndroid Build Coastguard Worker '--system', required=True, type=str, help='Path of the system image.') 247*333d2b36SAndroid Build Coastguard Worker system_provide_libs.set_defaults(func=SystemProvide) 248*333d2b36SAndroid Build Coastguard Worker 249*333d2b36SAndroid Build Coastguard Worker append = subparsers.add_parser( 250*333d2b36SAndroid Build Coastguard Worker 'append', help='Append value(s) to given key.') 251*333d2b36SAndroid Build Coastguard Worker append.add_argument( 252*333d2b36SAndroid Build Coastguard Worker '-s', 253*333d2b36SAndroid Build Coastguard Worker '--source', 254*333d2b36SAndroid Build Coastguard Worker required=True, 255*333d2b36SAndroid Build Coastguard Worker type=str, 256*333d2b36SAndroid Build Coastguard Worker help='Source linker configuration file in protobuf.') 257*333d2b36SAndroid Build Coastguard Worker append.add_argument( 258*333d2b36SAndroid Build Coastguard Worker '-o', 259*333d2b36SAndroid Build Coastguard Worker '--output', 260*333d2b36SAndroid Build Coastguard Worker required=True, 261*333d2b36SAndroid Build Coastguard Worker type=str, 262*333d2b36SAndroid Build Coastguard Worker help='Target linker configuration file to write in protobuf.') 263*333d2b36SAndroid Build Coastguard Worker append.add_argument('--key', required=True, type=str, help='.') 264*333d2b36SAndroid Build Coastguard Worker append.add_argument( 265*333d2b36SAndroid Build Coastguard Worker '--value', 266*333d2b36SAndroid Build Coastguard Worker required=True, 267*333d2b36SAndroid Build Coastguard Worker type=str, 268*333d2b36SAndroid Build Coastguard Worker help='Values of the libraries to append. If there are more than one' 269*333d2b36SAndroid Build Coastguard Worker 'it should be separated by empty space' 270*333d2b36SAndroid Build Coastguard Worker ) 271*333d2b36SAndroid Build Coastguard Worker append.set_defaults(func=Append) 272*333d2b36SAndroid Build Coastguard Worker 273*333d2b36SAndroid Build Coastguard Worker append = subparsers.add_parser('merge', help='Merge configurations') 274*333d2b36SAndroid Build Coastguard Worker append.add_argument( 275*333d2b36SAndroid Build Coastguard Worker '-o', 276*333d2b36SAndroid Build Coastguard Worker '--out', 277*333d2b36SAndroid Build Coastguard Worker required=True, 278*333d2b36SAndroid Build Coastguard Worker type=str, 279*333d2b36SAndroid Build Coastguard Worker help='Output linker configuration file to write in protobuf.') 280*333d2b36SAndroid Build Coastguard Worker append.add_argument( 281*333d2b36SAndroid Build Coastguard Worker '-i', 282*333d2b36SAndroid Build Coastguard Worker '--input', 283*333d2b36SAndroid Build Coastguard Worker nargs='+', 284*333d2b36SAndroid Build Coastguard Worker type=str, 285*333d2b36SAndroid Build Coastguard Worker help='Linker configuration files to merge.') 286*333d2b36SAndroid Build Coastguard Worker append.set_defaults(func=Merge) 287*333d2b36SAndroid Build Coastguard Worker 288*333d2b36SAndroid Build Coastguard Worker validate = subparsers.add_parser('validate', help='Validate configuration') 289*333d2b36SAndroid Build Coastguard Worker validate.add_argument( 290*333d2b36SAndroid Build Coastguard Worker '--type', 291*333d2b36SAndroid Build Coastguard Worker required=True, 292*333d2b36SAndroid Build Coastguard Worker choices=['apex', 'system'], 293*333d2b36SAndroid Build Coastguard Worker help='Type of linker configuration') 294*333d2b36SAndroid Build Coastguard Worker validate.add_argument( 295*333d2b36SAndroid Build Coastguard Worker 'input', 296*333d2b36SAndroid Build Coastguard Worker help='Input can be a directory which has etc/linker.config.pb or a path' 297*333d2b36SAndroid Build Coastguard Worker ' to the linker config file') 298*333d2b36SAndroid Build Coastguard Worker validate.set_defaults(func=Validate) 299*333d2b36SAndroid Build Coastguard Worker 300*333d2b36SAndroid Build Coastguard Worker return parser 301*333d2b36SAndroid Build Coastguard Worker 302*333d2b36SAndroid Build Coastguard Worker 303*333d2b36SAndroid Build Coastguard Workerdef main(): 304*333d2b36SAndroid Build Coastguard Worker parser = GetArgParser() 305*333d2b36SAndroid Build Coastguard Worker args = parser.parse_args() 306*333d2b36SAndroid Build Coastguard Worker if 'func' in args: 307*333d2b36SAndroid Build Coastguard Worker args.func(args) 308*333d2b36SAndroid Build Coastguard Worker else: 309*333d2b36SAndroid Build Coastguard Worker parser.print_help() 310*333d2b36SAndroid Build Coastguard Worker 311*333d2b36SAndroid Build Coastguard Worker 312*333d2b36SAndroid Build Coastguard Workerif __name__ == '__main__': 313*333d2b36SAndroid Build Coastguard Worker main() 314