#!/usr/bin/env python # Copyright (c) 2014 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # Disable the lint error for too-long lines for the URL below. # pylint: disable=C0301 """Fix Chrome App manifest.json files for use with multi-platform zip files. See info about multi-platform zip files here: https://developer.chrome.com/native-client/devguide/distributing#packaged-application The manifest.json file needs to point to the correct platform-specific paths, but we build all toolchains and configurations in the same tree. As a result, we can't have one manifest.json for all combinations. Instead, we update the top-level manifest.json file during the build: "platforms": [ { "nacl_arch": "x86-64", "sub_package_path": "_platform_specific/x86-64/" }, ... Becomes "platforms": [ { "nacl_arch": "x86-64", "sub_package_path": "//_platform_specific/x86-64/" }, ... """ import collections import json import optparse import os import sys if sys.version_info < (2, 6, 0): sys.stderr.write("python 2.6 or later is required run this script\n") sys.exit(1) class Error(Exception): """Local Error class for this file.""" pass def Trace(msg): if Trace.verbose: sys.stderr.write(str(msg) + '\n') Trace.verbose = False def main(argv): parser = optparse.OptionParser( usage='Usage: %prog [options] manifest.json', description=__doc__) parser.add_option('-p', '--prefix', help='Prefix to set for all sub_package_paths in the ' 'manifest. If none is specified, the prefix will be ' 'removed; i.e. the start of the path will be ' '"_platform_specific/..."') parser.add_option('-v', '--verbose', help='Verbose output', action='store_true') options, args = parser.parse_args(argv) if options.verbose: Trace.verbose = True if not args: parser.error('Expected manifest file.') manifest = args[0] Trace('Reading %s' % manifest) with open(manifest) as f: # Keep the dictionary order. This is only supported on Python 2.7+ if sys.version_info >= (2, 7, 0): data = json.load(f, object_pairs_hook=collections.OrderedDict) else: data = json.load(f) if 'platforms' not in data: raise Error('%s does not have "platforms" key.' % manifest) platforms = data['platforms'] if type(platforms) is not list: raise Error('Expected "platforms" key to be array.') if options.prefix: prefix = options.prefix + '/' else: prefix = '' for platform in platforms: nacl_arch = platform.get('nacl_arch') if 'sub_package_path' not in platform: raise Error('Expected each platform to have "sub_package_path" key.') sub_package_path = platform['sub_package_path'] index = sub_package_path.find('_platform_specific') if index == -1: raise Error('Could not find "_platform_specific" in the ' '"sub_package_path" key.') new_path = prefix + sub_package_path[index:] platform['sub_package_path'] = new_path Trace(' %s: "%s" -> "%s"' % (nacl_arch, sub_package_path, new_path)) with open(manifest, 'w') as f: json.dump(data, f, indent=2) return 0 if __name__ == '__main__': try: rtn = main(sys.argv[1:]) except Error, e: sys.stderr.write('%s: %s\n' % (os.path.basename(__file__), e)) rtn = 1 except KeyboardInterrupt: sys.stderr.write('%s: interrupted\n' % os.path.basename(__file__)) rtn = 1 sys.exit(rtn)