blob: 784a92f4c7dca38901034291893def5e3f2edebd [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
30def Proto(args):
Jooyung Han3397b6a2023-03-08 05:44:17 +090031 """
32 Merges input json files (--source) into a protobuf message (--output).
33 Fails if the output file exists. Set --force or --append to deal with the existing
34 output file.
35 --force to overwrite the output file with the input (.json files).
36 --append to append the input to the output file.
37 """
Jooyung Han014ccd42023-01-09 16:23:14 +090038 pb = linker_config_pb2.LinkerConfig()
Jooyung Han3397b6a2023-03-08 05:44:17 +090039 if os.path.isfile(args.output):
40 if args.force:
41 pass
42 elif args.append:
43 with open(args.output, 'rb') as f:
44 pb.ParseFromString(f.read())
45 else:
46 sys.stderr.write(f'Error: {args.output} exists. Use --force or --append.\n')
47 sys.exit(1)
48
Jooyung Hanb531bee2023-03-04 08:28:40 +090049 if args.source:
50 for input in args.source.split(':'):
51 json_content = ''
52 with open(input) as f:
53 for line in f:
54 if not line.lstrip().startswith('//'):
55 json_content += line
56 obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
57 ParseDict(obj, pb)
Spandan Das1d4bfd82021-08-25 22:58:46 +000058 with open(args.output, 'wb') as f:
59 f.write(pb.SerializeToString())
Kiyoung Kim62abd122020-10-06 17:16:44 +090060
61
62def Print(args):
Spandan Das1d4bfd82021-08-25 22:58:46 +000063 with open(args.source, 'rb') as f:
64 pb = linker_config_pb2.LinkerConfig()
65 pb.ParseFromString(f.read())
66 print(MessageToString(pb))
Kiyoung Kim62abd122020-10-06 17:16:44 +090067
68
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +090069def SystemProvide(args):
Spandan Das1d4bfd82021-08-25 22:58:46 +000070 pb = linker_config_pb2.LinkerConfig()
71 with open(args.source, 'rb') as f:
72 pb.ParseFromString(f.read())
73 libraries = args.value.split()
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +090074
Spandan Das1d4bfd82021-08-25 22:58:46 +000075 def IsInLibPath(lib_name):
76 lib_path = os.path.join(args.system, 'lib', lib_name)
77 lib64_path = os.path.join(args.system, 'lib64', lib_name)
78 return os.path.exists(lib_path) or os.path.islink(
79 lib_path) or os.path.exists(lib64_path) or os.path.islink(
80 lib64_path)
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +090081
Spandan Das1d4bfd82021-08-25 22:58:46 +000082 installed_libraries = [lib for lib in libraries if IsInLibPath(lib)]
83 for item in installed_libraries:
84 if item not in getattr(pb, 'provideLibs'):
85 getattr(pb, 'provideLibs').append(item)
86 with open(args.output, 'wb') as f:
87 f.write(pb.SerializeToString())
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +090088
89
Kiyoung Kim4ee686d2020-12-03 15:20:07 +090090def Append(args):
Spandan Das1d4bfd82021-08-25 22:58:46 +000091 pb = linker_config_pb2.LinkerConfig()
92 with open(args.source, 'rb') as f:
93 pb.ParseFromString(f.read())
Kiyoung Kim4ee686d2020-12-03 15:20:07 +090094
Spandan Das1d4bfd82021-08-25 22:58:46 +000095 if getattr(type(pb),
96 args.key).DESCRIPTOR.label == FieldDescriptor.LABEL_REPEATED:
97 for value in args.value.split():
98 getattr(pb, args.key).append(value)
99 else:
100 setattr(pb, args.key, args.value)
Kiyoung Kim4ee686d2020-12-03 15:20:07 +0900101
Spandan Das1d4bfd82021-08-25 22:58:46 +0000102 with open(args.output, 'wb') as f:
103 f.write(pb.SerializeToString())
104
Kiyoung Kim4ee686d2020-12-03 15:20:07 +0900105
Jooyung Hane134d092021-04-15 05:13:34 +0900106def Merge(args):
Spandan Das1d4bfd82021-08-25 22:58:46 +0000107 pb = linker_config_pb2.LinkerConfig()
108 for other in args.input:
109 with open(other, 'rb') as f:
110 pb.MergeFromString(f.read())
Jooyung Hane134d092021-04-15 05:13:34 +0900111
Spandan Das1d4bfd82021-08-25 22:58:46 +0000112 with open(args.out, 'wb') as f:
113 f.write(pb.SerializeToString())
114
Kiyoung Kim4ee686d2020-12-03 15:20:07 +0900115
Kiyoung Kim62abd122020-10-06 17:16:44 +0900116def GetArgParser():
Spandan Das1d4bfd82021-08-25 22:58:46 +0000117 parser = argparse.ArgumentParser()
118 subparsers = parser.add_subparsers()
Kiyoung Kim62abd122020-10-06 17:16:44 +0900119
Spandan Das1d4bfd82021-08-25 22:58:46 +0000120 parser_proto = subparsers.add_parser(
121 'proto',
122 help='Convert the input JSON configuration file into protobuf.')
123 parser_proto.add_argument(
124 '-s',
125 '--source',
Jooyung Hanb531bee2023-03-04 08:28:40 +0900126 nargs='?',
Spandan Das1d4bfd82021-08-25 22:58:46 +0000127 type=str,
Jooyung Han014ccd42023-01-09 16:23:14 +0900128 help='Colon-separated list of linker configuration files in JSON.')
Spandan Das1d4bfd82021-08-25 22:58:46 +0000129 parser_proto.add_argument(
130 '-o',
131 '--output',
132 required=True,
133 type=str,
134 help='Target path to create protobuf file.')
Jooyung Han3397b6a2023-03-08 05:44:17 +0900135 option_for_existing_output = parser_proto.add_mutually_exclusive_group()
136 option_for_existing_output.add_argument(
137 '-f',
138 '--force',
139 action='store_true',
140 help='Overwrite if the output file exists.')
141 option_for_existing_output.add_argument(
142 '-a',
143 '--append',
144 action='store_true',
145 help='Append the input to the output file if the output file exists.')
Spandan Das1d4bfd82021-08-25 22:58:46 +0000146 parser_proto.set_defaults(func=Proto)
Kiyoung Kim62abd122020-10-06 17:16:44 +0900147
Spandan Das1d4bfd82021-08-25 22:58:46 +0000148 print_proto = subparsers.add_parser(
149 'print', help='Print configuration in human-readable text format.')
150 print_proto.add_argument(
151 '-s',
152 '--source',
153 required=True,
154 type=str,
155 help='Source linker configuration file in protobuf.')
156 print_proto.set_defaults(func=Print)
Kiyoung Kim62abd122020-10-06 17:16:44 +0900157
Spandan Das1d4bfd82021-08-25 22:58:46 +0000158 system_provide_libs = subparsers.add_parser(
159 'systemprovide',
160 help='Append system provide libraries into the configuration.')
161 system_provide_libs.add_argument(
162 '-s',
163 '--source',
164 required=True,
165 type=str,
166 help='Source linker configuration file in protobuf.')
167 system_provide_libs.add_argument(
168 '-o',
169 '--output',
170 required=True,
171 type=str,
172 help='Target linker configuration file to write in protobuf.')
173 system_provide_libs.add_argument(
174 '--value',
175 required=True,
176 type=str,
177 help='Values of the libraries to append. If there are more than one '
178 'it should be separated by empty space'
179 )
180 system_provide_libs.add_argument(
181 '--system', required=True, type=str, help='Path of the system image.')
182 system_provide_libs.set_defaults(func=SystemProvide)
Kiyoung Kim24dfc1f2020-11-16 10:48:44 +0900183
Spandan Das1d4bfd82021-08-25 22:58:46 +0000184 append = subparsers.add_parser(
185 'append', help='Append value(s) to given key.')
186 append.add_argument(
187 '-s',
188 '--source',
189 required=True,
190 type=str,
191 help='Source linker configuration file in protobuf.')
192 append.add_argument(
193 '-o',
194 '--output',
195 required=True,
196 type=str,
197 help='Target linker configuration file to write in protobuf.')
198 append.add_argument('--key', required=True, type=str, help='.')
199 append.add_argument(
200 '--value',
201 required=True,
202 type=str,
203 help='Values of the libraries to append. If there are more than one'
204 'it should be separated by empty space'
205 )
206 append.set_defaults(func=Append)
Kiyoung Kim4ee686d2020-12-03 15:20:07 +0900207
Spandan Das1d4bfd82021-08-25 22:58:46 +0000208 append = subparsers.add_parser('merge', help='Merge configurations')
209 append.add_argument(
210 '-o',
211 '--out',
212 required=True,
213 type=str,
214 help='Output linker configuration file to write in protobuf.')
215 append.add_argument(
216 '-i',
217 '--input',
218 nargs='+',
219 type=str,
220 help='Linker configuration files to merge.')
221 append.set_defaults(func=Merge)
Jooyung Hane134d092021-04-15 05:13:34 +0900222
Spandan Das1d4bfd82021-08-25 22:58:46 +0000223 return parser
Kiyoung Kim62abd122020-10-06 17:16:44 +0900224
225
226def main():
Jooyung Han3397b6a2023-03-08 05:44:17 +0900227 parser = GetArgParser()
228 args = parser.parse_args()
229 if 'func' in args:
230 args.func(args)
231 else:
232 parser.print_help()
Kiyoung Kim62abd122020-10-06 17:16:44 +0900233
234
235if __name__ == '__main__':
Spandan Das1d4bfd82021-08-25 22:58:46 +0000236 main()