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.
7 """Creates a TOC file from a Java jar.
9 The TOC file contains the non-package API of the jar. This includes all
10 public/protected/package classes/functions/members and the values of static
11 final variables (members with package access are kept because in some cases we
12 have multiple libraries with the same package, particularly test+non-test). Some
13 other information (major/minor javac version) is also included.
15 This TOC file then can be used to determine if a dependent library should be
16 rebuilt when this jar changes. I.e. any change to the jar that would require a
17 rebuild, will have a corresponding change in the TOC file.
26 from util
import build_utils
27 from util
import md5_check
30 def GetClassesInZipFile(zip_file
):
32 files
= zip_file
.namelist()
34 if f
.endswith('.class'):
35 # f is of the form org/chromium/base/Class$Inner.class
36 classes
.append(f
.replace('/', '.')[:-6])
40 def CallJavap(classpath
, classes
):
43 '-package', # Show public/protected/package.
44 # -verbose is required to get constant values (which can be inlined in
47 '-classpath', classpath
49 return build_utils
.CheckOutput(javap_cmd
)
52 def ExtractToc(disassembled_classes
):
53 # javap output is structured by indent (2-space) levels.
55 '^[^ ]', # This includes all class/function/member signatures.
62 '^const #', # Matches the constant pool (i.e. literals used in the class).
65 def JavapFilter(line
):
66 return (re
.match('|'.join(good_patterns
), line
) and
67 not re
.match('|'.join(bad_patterns
), line
))
68 toc
= filter(JavapFilter
, disassembled_classes
.split('\n'))
73 def UpdateToc(jar_path
, toc_path
):
74 classes
= GetClassesInZipFile(zipfile
.ZipFile(jar_path
))
77 javap_output
= CallJavap(classpath
=jar_path
, classes
=classes
)
78 toc
= ExtractToc(javap_output
)
80 with
open(toc_path
, 'w') as tocfile
:
84 def DoJarToc(options
):
85 jar_path
= options
.jar_path
86 toc_path
= options
.toc_path
87 record_path
= '%s.md5.stamp' % toc_path
88 md5_check
.CallAndRecordIfStale(
89 lambda: UpdateToc(jar_path
, toc_path
),
90 record_path
=record_path
,
91 input_paths
=[jar_path
],
92 force
=not os
.path
.exists(toc_path
),
94 build_utils
.Touch(toc_path
, fail_if_missing
=True)
98 parser
= optparse
.OptionParser()
99 build_utils
.AddDepfileOption(parser
)
101 parser
.add_option('--jar-path', help='Input .jar path.')
102 parser
.add_option('--toc-path', help='Output .jar.TOC path.')
103 parser
.add_option('--stamp', help='Path to touch on success.')
105 options
, _
= parser
.parse_args()
108 build_utils
.WriteDepfile(
110 build_utils
.GetPythonDependencies())
115 build_utils
.WriteDepfile(
117 build_utils
.GetPythonDependencies())
120 build_utils
.Touch(options
.stamp
)
123 if __name__
== '__main__':