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
))
75 javap_output
= CallJavap(classpath
=jar_path
, classes
=classes
)
76 toc
= ExtractToc(javap_output
)
78 with
open(toc_path
, 'w') as tocfile
:
82 def DoJarToc(options
):
83 jar_path
= options
.jar_path
84 toc_path
= options
.toc_path
85 record_path
= '%s.md5.stamp' % toc_path
86 md5_check
.CallAndRecordIfStale(
87 lambda: UpdateToc(jar_path
, toc_path
),
88 record_path
=record_path
,
89 input_paths
=[jar_path
],
90 force
=not os
.path
.exists(toc_path
),
92 build_utils
.Touch(toc_path
, fail_if_missing
=True)
96 parser
= optparse
.OptionParser()
97 build_utils
.AddDepfileOption(parser
)
99 parser
.add_option('--jar-path', help='Input .jar path.')
100 parser
.add_option('--toc-path', help='Output .jar.TOC path.')
101 parser
.add_option('--stamp', help='Path to touch on success.')
103 options
, _
= parser
.parse_args()
106 build_utils
.WriteDepfile(
108 build_utils
.GetPythonDependencies())
113 build_utils
.WriteDepfile(
115 build_utils
.GetPythonDependencies())
118 build_utils
.Touch(options
.stamp
)
121 if __name__
== '__main__':