Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to extract proguard configurations in jvm_import #920

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ build --tool_java_runtime_version=remotejdk_11
build --experimental_strict_java_deps=strict
build --explicit_java_test_deps

build --experimental_google_legacy_api

# Make sure we get something helpful when tests fail
test --verbose_failures
test --test_output=errors
Expand Down
1 change: 1 addition & 0 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ bzl_library(
"//private/rules:urls.bzl",
"//private/rules:v1_lock_file.bzl",
"//private/rules:v2_lock_file.bzl",
"//settings:extract_proguard_config.bzl",
"//settings:stamp_manifest.bzl",
],
visibility = [
Expand Down
2 changes: 2 additions & 0 deletions examples/android_instrumentation_test/.bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,5 @@ build:rbe_demo --experimental_remote_download_outputs=toplevel
build:rbe_demo --experimental_inmemory_dotd_files
build:rbe_demo --experimental_inmemory_jdeps_files
build:rbe_demo --jobs=300

build --experimental_google_legacy_api # Needed to use ProguardSpecProvider
1 change: 1 addition & 0 deletions examples/android_kotlin_app/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build --experimental_google_legacy_api # Needed to use ProguardSpecProvider
1 change: 1 addition & 0 deletions examples/android_local_test/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build --experimental_google_legacy_api # Needed to use ProguardSpecProvider
2 changes: 2 additions & 0 deletions examples/java-export/.bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ build --java_runtime_version=remotejdk_11
build --tool_java_language_version=11

build --javacopt="--release 11"

build --experimental_google_legacy_api # Needed to use ProguardSpecProvider
1 change: 1 addition & 0 deletions examples/kt_android_local_test/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build --experimental_google_legacy_api # Needed to use ProguardSpecProvider
1 change: 1 addition & 0 deletions examples/pom_file_generation/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build --experimental_google_legacy_api # Needed to use ProguardSpecProvider
1 change: 1 addition & 0 deletions examples/protobuf-java/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build --experimental_google_legacy_api # Needed to use ProguardSpecProvider
1 change: 1 addition & 0 deletions examples/scala_akka/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build --experimental_google_legacy_api # Needed to use ProguardSpecProvider
1 change: 1 addition & 0 deletions examples/simple/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build --experimental_google_legacy_api # Needed to use ProguardSpecProvider
1 change: 1 addition & 0 deletions examples/spring_boot/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build --experimental_google_legacy_api # Needed to use ProguardSpecProvider
31 changes: 30 additions & 1 deletion private/rules/jvm_import.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
# [1]: https://github.com/bazelbuild/bazel/issues/4549

load("//settings:stamp_manifest.bzl", "StampManifestProvider")
load("//settings:extract_proguard_config.bzl", "ExtractProguardConfigProvider")

def _jvm_import_impl(ctx):
if len(ctx.files.jars) != 1:
Expand All @@ -30,6 +31,26 @@ def _jvm_import_impl(ctx):
else:
outjar = injar

proguard_info = []
if ctx.attr._extract_proguard_config[ExtractProguardConfigProvider].extract_proguard_config:
spec = ctx.actions.declare_file("%s_proguard.pro" % injar.basename.split(".jar")[0])

args = ctx.actions.args()
args.add("--jar_to_spec", "%s:%s" % (injar.path, spec.path))

ctx.actions.run(
inputs = [injar],
outputs = [spec],
executable = ctx.executable._proguard_config_extractor,
arguments = [args],
mnemonic = "ExtractProguardSpec",
progress_message = "Extracting proguard config of %s" % ctx.label,
)

proguard_info = [
ProguardSpecProvider(depset(direct = [spec])),
]

compilejar = ctx.actions.declare_file("header_" + injar.basename, sibling = injar)
args = ctx.actions.args()
args.add_all(["--source", outjar, "--output", compilejar])
Expand Down Expand Up @@ -69,7 +90,7 @@ def _jvm_import_impl(ctx):
],
neverlink = ctx.attr.neverlink,
),
]
] + proguard_info

jvm_import = rule(
attrs = {
Expand All @@ -95,9 +116,17 @@ jvm_import = rule(
cfg = "exec",
default = "//private/tools/java/com/github/bazelbuild/rules_jvm_external/jar:AddJarManifestEntry",
),
"_proguard_config_extractor": attr.label(
executable = True,
cfg = "exec",
default = "//private/tools/java/com/github/bazelbuild/rules_jvm_external/jar:ExtractProguardConfig",
),
"_stamp_manifest": attr.label(
default = "@rules_jvm_external//settings:stamp_manifest",
),
"_extract_proguard_config": attr.label(
default = "@rules_jvm_external//settings:extract_proguard_config",
),
},
implementation = _jvm_import_impl,
provides = [JavaInfo],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,14 @@ java_binary(
"//private/tools/java/com/github/bazelbuild/rules_jvm_external/zip",
],
)

java_binary(
name = "ExtractProguardConfig",
srcs = [
"ExtractProguardConfig.java",
],
main_class = "com.github.bazelbuild.rules_jvm_external.jar.ExtractProguardConfig",
visibility = [
"//visibility:public",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.github.bazelbuild.rules_jvm_external.jar;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public final class ExtractProguardConfig {

private List<String> jarToSpec;

// Directories to search for proguard configurations.
// The list is sorted from highest priorty to lowest priority
// Only the first one is extracted.
private List<String> proguardDirs = Arrays.asList(
"META-INF/com.android.tools/r8",
"META-INF/com.android.tools/proguard",
"META-INF/proguard"
);

public ExtractProguardConfig(List<String> jarToSpec) {
this.jarToSpec = jarToSpec;
}

private boolean maybeCopySpec(String jarPath, String directoryName, String spec) {
try {
JarFile jarFile = new JarFile(jarPath);
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (!entry.isDirectory() && entry.getName().startsWith(directoryName)) {
File outputFile = new File(spec);
FileOutputStream outputStream = new FileOutputStream(outputFile);
jarFile.getInputStream(entry).transferTo(outputStream);

outputStream.close();
return true;
}
}
jarFile.close();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}

private void extractSpec(String jar, String spec) {
boolean hadSpec = false;
for (String dir : proguardDirs) {
hadSpec = maybeCopySpec(jar, dir, spec);
if (hadSpec) {
break;
}
}

if (!hadSpec) {
try {
File file = new File(spec);
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}

public void run() {
for (String js : jarToSpec) {
String[] parts = js.split(":");
if (parts.length != 2) {
throw new IllegalArgumentException("Invalid jar_to_spec value: " + js);
}
extractSpec(parts[0], parts[1]);
}
}

public static void main(String[] args) {
List<String> jarToSpec = new ArrayList();
for (int i = 0; i < args.length; i++) {
if (args[i].equals("--jar_to_spec")) {
if (i + 1 < args.length) {
jarToSpec.add(args[i + 1]);
i++;
}
}
}

new ExtractProguardConfig(jarToSpec).run();
}
}
11 changes: 10 additions & 1 deletion settings/BUILD
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
load("//settings:stamp_manifest.bzl", "stamp_manifest")
load("//settings:extract_proguard_config.bzl", "extract_proguard_config")

package(
default_visibility = ["//visibility:public"],
)

exports_files(["stamp_manifest.bzl"])
exports_files([
"extract_proguard_config.bzl",
"stamp_manifest.bzl",
])

stamp_manifest(
name = "stamp_manifest",
build_setting_default = True,
)

extract_proguard_config(
name = "extract_proguard_config",
build_setting_default = False,
)
9 changes: 9 additions & 0 deletions settings/extract_proguard_config.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
ExtractProguardConfigProvider = provider(fields = ["extract_proguard_config"])

def _impl(ctx):
return ExtractProguardConfigProvider(extract_proguard_config = ctx.build_setting_value)

extract_proguard_config = rule(
implementation = _impl,
build_setting = config.bool(flag = True),
)