• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2#
3# Copyright (C) 2020 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""" A tool to convert json file into pb with linker config format."""
17
18import argparse
19import collections
20import json
21import os
22
23import linker_config_pb2 #pylint: disable=import-error
24from google.protobuf.descriptor import FieldDescriptor
25from google.protobuf.json_format import ParseDict
26from google.protobuf.text_format import MessageToString
27
28
29def Proto(args):
30    json_content = ''
31    with open(args.source) as f:
32        for line in f:
33            if not line.lstrip().startswith('//'):
34                json_content += line
35    obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
36    pb = ParseDict(obj, linker_config_pb2.LinkerConfig())
37    with open(args.output, 'wb') as f:
38        f.write(pb.SerializeToString())
39
40
41def Print(args):
42    with open(args.source, 'rb') as f:
43        pb = linker_config_pb2.LinkerConfig()
44        pb.ParseFromString(f.read())
45    print(MessageToString(pb))
46
47
48def SystemProvide(args):
49    pb = linker_config_pb2.LinkerConfig()
50    with open(args.source, 'rb') as f:
51        pb.ParseFromString(f.read())
52    libraries = args.value.split()
53
54    def IsInLibPath(lib_name):
55        lib_path = os.path.join(args.system, 'lib', lib_name)
56        lib64_path = os.path.join(args.system, 'lib64', lib_name)
57        return os.path.exists(lib_path) or os.path.islink(
58            lib_path) or os.path.exists(lib64_path) or os.path.islink(
59                lib64_path)
60
61    installed_libraries = [lib for lib in libraries if IsInLibPath(lib)]
62    for item in installed_libraries:
63        if item not in getattr(pb, 'provideLibs'):
64            getattr(pb, 'provideLibs').append(item)
65    with open(args.output, 'wb') as f:
66        f.write(pb.SerializeToString())
67
68
69def Append(args):
70    pb = linker_config_pb2.LinkerConfig()
71    with open(args.source, 'rb') as f:
72        pb.ParseFromString(f.read())
73
74    if getattr(type(pb),
75               args.key).DESCRIPTOR.label == FieldDescriptor.LABEL_REPEATED:
76        for value in args.value.split():
77            getattr(pb, args.key).append(value)
78    else:
79        setattr(pb, args.key, args.value)
80
81    with open(args.output, 'wb') as f:
82        f.write(pb.SerializeToString())
83
84
85def Merge(args):
86    pb = linker_config_pb2.LinkerConfig()
87    for other in args.input:
88        with open(other, 'rb') as f:
89            pb.MergeFromString(f.read())
90
91    with open(args.out, 'wb') as f:
92        f.write(pb.SerializeToString())
93
94
95def GetArgParser():
96    parser = argparse.ArgumentParser()
97    subparsers = parser.add_subparsers()
98
99    parser_proto = subparsers.add_parser(
100        'proto',
101        help='Convert the input JSON configuration file into protobuf.')
102    parser_proto.add_argument(
103        '-s',
104        '--source',
105        required=True,
106        type=str,
107        help='Source linker configuration file in JSON.')
108    parser_proto.add_argument(
109        '-o',
110        '--output',
111        required=True,
112        type=str,
113        help='Target path to create protobuf file.')
114    parser_proto.set_defaults(func=Proto)
115
116    print_proto = subparsers.add_parser(
117        'print', help='Print configuration in human-readable text format.')
118    print_proto.add_argument(
119        '-s',
120        '--source',
121        required=True,
122        type=str,
123        help='Source linker configuration file in protobuf.')
124    print_proto.set_defaults(func=Print)
125
126    system_provide_libs = subparsers.add_parser(
127        'systemprovide',
128        help='Append system provide libraries into the configuration.')
129    system_provide_libs.add_argument(
130        '-s',
131        '--source',
132        required=True,
133        type=str,
134        help='Source linker configuration file in protobuf.')
135    system_provide_libs.add_argument(
136        '-o',
137        '--output',
138        required=True,
139        type=str,
140        help='Target linker configuration file to write in protobuf.')
141    system_provide_libs.add_argument(
142        '--value',
143        required=True,
144        type=str,
145        help='Values of the libraries to append. If there are more than one '
146        'it should be separated by empty space'
147    )
148    system_provide_libs.add_argument(
149        '--system', required=True, type=str, help='Path of the system image.')
150    system_provide_libs.set_defaults(func=SystemProvide)
151
152    append = subparsers.add_parser(
153        'append', help='Append value(s) to given key.')
154    append.add_argument(
155        '-s',
156        '--source',
157        required=True,
158        type=str,
159        help='Source linker configuration file in protobuf.')
160    append.add_argument(
161        '-o',
162        '--output',
163        required=True,
164        type=str,
165        help='Target linker configuration file to write in protobuf.')
166    append.add_argument('--key', required=True, type=str, help='.')
167    append.add_argument(
168        '--value',
169        required=True,
170        type=str,
171        help='Values of the libraries to append. If there are more than one'
172        'it should be separated by empty space'
173    )
174    append.set_defaults(func=Append)
175
176    append = subparsers.add_parser('merge', help='Merge configurations')
177    append.add_argument(
178        '-o',
179        '--out',
180        required=True,
181        type=str,
182        help='Output linker configuration file to write in protobuf.')
183    append.add_argument(
184        '-i',
185        '--input',
186        nargs='+',
187        type=str,
188        help='Linker configuration files to merge.')
189    append.set_defaults(func=Merge)
190
191    return parser
192
193
194def main():
195    args = GetArgParser().parse_args()
196    args.func(args)
197
198
199if __name__ == '__main__':
200    main()
201