Add linting for java libraries/apks to gn

BUG=359249

Review URL: https://codereview.chromium.org/465713002

git-svn-id: http://src.chromium.org/svn/trunk/src/build@291240 4ff67af0-8c30-449e-8e8b-ad334ec8d88c
This commit is contained in:
cjhopman@chromium.org 2014-08-21 23:27:22 +00:00
Родитель 71dffd6d32
Коммит cc6e76886b
3 изменённых файлов: 153 добавлений и 54 удалений

Просмотреть файл

@ -20,7 +20,7 @@ _SRC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__),
def _RunLint(lint_path, config_path, processed_config_path, manifest_path,
result_path, product_dir, src_dirs, jar_path):
result_path, product_dir, sources, jar_path):
def _RelativizePath(path):
"""Returns relative path to top-level src dir.
@ -71,62 +71,89 @@ def _RunLint(lint_path, config_path, processed_config_path, manifest_path,
print >> sys.stderr, error_line
return len(issues)
_ProcessConfigFile()
with build_utils.TempDir() as temp_dir:
_ProcessConfigFile()
cmd = [
lint_path, '-Werror', '--exitcode', '--showall',
'--config', _RelativizePath(processed_config_path),
'--classpath', _RelativizePath(jar_path),
'--xml', _RelativizePath(result_path),
]
for src in src_dirs:
cmd.extend(['--sources', _RelativizePath(src)])
cmd.append(_RelativizePath(os.path.join(manifest_path, os.pardir)))
cmd = [
_RelativizePath(lint_path), '-Werror', '--exitcode', '--showall',
'--config', _RelativizePath(processed_config_path),
'--classpath', _RelativizePath(jar_path),
'--xml', _RelativizePath(result_path),
]
if os.path.exists(result_path):
os.remove(result_path)
# There may be multiple source files with the same basename (but in
# different directories). It is difficult to determine what part of the path
# corresponds to the java package, and so instead just link the source files
# into temporary directories (creating a new one whenever there is a name
# conflict).
src_dirs = []
def NewSourceDir():
new_dir = os.path.join(temp_dir, str(len(src_dirs)))
os.mkdir(new_dir)
src_dirs.append(new_dir)
cmd.extend(['--sources', _RelativizePath(new_dir)])
return new_dir
try:
build_utils.CheckOutput(cmd, cwd=_SRC_ROOT)
except build_utils.CalledProcessError as e:
# There is a problem with lint usage
if not os.path.exists(result_path):
print 'Something is wrong:'
print e
return 0
def PathInDir(d, src):
return os.path.join(d, os.path.basename(src))
# There are actual lint issues
else:
try:
num_issues = _ParseAndShowResultFile()
except Exception:
print 'Lint created unparseable xml file...'
print 'File contents:'
with open(result_path) as f:
print f.read()
for src in sources:
src_dir = None
for d in src_dirs:
if not os.path.exists(PathInDir(d, src)):
src_dir = d
break
if not src_dir:
src_dir = NewSourceDir()
os.symlink(os.path.abspath(src), PathInDir(src_dir, src))
cmd.append(_RelativizePath(os.path.join(manifest_path, os.pardir)))
if os.path.exists(result_path):
os.remove(result_path)
try:
build_utils.CheckOutput(cmd, cwd=_SRC_ROOT)
except build_utils.CalledProcessError as e:
# There is a problem with lint usage
if not os.path.exists(result_path):
print 'Something is wrong:'
print e
return 0
_ProcessResultFile()
msg = ('\nLint found %d new issues.\n'
' - For full explanation refer to %s\n'
' - Wanna suppress these issues?\n'
' 1. Read comment in %s\n'
' 2. Run "python %s %s"\n' %
(num_issues,
_RelativizePath(result_path),
_RelativizePath(config_path),
_RelativizePath(os.path.join(_SRC_ROOT, 'build', 'android',
'lint', 'suppress.py')),
_RelativizePath(result_path)))
print >> sys.stderr, msg
# Lint errors do not fail the build.
return 0
# There are actual lint issues
else:
try:
num_issues = _ParseAndShowResultFile()
except Exception:
print 'Lint created unparseable xml file...'
print 'File contents:'
with open(result_path) as f:
print f.read()
return 0
_ProcessResultFile()
msg = ('\nLint found %d new issues.\n'
' - For full explanation refer to %s\n'
' - Wanna suppress these issues?\n'
' 1. Read comment in %s\n'
' 2. Run "python %s %s"\n' %
(num_issues,
_RelativizePath(result_path),
_RelativizePath(config_path),
_RelativizePath(os.path.join(_SRC_ROOT, 'build', 'android',
'lint', 'suppress.py')),
_RelativizePath(result_path)))
print >> sys.stderr, msg
# Lint errors do not fail the build.
return 0
return 0
def main():
parser = optparse.OptionParser()
build_utils.AddDepfileOption(parser)
parser.add_option('--lint-path', help='Path to lint executable.')
parser.add_option('--config-path', help='Path to lint suppressions file.')
parser.add_option('--processed-config-path',
@ -135,6 +162,7 @@ def main():
parser.add_option('--result-path', help='Path to XML lint result file.')
parser.add_option('--product-dir', help='Path to product dir.')
parser.add_option('--src-dirs', help='Directories containing java files.')
parser.add_option('--java-files', help='Paths to java files.')
parser.add_option('--jar-path', help='Jar file containing class files.')
parser.add_option('--stamp', help='Path to touch on success.')
parser.add_option('--enable', action='store_true',
@ -145,18 +173,30 @@ def main():
build_utils.CheckOptions(
options, parser, required=['lint_path', 'config_path',
'processed_config_path', 'manifest_path',
'result_path', 'product_dir', 'src_dirs',
'result_path', 'product_dir',
'jar_path'])
src_dirs = build_utils.ParseGypList(options.src_dirs)
rc = 0
if options.enable:
sources = []
if options.src_dirs:
src_dirs = build_utils.ParseGypList(options.src_dirs)
sources = build_utils.FindInDirectories(src_dirs, '*.java')
elif options.java_files:
sources = build_utils.ParseGypList(options.java_files)
else:
print 'One of --src-dirs or --java-files must be specified.'
return 1
rc = _RunLint(options.lint_path, options.config_path,
options.processed_config_path,
options.manifest_path, options.result_path,
options.product_dir, src_dirs, options.jar_path)
options.product_dir, sources, options.jar_path)
if options.depfile:
build_utils.WriteDepfile(
options.depfile,
build_utils.GetPythonDependencies())
if options.stamp and not rc:
build_utils.Touch(options.stamp)

Просмотреть файл

@ -11,6 +11,44 @@ rebased_android_sdk = rebase_path(android_sdk, root_build_dir)
rebased_android_sdk_root = rebase_path(android_sdk_root, root_build_dir)
rebased_android_sdk_build_tools = rebase_path(android_sdk_build_tools, root_build_dir)
template("android_lint") {
jar_path = invoker.jar_path
android_manifest = invoker.android_manifest
java_files = invoker.java_files
base_path = "$target_gen_dir/$target_name"
action(target_name) {
script = "//build/android/gyp/lint.py"
result_path = base_path + "/result.xml"
config_path = base_path + "/config.xml"
suppressions_file = "//build/android/lint/suppressions.xml"
inputs = [
suppressions_file,
android_manifest,
jar_path,
] + java_files
outputs = [
config_path,
result_path
]
rebased_java_files = rebase_path(java_files, root_build_dir)
args = [
"--lint-path=$rebased_android_sdk_root/tools/lint",
"--config-path", rebase_path(suppressions_file, root_build_dir),
"--manifest-path", rebase_path(android_manifest, root_build_dir),
"--product-dir=.",
"--jar-path", rebase_path(jar_path, root_build_dir),
"--processed-config-path", rebase_path(config_path, root_build_dir),
"--result-path", rebase_path(result_path, root_build_dir),
"--java-files=$rebased_java_files",
"--enable",
]
}
}
# Write the target's .build_config file. This is a json file that contains a
# dictionary of information about how to build this target (things that
@ -304,7 +342,7 @@ template("create_apk") {
# java_files: List of .java files to compile.
# java_deps: List of java dependencies. These should all have a .jar output
# at "${target_gen_dir}/${target_name}.jar.
# chromium_code: If 1, enable extra warnings.
# chromium_code: If true, enable extra warnings.
# srcjar_deps: List of srcjar dependencies. The .java files contained in the
# dependencies srcjar outputs will be compiled and added to the output jar.
# jar_path: Use this to explicitly set the output jar path. Defaults to
@ -419,6 +457,14 @@ template("android_java_library") {
_jar_path = invoker.jar_path
_dex_path = invoker.dex_path
_android_manifest = "//build/android/AndroidManifest.xml"
if (defined(invoker.android_manifest)) {
_android_manifest = invoker.android_manifest
}
assert(_android_manifest != "")
_final_deps = []
java_library("${target_name}__java_library") {
jar_path = _jar_path
if (defined(invoker.jar_excluded_patterns)) {
@ -432,8 +478,14 @@ template("android_java_library") {
}
}
# TODO(cjhopman): lint
if (defined(invoker.chromium_code) && invoker.chromium_code) {
_final_deps += [ ":${target_name}__lint" ]
android_lint("${target_name}__lint") {
android_manifest = _android_manifest
jar_path = _jar_path
java_files = invoker.java_files
}
}
dex("${target_name}__dex") {
sources = [_jar_path]
@ -444,7 +496,7 @@ template("android_java_library") {
deps = [
":${target_name}__java_library",
":${target_name}__dex",
]
] + _final_deps
}
}

Просмотреть файл

@ -405,7 +405,7 @@ template("java_strings_grd") {
# java_files: List of .java files included in this library.
# srcjar_deps: List of srcjar dependencies. The .java files in the srcjars
# will be added to java_files and be included in this library.
#
# chromium_code: If true, extra static analysis warning/errors will be enabled.
# jar_excluded_patterns: List of patterns of .class files to exclude from the
# final jar.
#
@ -444,7 +444,13 @@ template("android_library") {
# base_path
}
_chromium_code = true
if (defined(invoker.chromium_code)) {
_chromium_code = invoker.chromium_code
}
android_java_library(target_name) {
chromium_code = _chromium_code
java_files = invoker.java_files
build_config = build_config
@ -595,6 +601,7 @@ template("android_apk") {
final_deps += [":${target_name}__java"]
android_java_library("${target_name}__java") {
android_manifest = invoker.android_manifest
java_files = invoker.java_files
srcjar_deps = _srcjar_deps
dex_path = base_path + ".dex.jar"