• 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
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(lib_path) or os.path.exists(lib64_path) or os.path.islink(lib64_path)
58
59  installed_libraries = list(filter(IsInLibPath, libraries))
60  for item in installed_libraries:
61    if item not in getattr(pb, 'provideLibs'):
62      getattr(pb, 'provideLibs').append(item)
63  with open(args.output, 'wb') as f:
64    f.write(pb.SerializeToString())
65
66
67def Append(args):
68  pb = linker_config_pb2.LinkerConfig()
69  with open(args.source, 'rb') as f:
70    pb.ParseFromString(f.read())
71
72  if getattr(type(pb), args.key).DESCRIPTOR.label == FieldDescriptor.LABEL_REPEATED:
73    for value in args.value.split():
74      getattr(pb, args.key).append(value)
75  else:
76    setattr(pb, args.key, args.value)
77
78  with open(args.output, 'wb') as f:
79    f.write(pb.SerializeToString())
80
81def Merge(args):
82  pb = linker_config_pb2.LinkerConfig()
83  for other in args.input:
84    with open(other, 'rb') as f:
85      pb.MergeFromString(f.read())
86
87  with open(args.out, 'wb') as f:
88    f.write(pb.SerializeToString())
89
90def GetArgParser():
91  parser = argparse.ArgumentParser()
92  subparsers = parser.add_subparsers()
93
94  parser_proto = subparsers.add_parser(
95      'proto', help='Convert the input JSON configuration file into protobuf.')
96  parser_proto.add_argument(
97      '-s',
98      '--source',
99      required=True,
100      type=str,
101      help='Source linker configuration file in JSON.')
102  parser_proto.add_argument(
103      '-o',
104      '--output',
105      required=True,
106      type=str,
107      help='Target path to create protobuf file.')
108  parser_proto.set_defaults(func=Proto)
109
110  print_proto = subparsers.add_parser(
111      'print', help='Print configuration in human-readable text format.')
112  print_proto.add_argument(
113      '-s',
114      '--source',
115      required=True,
116      type=str,
117      help='Source linker configuration file in protobuf.')
118  print_proto.set_defaults(func=Print)
119
120  system_provide_libs = subparsers.add_parser(
121      'systemprovide', help='Append system provide libraries into the configuration.')
122  system_provide_libs.add_argument(
123      '-s',
124      '--source',
125      required=True,
126      type=str,
127      help='Source linker configuration file in protobuf.')
128  system_provide_libs.add_argument(
129      '-o',
130      '--output',
131      required=True,
132      type=str,
133      help='Target linker configuration file to write in protobuf.')
134  system_provide_libs.add_argument(
135      '--value',
136      required=True,
137      type=str,
138      help='Values of the libraries to append. If there are more than one it should be separated by empty space')
139  system_provide_libs.add_argument(
140      '--system',
141      required=True,
142      type=str,
143      help='Path of the system image.')
144  system_provide_libs.set_defaults(func=SystemProvide)
145
146  append = subparsers.add_parser(
147      'append', help='Append value(s) to given key.')
148  append.add_argument(
149      '-s',
150      '--source',
151      required=True,
152      type=str,
153      help='Source linker configuration file in protobuf.')
154  append.add_argument(
155      '-o',
156      '--output',
157      required=True,
158      type=str,
159      help='Target linker configuration file to write in protobuf.')
160  append.add_argument(
161      '--key',
162      required=True,
163      type=str,
164      help='.')
165  append.add_argument(
166      '--value',
167      required=True,
168      type=str,
169      help='Values of the libraries to append. If there are more than one it should be separated by empty space')
170  append.set_defaults(func=Append)
171
172  append = subparsers.add_parser(
173      'merge', help='Merge configurations')
174  append.add_argument(
175      '-o',
176      '--out',
177      required=True,
178      type=str,
179      help='Ouptut linker configuration file to write in protobuf.')
180  append.add_argument(
181      '-i',
182      '--input',
183      nargs='+',
184      type=str,
185      help='Linker configuration files to merge.')
186  append.set_defaults(func=Merge)
187
188  return parser
189
190
191def main():
192  args = GetArgParser().parse_args()
193  args.func(args)
194
195
196if __name__ == '__main__':
197  main()
198