xref: /aosp_15_r20/build/soong/scripts/conv_linker_config.py (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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