diff --git a/.bazelrc b/.bazelrc
index a9e05a75a..186c2d358 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -1,3 +1,5 @@
+build --experimental_google_legacy_api
+
build --java_language_version=11
build --java_runtime_version=remotejdk_11
diff --git a/private/rules/has_maven_deps.bzl b/private/rules/has_maven_deps.bzl
index ccdd5add2..07f42e4a1 100644
--- a/private/rules/has_maven_deps.bzl
+++ b/private/rules/has_maven_deps.bzl
@@ -95,6 +95,7 @@ _gathered = provider(
"artifact_infos",
"transitive_exports",
"dep_infos",
+ "artifact_coordinates",
],
)
@@ -104,7 +105,7 @@ def _extract_from(gathered, maven_info, dep, include_transitive_exports):
gathered.all_infos.append(maven_info)
gathered.label_to_javainfo.update(maven_info.label_to_javainfo)
if java_info:
- if maven_info.coordinates:
+ if maven_info.coordinates and maven_info.coordinates != gathered.artifact_coordinates:
gathered.dep_infos.append(dep[JavaInfo])
else:
gathered.artifact_infos.append(dep[JavaInfo])
@@ -129,6 +130,7 @@ def _has_maven_deps_impl(target, ctx):
transitive_exports = [],
dep_infos = [],
label_to_javainfo = {target.label: target[JavaInfo]},
+ artifact_coordinates = coordinates,
)
for attr in _ASPECT_ATTRS:
diff --git a/private/rules/maven_project_jar.bzl b/private/rules/maven_project_jar.bzl
index 5467dd7b3..8fe1d65e2 100644
--- a/private/rules/maven_project_jar.bzl
+++ b/private/rules/maven_project_jar.bzl
@@ -1,5 +1,5 @@
load(":has_maven_deps.bzl", "MavenInfo", "calculate_artifact_jars", "calculate_artifact_source_jars", "has_maven_deps")
-load(":maven_utils.bzl", "determine_additional_dependencies")
+load(":maven_utils.bzl", "determine_additional_dependencies", "unpack_coordinates")
DEFAULT_EXCLUDED_WORKSPACES = [
# Note: we choose to drop the dependency entirely because
@@ -64,7 +64,12 @@ def _maven_project_jar_impl(ctx):
)
# Merge together all the binary jars
- bin_jar = ctx.actions.declare_file("%s.jar" % ctx.label.name)
+ packaging = unpack_coordinates(info.coordinates).type or "jar"
+ bin_jar = ctx.actions.declare_file("%s.%s" % (ctx.label.name, packaging))
+
+ if packaging == "aar" and AndroidLibraryAarInfo in target and target[AndroidLibraryAarInfo].aar:
+ artifact_jars = artifact_jars + [target[AndroidLibraryAarInfo].aar]
+
_combine_jars(
ctx,
ctx.executable._merge_jars,
diff --git a/private/templates/pom.tpl b/private/templates/pom.tpl
index 1028295d1..c9acd719c 100644
--- a/private/templates/pom.tpl
+++ b/private/templates/pom.tpl
@@ -6,6 +6,7 @@
{groupId}
{artifactId}
{version}
+ {type}
{dependencies}
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/jar/MergeJars.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/jar/MergeJars.java
index 8fa7d9a1c..56377ea92 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/jar/MergeJars.java
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/jar/MergeJars.java
@@ -28,12 +28,15 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
@@ -45,18 +48,27 @@
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
+import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
public class MergeJars {
+ private enum Packaging {
+ JAR, AAR;
+ }
+
public static void main(String[] args) throws IOException {
Path out = null;
// Insertion order may matter
Set sources = new LinkedHashSet<>();
Set excludes = new HashSet<>();
DuplicateEntryStrategy onDuplicate = LAST_IN_WINS;
+ Packaging packaging = Packaging.JAR;
+ PathMatcher aarMatcher = FileSystems.getDefault().getPathMatcher("glob:*.aar");
+ // AAR to build from
+ Path aarSource = null;
for (int i = 0; i < args.length; i++) {
switch (args[i]) {
@@ -75,6 +87,9 @@ public static void main(String[] args) throws IOException {
case "--output":
out = Paths.get(args[++i]);
+ if (aarMatcher.matches(out.getFileName())) {
+ packaging = Packaging.AAR;
+ }
break;
case "--sources":
@@ -87,6 +102,26 @@ public static void main(String[] args) throws IOException {
}
}
+ if (packaging == Packaging.AAR) {
+ aarSource = sources.stream()
+ .filter(source -> aarMatcher.matches(source.getFileName()))
+ .findFirst() // AAR is explicitly only added for top level distribution target, so we _should_ only ever have 1
+ .orElseThrow(() -> new IllegalArgumentException("For AAR packaging, we require a prebuilt AAR that already contains the Android resources that we'll add the transitive source closure to."));
+
+ sources.remove(aarSource);
+
+ // Pull out classes jar and add to source set
+ Path aarClassesJar = out.getParent().resolve("aar-classes.jar");
+ try (ZipFile aar = new ZipFile(aarSource.toFile())) {
+ ZipEntry classes = aar.getEntry("classes.jar");
+ try (InputStream is = aar.getInputStream(classes);
+ OutputStream fos = Files.newOutputStream(aarClassesJar)) {
+ ByteStreams.copy(is, fos);
+ }
+ }
+ sources.add(aarClassesJar);
+ }
+
Objects.requireNonNull(out, "Output path must be set.");
if (sources.isEmpty()) {
// Just write an empty jar and leave
@@ -144,6 +179,12 @@ public static void main(String[] args) throws IOException {
continue;
}
+ // TODO: Why do we need to do this?? Is there a better way?
+ Pattern rClassMatcher = Pattern.compile("^.*\\/R(\\$.*)?\\.(class|java)");
+ if (rClassMatcher.asMatchPredicate().test(entry.getName())) {
+ continue;
+ }
+
if (!entry.isDirectory()) {
// Duplicate files, however may not be. We need the hash to determine
// whether we should do anything.
@@ -171,6 +212,53 @@ public static void main(String[] args) throws IOException {
// jar and not useful for consumers.
manifest.getMainAttributes().remove(new Attributes.Name("Target-Label"));
+ switch (packaging) {
+ case JAR:
+ writeClassesJar(out, manifest, allServices, sources, fileToSourceJar);
+ break;
+ case AAR:
+ Path classesJar = out.getParent().resolve("classes.jar");
+ writeClassesJar(classesJar, manifest, allServices, sources, fileToSourceJar);
+ writeAar(out, aarSource, classesJar);
+ }
+ }
+
+ private static void writeAar(Path out, Path aarSource, Path classesJar) throws IOException {
+ try (OutputStream os = Files.newOutputStream(out);
+ JarOutputStream jos = new JarOutputStream(os)) {
+ ZipEntry je = new StableZipEntry(classesJar.toFile().getName());
+ jos.putNextEntry(je);
+
+ try (InputStream is = Files.newInputStream(classesJar)) {
+ ByteStreams.copy(is, jos);
+ }
+ jos.closeEntry();
+
+ try (ZipFile aar = new ZipFile(aarSource.toFile())) {
+ Enumeration extends ZipEntry> entries = aar.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+
+ // transitive class closure is captured in our classes.jar
+ if ("classes.jar".equals(entry.getName())) {
+ continue;
+ }
+
+ jos.putNextEntry(new ZipEntry(entry.getName()));
+ try (InputStream is = aar.getInputStream(entry)) {
+ ByteStreams.copy(is, jos);
+ }
+ jos.closeEntry();
+ }
+ }
+ }
+ }
+
+ private static void writeClassesJar(Path out,
+ Manifest manifest,
+ Map> allServices,
+ Set sources,
+ Map fileToSourceJar) throws IOException {
// Now create the output jar
Files.createDirectories(out.getParent());
diff --git a/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java b/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java
index a9af8b5fe..9ef8e184b 100644
--- a/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java
+++ b/private/tools/java/com/github/bazelbuild/rules_jvm_external/maven/MavenPublisher.java
@@ -93,7 +93,6 @@ public static void main(String[] args)
try {
List> futures = new ArrayList<>();
- futures.add(upload(repo, credentials, coords, ".pom", pom, gpgSign));
if (mainArtifact != null) {
String ext =
@@ -101,6 +100,8 @@ public static void main(String[] args)
futures.add(upload(repo, credentials, coords, "." + ext, mainArtifact, gpgSign));
}
+ futures.add(upload(repo, credentials, coords, ".pom", pom, gpgSign));
+
if (args.length > 3 && !args[3].isEmpty()) {
List extraArtifactTuples = Splitter.onPattern(",").splitToList(args[3]);
for (String artifactTuple : extraArtifactTuples) {