blob: 3ac1b7e5e99c8e6690dfb43d129254d972a86b10 [file] [log] [blame]
Kiyoung Kim62abd122020-10-06 17:16:44 +09001#!/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
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +090021import os
Jooyung Han3397b6a2023-03-08 05:44:17 +090022import sys
Kiyoung Kim62abd122020-10-06 17:16:44 +090023
Spandan Das1d4bfd82021-08-25 22:58:46 +000024import linker_config_pb2 #pylint: disable=import-error
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +090025from google.protobuf.descriptor import FieldDescriptor
Kiyoung Kim62abd122020-10-06 17:16:44 +090026from google.protobuf.json_format import ParseDict
27from google.protobuf.text_format import MessageToString
28
29
Jooyung Hanf6fd4c22023-03-09 14:50:35 +090030def LoadJsonMessage(path):
31 """
32 Loads a message from a .json file with `//` comments strippedfor convenience.
33 """
34 json_content = ''
35 with open(path) as f:
36 for line in f:
37 if not line.lstrip().startswith('//'):
38 json_content += line
39 obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
40 return ParseDict(obj, linker_config_pb2.LinkerConfig())
41
42
Kiyoung Kim62abd122020-10-06 17:16:44 +090043def Proto(args):
Jooyung Han3397b6a2023-03-08 05:44:17 +090044 """
45 Merges input json files (--source) into a protobuf message (--output).
46 Fails if the output file exists. Set --force or --append to deal with the existing
47 output file.
48 --force to overwrite the output file with the input (.json files).
49 --append to append the input to the output file.
50 """
Jooyung Han014ccd42023-01-09 16:23:14 +090051 pb = linker_config_pb2.LinkerConfig()
Jooyung Han3397b6a2023-03-08 05:44:17 +090052 if os.path.isfile(args.output):
53 if args.force:
54 pass
55 elif args.append:
56 with open(args.output, 'rb') as f:
57 pb.ParseFromString(f.read())
58 else:
59 sys.stderr.write(f'Error: {args.output} exists. Use --force or --append.\n')
60 sys.exit(1)
61
Jooyung Hanb531bee2023-03-04 08:28:40 +090062 if args.source:
63 for input in args.source.split(':'):
Jooyung Hanf6fd4c22023-03-09 14:50:35 +090064 pb.MergeFrom(LoadJsonMessage(input))
Spandan Das1d4bfd82021-08-25 22:58:46 +000065 with open(args.output, 'wb') as f:
66 f.write(pb.SerializeToString())
Kiyoung Kim62abd122020-10-06 17:16:44 +090067
68
69def Print(args):
Spandan Das1d4bfd82021-08-25 22:58:46 +000070 with open(args.source, 'rb') as f:
71 pb = linker_config_pb2.LinkerConfig()
72 pb.ParseFromString(f.read())
73 print(MessageToString(pb))
Kiyoung Kim62abd122020-10-06 17:16:44 +090074
75
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +090076def SystemProvide(args):
Spandan Das1d4bfd82021-08-25 22:58:46 +000077 pb = linker_config_pb2.LinkerConfig()
78 with open(args.source, 'rb') as f:
79 pb.ParseFromString(f.read())
80 libraries = args.value.split()
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +090081
Spandan Das1d4bfd82021-08-25 22:58:46 +000082 def IsInLibPath(lib_name):
83 lib_path = os.path.join(args.system, 'lib', lib_name)
84 lib64_path = os.path.join(args.system, 'lib64', lib_name)
85 return os.path.exists(lib_path) or os.path.islink(
86 lib_path) or os.path.exists(lib64_path) or os.path.islink(
87 lib64_path)
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +090088
Spandan Das1d4bfd82021-08-25 22:58:46 +000089 installed_libraries = [lib for lib in libraries if IsInLibPath(lib)]
90 for item in installed_libraries:
91 if item not in getattr(pb, 'provideLibs'):
92 getattr(pb, 'provideLibs').append(item)
93 with open(args.output, 'wb') as f:
94 f.write(pb.SerializeToString())
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +090095
96
Kiyoung Kim4ee686d2020-12-03 15:20:07 +090097def Append(args):
Spandan Das1d4bfd82021-08-25 22:58:46 +000098 pb = linker_config_pb2.LinkerConfig()
99 with open(args.source, 'rb') as f:
100 pb.ParseFromString(f.read())
Kiyoung Kim4ee686d2020-12-03 15:20:07 +0900101
Spandan Das1d4bfd82021-08-25 22:58:46 +0000102 if getattr(type(pb),
103 args.key).DESCRIPTOR.label == FieldDescriptor.LABEL_REPEATED:
104 for value in args.value.split():
105 getattr(pb, args.key).append(value)
106 else:
107 setattr(pb, args.key, args.value)
Kiyoung Kim4ee686d2020-12-03 15:20:07 +0900108
Spandan Das1d4bfd82021-08-25 22:58:46 +0000109 with open(args.output, 'wb') as f:
110 f.write(pb.SerializeToString())
111
Kiyoung Kim4ee686d2020-12-03 15:20:07 +0900112
Jooyung Hane134d092021-04-15 05:13:34 +0900113def Merge(args):
Spandan Das1d4bfd82021-08-25 22:58:46 +0000114 pb = linker_config_pb2.LinkerConfig()
115 for other in args.input:
116 with open(other, 'rb') as f:
117 pb.MergeFromString(f.read())
Jooyung Hane134d092021-04-15 05:13:34 +0900118
Spandan Das1d4bfd82021-08-25 22:58:46 +0000119 with open(args.out, 'wb') as f:
120 f.write(pb.SerializeToString())
121
Kiyoung Kim4ee686d2020-12-03 15:20:07 +0900122
Kiyoung Kim62abd122020-10-06 17:16:44 +0900123def GetArgParser():
Spandan Das1d4bfd82021-08-25 22:58:46 +0000124 parser = argparse.ArgumentParser()
125 subparsers = parser.add_subparsers()
Kiyoung Kim62abd122020-10-06 17:16:44 +0900126
Spandan Das1d4bfd82021-08-25 22:58:46 +0000127 parser_proto = subparsers.add_parser(
128 'proto',
129 help='Convert the input JSON configuration file into protobuf.')
130 parser_proto.add_argument(
131 '-s',
132 '--source',
Jooyung Hanb531bee2023-03-04 08:28:40 +0900133 nargs='?',
Spandan Das1d4bfd82021-08-25 22:58:46 +0000134 type=str,
Jooyung Han014ccd42023-01-09 16:23:14 +0900135 help='Colon-separated list of linker configuration files in JSON.')
Spandan Das1d4bfd82021-08-25 22:58:46 +0000136 parser_proto.add_argument(
137 '-o',
138 '--output',
139 required=True,
140 type=str,
141 help='Target path to create protobuf file.')
Jooyung Han3397b6a2023-03-08 05:44:17 +0900142 option_for_existing_output = parser_proto.add_mutually_exclusive_group()
143 option_for_existing_output.add_argument(
144 '-f',
145 '--force',
146 action='store_true',
147 help='Overwrite if the output file exists.')
148 option_for_existing_output.add_argument(
149 '-a',
150 '--append',
151 action='store_true',
152 help='Append the input to the output file if the output file exists.')
Spandan Das1d4bfd82021-08-25 22:58:46 +0000153 parser_proto.set_defaults(func=Proto)
Kiyoung Kim62abd122020-10-06 17:16:44 +0900154
Spandan Das1d4bfd82021-08-25 22:58:46 +0000155 print_proto = subparsers.add_parser(
156 'print', help='Print configuration in human-readable text format.')
157 print_proto.add_argument(
158 '-s',
159 '--source',
160 required=True,
161 type=str,
162 help='Source linker configuration file in protobuf.')
163 print_proto.set_defaults(func=Print)
Kiyoung Kim62abd122020-10-06 17:16:44 +0900164
Spandan Das1d4bfd82021-08-25 22:58:46 +0000165 system_provide_libs = subparsers.add_parser(
166 'systemprovide',
167 help='Append system provide libraries into the configuration.')
168 system_provide_libs.add_argument(
169 '-s',
170 '--source',
171 required=True,
172 type=str,
173 help='Source linker configuration file in protobuf.')
174 system_provide_libs.add_argument(
175 '-o',
176 '--output',
177 required=True,
178 type=str,
179 help='Target linker configuration file to write in protobuf.')
180 system_provide_libs.add_argument(
181 '--value',
182 required=True,
183 type=str,
184 help='Values of the libraries to append. If there are more than one '
185 'it should be separated by empty space'
186 )
187 system_provide_libs.add_argument(
188 '--system', required=True, type=str, help='Path of the system image.')
189 system_provide_libs.set_defaults(func=SystemProvide)
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +0900190
Spandan Das1d4bfd82021-08-25 22:58:46 +0000191 append = subparsers.add_parser(
192 'append', help='Append value(s) to given key.')
193 append.add_argument(
194 '-s',
195 '--source',
196 required=True,
197 type=str,
198 help='Source linker configuration file in protobuf.')
199 append.add_argument(
200 '-o',
201 '--output',
202 required=True,
203 type=str,
204 help='Target linker configuration file to write in protobuf.')
205 append.add_argument('--key', required=True, type=str, help='.')
206 append.add_argument(
207 '--value',
208 required=True,
209 type=str,
210 help='Values of the libraries to append. If there are more than one'
211 'it should be separated by empty space'
212 )
213 append.set_defaults(func=Append)
Kiyoung Kim4ee686d2020-12-03 15:20:07 +0900214
Spandan Das1d4bfd82021-08-25 22:58:46 +0000215 append = subparsers.add_parser('merge', help='Merge configurations')
216 append.add_argument(
217 '-o',
218 '--out',
219 required=True,
220 type=str,
221 help='Output linker configuration file to write in protobuf.')
222 append.add_argument(
223 '-i',
224 '--input',
225 nargs='+',
226 type=str,
227 help='Linker configuration files to merge.')
228 append.set_defaults(func=Merge)
Jooyung Hane134d092021-04-15 05:13:34 +0900229
Spandan Das1d4bfd82021-08-25 22:58:46 +0000230 return parser
Kiyoung Kim62abd122020-10-06 17:16:44 +0900231
232
233def main():
Jooyung Han3397b6a2023-03-08 05:44:17 +0900234 parser = GetArgParser()
235 args = parser.parse_args()
236 if 'func' in args:
237 args.func(args)
238 else:
239 parser.print_help()
Kiyoung Kim62abd122020-10-06 17:16:44 +0900240
241
242if __name__ == '__main__':
Spandan Das1d4bfd82021-08-25 22:58:46 +0000243 main()