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
48 '-classpath', classpath
50 return build_utils
.CheckOutput(javap_cmd
)
53 def ExtractToc(disassembled_classes
):
54 # javap output is structured by indent (2-space) levels.
56 '^[^ ]', # This includes all class/function/member signatures.
63 '^const #', # Matches the constant pool (i.e. literals used in the class).
66 def JavapFilter(line
):
67 return (re
.match('|'.join(good_patterns
), line
) and
68 not re
.match('|'.join(bad_patterns
), line
))
69 toc
= filter(JavapFilter
, disassembled_classes
.split('\n'))
74 def UpdateToc(jar_path
, toc_path
):
75 classes
= GetClassesInZipFile(zipfile
.ZipFile(jar_path
))
78 javap_output
= CallJavap(classpath
=jar_path
, classes
=classes
)
79 toc
= ExtractToc(javap_output
)
81 with
open(toc_path
, 'w') as tocfile
:
85 def DoJarToc(options
):
86 jar_path
= options
.jar_path
87 toc_path
= options
.toc_path
88 record_path
= '%s.md5.stamp' % toc_path
89 md5_check
.CallAndRecordIfStale(
90 lambda: UpdateToc(jar_path
, toc_path
),
91 record_path
=record_path
,
92 input_paths
=[jar_path
],
93 force
=not os
.path
.exists(toc_path
),
95 build_utils
.Touch(toc_path
, fail_if_missing
=True)
99 parser
= optparse
.OptionParser()
100 build_utils
.AddDepfileOption(parser
)
102 parser
.add_option('--jar-path', help='Input .jar path.')
103 parser
.add_option('--toc-path', help='Output .jar.TOC path.')
104 parser
.add_option('--stamp', help='Path to touch on success.')
106 options
, _
= parser
.parse_args()
109 build_utils
.WriteDepfile(
111 build_utils
.GetPythonDependencies())
116 build_utils
.WriteDepfile(
118 build_utils
.GetPythonDependencies())
121 build_utils
.Touch(options
.stamp
)
124 if __name__
== '__main__':