123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- #!/usr/bin/env python
- #
- # Copyright (C) 2020 The Android Open Source Project
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- """ A tool to convert json file into pb with linker config format."""
- import argparse
- import collections
- import json
- import os
- import sys
- import linker_config_pb2 #pylint: disable=import-error
- from google.protobuf.descriptor import FieldDescriptor
- from google.protobuf.json_format import ParseDict
- from google.protobuf.text_format import MessageToString
- def LoadJsonMessage(path):
- """
- Loads a message from a .json file with `//` comments strippedfor convenience.
- """
- json_content = ''
- with open(path) as f:
- for line in f:
- if not line.lstrip().startswith('//'):
- json_content += line
- obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
- return ParseDict(obj, linker_config_pb2.LinkerConfig())
- def Proto(args):
- """
- Merges input json files (--source) into a protobuf message (--output).
- Fails if the output file exists. Set --force or --append to deal with the existing
- output file.
- --force to overwrite the output file with the input (.json files).
- --append to append the input to the output file.
- """
- pb = linker_config_pb2.LinkerConfig()
- if os.path.isfile(args.output):
- if args.force:
- pass
- elif args.append:
- with open(args.output, 'rb') as f:
- pb.ParseFromString(f.read())
- else:
- sys.stderr.write(f'Error: {args.output} exists. Use --force or --append.\n')
- sys.exit(1)
- if args.source:
- for input in args.source.split(':'):
- pb.MergeFrom(LoadJsonMessage(input))
- with open(args.output, 'wb') as f:
- f.write(pb.SerializeToString())
- def Print(args):
- with open(args.source, 'rb') as f:
- pb = linker_config_pb2.LinkerConfig()
- pb.ParseFromString(f.read())
- print(MessageToString(pb))
- def SystemProvide(args):
- pb = linker_config_pb2.LinkerConfig()
- with open(args.source, 'rb') as f:
- pb.ParseFromString(f.read())
- libraries = args.value.split()
- def IsInLibPath(lib_name):
- lib_path = os.path.join(args.system, 'lib', lib_name)
- lib64_path = os.path.join(args.system, 'lib64', lib_name)
- return os.path.exists(lib_path) or os.path.islink(
- lib_path) or os.path.exists(lib64_path) or os.path.islink(
- lib64_path)
- installed_libraries = [lib for lib in libraries if IsInLibPath(lib)]
- for item in installed_libraries:
- if item not in getattr(pb, 'provideLibs'):
- getattr(pb, 'provideLibs').append(item)
- with open(args.output, 'wb') as f:
- f.write(pb.SerializeToString())
- def Append(args):
- pb = linker_config_pb2.LinkerConfig()
- with open(args.source, 'rb') as f:
- pb.ParseFromString(f.read())
- if getattr(type(pb),
- args.key).DESCRIPTOR.label == FieldDescriptor.LABEL_REPEATED:
- for value in args.value.split():
- getattr(pb, args.key).append(value)
- else:
- setattr(pb, args.key, args.value)
- with open(args.output, 'wb') as f:
- f.write(pb.SerializeToString())
- def Merge(args):
- pb = linker_config_pb2.LinkerConfig()
- for other in args.input:
- with open(other, 'rb') as f:
- pb.MergeFromString(f.read())
- with open(args.out, 'wb') as f:
- f.write(pb.SerializeToString())
- def GetArgParser():
- parser = argparse.ArgumentParser()
- subparsers = parser.add_subparsers()
- parser_proto = subparsers.add_parser(
- 'proto',
- help='Convert the input JSON configuration file into protobuf.')
- parser_proto.add_argument(
- '-s',
- '--source',
- nargs='?',
- type=str,
- help='Colon-separated list of linker configuration files in JSON.')
- parser_proto.add_argument(
- '-o',
- '--output',
- required=True,
- type=str,
- help='Target path to create protobuf file.')
- option_for_existing_output = parser_proto.add_mutually_exclusive_group()
- option_for_existing_output.add_argument(
- '-f',
- '--force',
- action='store_true',
- help='Overwrite if the output file exists.')
- option_for_existing_output.add_argument(
- '-a',
- '--append',
- action='store_true',
- help='Append the input to the output file if the output file exists.')
- parser_proto.set_defaults(func=Proto)
- print_proto = subparsers.add_parser(
- 'print', help='Print configuration in human-readable text format.')
- print_proto.add_argument(
- '-s',
- '--source',
- required=True,
- type=str,
- help='Source linker configuration file in protobuf.')
- print_proto.set_defaults(func=Print)
- system_provide_libs = subparsers.add_parser(
- 'systemprovide',
- help='Append system provide libraries into the configuration.')
- system_provide_libs.add_argument(
- '-s',
- '--source',
- required=True,
- type=str,
- help='Source linker configuration file in protobuf.')
- system_provide_libs.add_argument(
- '-o',
- '--output',
- required=True,
- type=str,
- help='Target linker configuration file to write in protobuf.')
- system_provide_libs.add_argument(
- '--value',
- required=True,
- type=str,
- help='Values of the libraries to append. If there are more than one '
- 'it should be separated by empty space'
- )
- system_provide_libs.add_argument(
- '--system', required=True, type=str, help='Path of the system image.')
- system_provide_libs.set_defaults(func=SystemProvide)
- append = subparsers.add_parser(
- 'append', help='Append value(s) to given key.')
- append.add_argument(
- '-s',
- '--source',
- required=True,
- type=str,
- help='Source linker configuration file in protobuf.')
- append.add_argument(
- '-o',
- '--output',
- required=True,
- type=str,
- help='Target linker configuration file to write in protobuf.')
- append.add_argument('--key', required=True, type=str, help='.')
- append.add_argument(
- '--value',
- required=True,
- type=str,
- help='Values of the libraries to append. If there are more than one'
- 'it should be separated by empty space'
- )
- append.set_defaults(func=Append)
- append = subparsers.add_parser('merge', help='Merge configurations')
- append.add_argument(
- '-o',
- '--out',
- required=True,
- type=str,
- help='Output linker configuration file to write in protobuf.')
- append.add_argument(
- '-i',
- '--input',
- nargs='+',
- type=str,
- help='Linker configuration files to merge.')
- append.set_defaults(func=Merge)
- return parser
- def main():
- parser = GetArgParser()
- args = parser.parse_args()
- if 'func' in args:
- args.func(args)
- else:
- parser.print_help()
- if __name__ == '__main__':
- main()
|