Home | History | Annotate | Download | only in gyp
      1 #!/usr/bin/env python
      2 #
      3 # Copyright 2013 The Chromium Authors. All rights reserved.
      4 # Use of this source code is governed by a BSD-style license that can be
      5 # found in the LICENSE file.
      6 
      7 import optparse
      8 import os
      9 import sys
     10 
     11 from util import build_utils
     12 
     13 
     14 _RESOURCE_CLASSES = [
     15     "R.class",
     16     "R##*.class",
     17     "Manifest.class",
     18     "Manifest##*.class",
     19 ]
     20 
     21 
     22 def Jar(class_files, classes_dir, jar_path, manifest_file=None):
     23   jar_path = os.path.abspath(jar_path)
     24 
     25   # The paths of the files in the jar will be the same as they are passed in to
     26   # the command. Because of this, the command should be run in
     27   # options.classes_dir so the .class file paths in the jar are correct.
     28   jar_cwd = classes_dir
     29   class_files_rel = [os.path.relpath(f, jar_cwd) for f in class_files]
     30   jar_cmd = ['jar', 'cf0', jar_path]
     31   if manifest_file:
     32     jar_cmd[1] += 'm'
     33     jar_cmd.append(os.path.abspath(manifest_file))
     34   jar_cmd.extend(class_files_rel)
     35 
     36   if not class_files_rel:
     37     empty_file = os.path.join(classes_dir, '.empty')
     38     build_utils.Touch(empty_file)
     39     jar_cmd.append(os.path.relpath(empty_file, jar_cwd))
     40   build_utils.CheckOutput(jar_cmd, cwd=jar_cwd)
     41   build_utils.Touch(jar_path, fail_if_missing=True)
     42 
     43 
     44 def JarDirectory(classes_dir, jar_path, manifest_file=None, predicate=None):
     45   class_files = build_utils.FindInDirectory(classes_dir, '*.class')
     46   if predicate:
     47     class_files = [f for f in class_files if predicate(f)]
     48 
     49   Jar(class_files, classes_dir, jar_path, manifest_file=manifest_file)
     50 
     51 
     52 def main():
     53   parser = optparse.OptionParser()
     54   parser.add_option('--classes-dir', help='Directory containing .class files.')
     55   parser.add_option('--input-jar', help='Jar to include .class files from')
     56   parser.add_option('--jar-path', help='Jar output path.')
     57   parser.add_option('--excluded-classes',
     58       help='GYP list of .class file patterns to exclude from the jar.')
     59   parser.add_option('--strip-resource-classes-for',
     60       help='GYP list of java package names exclude R.class files in.')
     61   parser.add_option('--stamp', help='Path to touch on success.')
     62 
     63   args = build_utils.ExpandFileArgs(sys.argv[1:])
     64   options, _ = parser.parse_args(args)
     65   # Current implementation supports just one or the other of these:
     66   assert not options.classes_dir or not options.input_jar
     67 
     68   excluded_classes = []
     69   if options.excluded_classes:
     70     excluded_classes = build_utils.ParseGypList(options.excluded_classes)
     71 
     72   if options.strip_resource_classes_for:
     73     packages = build_utils.ParseGypList(options.strip_resource_classes_for)
     74     excluded_classes.extend(p.replace('.', '/') + '/' + f
     75                             for p in packages for f in _RESOURCE_CLASSES)
     76 
     77   predicate = None
     78   if excluded_classes:
     79     predicate = lambda f: not build_utils.MatchesGlob(f, excluded_classes)
     80 
     81   with build_utils.TempDir() as temp_dir:
     82     classes_dir = options.classes_dir
     83     if options.input_jar:
     84       build_utils.ExtractAll(options.input_jar, temp_dir)
     85       classes_dir = temp_dir
     86     JarDirectory(classes_dir, options.jar_path, predicate=predicate)
     87 
     88   if options.stamp:
     89     build_utils.Touch(options.stamp)
     90 
     91 
     92 if __name__ == '__main__':
     93   sys.exit(main())
     94 
     95