aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Irina Iancu <elenairina@google.com>2017-01-16 09:11:33 +0000
committerGravatar Vladimir Moskva <vladmos@google.com>2017-01-16 13:47:07 +0000
commite9674fb187b5b95136eb93058eab9d48dcfdbeca (patch)
tree450ff9f6a59166a0767a1f39ed60aee3ab3aa52c
parent266bb166293c44cd6fb25d66fc2b2aff328ed69e (diff)
Adding Java compilation to java_lite_proto_library Skylark version.
-- PiperOrigin-RevId: 144608820 MOS_MIGRATED_REVID=144608820
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java136
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoSkylarkCommon.java47
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java18
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/java/proto/SkylarkJavaLiteProtoLibraryTest.java366
5 files changed, 568 insertions, 3 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
index d89953d1bf..362fd2709b 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/BazelRuleClassProvider.java
@@ -52,6 +52,7 @@ import com.google.devtools.build.lib.bazel.rules.java.BazelJavaImportRule;
import com.google.devtools.build.lib.bazel.rules.java.BazelJavaLibraryRule;
import com.google.devtools.build.lib.bazel.rules.java.BazelJavaPluginRule;
import com.google.devtools.build.lib.bazel.rules.java.BazelJavaRuleClasses;
+import com.google.devtools.build.lib.bazel.rules.java.BazelJavaSemantics;
import com.google.devtools.build.lib.bazel.rules.java.BazelJavaTestRule;
import com.google.devtools.build.lib.bazel.rules.java.proto.BazelJavaLiteProtoAspect;
import com.google.devtools.build.lib.bazel.rules.java.proto.BazelJavaLiteProtoLibraryRule;
@@ -550,8 +551,9 @@ public class BazelRuleClassProvider {
builder.addRuleDefinition(new BazelAarImportRule());
builder.addSkylarkAccessibleTopLevels("android_common", new AndroidSkylarkCommon());
+ builder.addSkylarkAccessibleTopLevels(
+ "java_common", new JavaSkylarkCommon(BazelJavaSemantics.INSTANCE));
builder.addSkylarkAccessibleTopLevels("java_proto_common", JavaProtoSkylarkCommon.class);
- builder.addSkylarkAccessibleTopLevels("java_common", JavaSkylarkCommon.INSTANCE);
try {
builder.addWorkspaceFilePrefix(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java
index 7797ef5658..632dba6da4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaSkylarkCommon.java
@@ -13,14 +13,33 @@
// limitations under the License.
package com.google.devtools.build.lib.rules.java;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.MiddlemanProvider;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration.StrictDepsMode;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.SkylarkClassObjectConstructor;
+import com.google.devtools.build.lib.rules.SkylarkRuleContext;
+import com.google.devtools.build.lib.skylarkinterface.Param;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import com.google.devtools.build.lib.syntax.SkylarkList;
+import java.util.LinkedList;
+import java.util.List;
/** A module that contains Skylark utilities for Java support. */
@SkylarkModule(name = "java_common", doc = "Utilities for Java compilation support in Skylark.")
public class JavaSkylarkCommon {
- public static final JavaSkylarkCommon INSTANCE = new JavaSkylarkCommon();
+ private final JavaSemantics javaSemantics;
+
+ public JavaSkylarkCommon(JavaSemantics javaSemantics) {
+ this.javaSemantics = javaSemantics;
+ }
@SkylarkCallable(
name = "provider",
@@ -30,4 +49,119 @@ public class JavaSkylarkCommon {
public SkylarkClassObjectConstructor getJavaProvider() {
return JavaProvider.JAVA_PROVIDER;
}
+
+ @SkylarkCallable(
+ name = "compile",
+ // There is one mandatory positional: the Skylark rule context.
+ mandatoryPositionals = 1,
+ parameters = {
+ @Param(
+ name = "source_jars",
+ positional = false,
+ named = true,
+ type = SkylarkList.class,
+ generic1 = Artifact.class
+ ),
+ @Param(name = "output", positional = false, named = true, type = Artifact.class),
+ @Param(
+ name = "javac_opts",
+ positional = false,
+ named = true,
+ type = SkylarkList.class,
+ generic1 = String.class
+ ),
+ @Param(
+ name = "deps",
+ positional = false,
+ named = true,
+ type = SkylarkList.class,
+ generic1 = JavaProvider.class
+ ),
+ @Param(
+ name = "strict_deps",
+ defaultValue = "OFF",
+ positional = false,
+ named = true,
+ type = String.class
+ ),
+ @Param(
+ name = "java_toolchain",
+ positional = false,
+ named = true,
+ type = ConfiguredTarget.class
+ ),
+ @Param(
+ name = "host_javabase",
+ positional = false,
+ named = true,
+ type = ConfiguredTarget.class
+ ),
+ }
+ )
+ public JavaProvider createJavaCompileAction(
+ SkylarkRuleContext skylarkRuleContext,
+ SkylarkList<Artifact> sourceJars,
+ Artifact outputJar,
+ SkylarkList<String> javacOpts,
+ SkylarkList<JavaProvider> deps,
+ String strictDepsMode,
+ ConfiguredTarget javaToolchain,
+ ConfiguredTarget hostJavabase) {
+ JavaLibraryHelper helper =
+ new JavaLibraryHelper(skylarkRuleContext.getRuleContext())
+ .setOutput(outputJar)
+ .addSourceJars(sourceJars)
+ .setJavacOpts(javacOpts);
+ helper.addAllDeps(getJavaCompilationArgsProviders(deps));
+ helper.setCompilationStrictDepsMode(getStrictDepsMode(strictDepsMode));
+ MiddlemanProvider hostJavabaseProvider = hostJavabase.getProvider(MiddlemanProvider.class);
+
+ NestedSet<Artifact> hostJavabaseArtifacts =
+ hostJavabase == null
+ ? NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER)
+ : hostJavabaseProvider.getMiddlemanArtifact();
+ JavaToolchainProvider javaToolchainProvider =
+ checkNotNull(javaToolchain.getProvider(JavaToolchainProvider.class));
+ JavaCompilationArgs artifacts =
+ helper.build(
+ javaSemantics,
+ javaToolchainProvider,
+ hostJavabaseArtifacts,
+ SkylarkList.createImmutable(ImmutableList.<Artifact>of()));
+ return new JavaProvider(helper.buildCompilationArgsProvider(artifacts, true));
+ }
+
+ @SkylarkCallable(
+ name = "merge",
+ // We have one positional argument: the list of providers to merge.
+ mandatoryPositionals = 1
+ )
+ public static JavaProvider mergeJavaProviders(SkylarkList<JavaProvider> providers) {
+ return new JavaProvider(
+ JavaCompilationArgsProvider.merge(getJavaCompilationArgsProviders(providers)));
+ }
+
+ private static List<JavaCompilationArgsProvider> getJavaCompilationArgsProviders(
+ SkylarkList<JavaProvider> providers) {
+ List<JavaCompilationArgsProvider> javaCompilationArgsProviders = new LinkedList<>();
+ for (JavaProvider provider : providers) {
+ javaCompilationArgsProviders.add(provider.getJavaCompilationArgsProvider());
+ }
+ return javaCompilationArgsProviders;
+ }
+
+ private static StrictDepsMode getStrictDepsMode(String strictDepsMode) {
+ switch (strictDepsMode) {
+ case "OFF":
+ return StrictDepsMode.OFF;
+ case "ERROR":
+ return StrictDepsMode.ERROR;
+ default:
+ throw new IllegalArgumentException(
+ "StrictDepsMode "
+ + strictDepsMode
+ + " not allowed."
+ + " Only OFF and ERROR values are accepted.");
+ }
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoSkylarkCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoSkylarkCommon.java
index 4135d4029a..5612095478 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoSkylarkCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaProtoSkylarkCommon.java
@@ -19,7 +19,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.rules.SkylarkRuleContext;
+import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
+import com.google.devtools.build.lib.rules.java.JavaProvider;
+import com.google.devtools.build.lib.rules.java.JavaSemantics;
+import com.google.devtools.build.lib.rules.java.JavaToolchainProvider;
import com.google.devtools.build.lib.rules.proto.ProtoCompileActionBuilder;
import com.google.devtools.build.lib.rules.proto.ProtoLangToolchainProvider;
import com.google.devtools.build.lib.rules.proto.ProtoSupportDataProvider;
@@ -27,6 +32,7 @@ import com.google.devtools.build.lib.rules.proto.SupportData;
import com.google.devtools.build.lib.skylarkinterface.Param;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
+import java.util.List;
/**
* A class that exposes Java common methods for proto compilation.
@@ -77,6 +83,47 @@ public class JavaProtoSkylarkCommon {
true /* allowServices */);
}
+ @SkylarkCallable(
+ name = "toolchain_deps",
+ // This function is experimental for now.
+ documented = false,
+ // There's only one mandatory positional,the Skylark context
+ mandatoryPositionals = 1,
+ parameters = {
+ @Param(name = "proto_toolchain_attr", positional = false, named = true, type = String.class)
+ }
+ )
+ public static JavaProvider getRuntimeToolchainProvider(
+ SkylarkRuleContext skylarkRuleContext, String protoToolchainAttr) {
+ TransitiveInfoCollection runtime =
+ getProtoToolchainProvider(skylarkRuleContext, protoToolchainAttr).runtime();
+ return new JavaProvider(runtime.getProvider(JavaCompilationArgsProvider.class));
+ }
+
+ @SkylarkCallable(
+ name = "javac_opts",
+ // This function is experimental for now.
+ documented = false,
+ // There's only one mandatory positional,the Skylark context
+ mandatoryPositionals = 1,
+ parameters = {
+ @Param(name = "java_toolchain_attr", positional = false, named = true, type = String.class)
+ }
+ )
+ // TODO(elenairina): Consider a nicer way of returning this, taking in a JavaToolchainProvider.
+ public static List<String> getJavacOpts(
+ SkylarkRuleContext skylarkRuleContext, String javaToolchainAttr) {
+ ConfiguredTarget javaToolchainConfigTarget =
+ (ConfiguredTarget) checkNotNull(skylarkRuleContext.getAttr().getValue(javaToolchainAttr));
+ JavaToolchainProvider toolchain =
+ checkNotNull(javaToolchainConfigTarget.getProvider(JavaToolchainProvider.class));
+
+ return ImmutableList.<String>builder()
+ .addAll(toolchain.getJavacOptions())
+ .addAll(toolchain.getCompatibleJavacOptions(JavaSemantics.PROTO_JAVACOPTS_KEY))
+ .build();
+ }
+
private static ProtoLangToolchainProvider getProtoToolchainProvider(
SkylarkRuleContext skylarkRuleContext, String protoToolchainAttr) {
ConfiguredTarget javaliteToolchain = (ConfiguredTarget) checkNotNull(
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java b/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java
index bb859c90c6..387b565e44 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java
@@ -157,12 +157,28 @@ public final class EvalUtils {
|| c.equals(String.class) // basic values
|| c.equals(Integer.class)
|| c.equals(Boolean.class)
- || c.isAnnotationPresent(SkylarkModule.class) // registered Skylark class
+ // there is a registered Skylark ancestor class (useful e.g. when using AutoValue)
+ || hasSkylarkAcceptableAncestor(c)
|| ImmutableMap.class.isAssignableFrom(c) // will be converted to SkylarkDict
|| NestedSet.class.isAssignableFrom(c) // will be converted to SkylarkNestedSet
|| c.equals(PathFragment.class); // other known class
}
+ private static boolean hasSkylarkAcceptableAncestor(Class<?> c) {
+ if (c == null) {
+ return false;
+ }
+ if (c.isAnnotationPresent(SkylarkModule.class)) {
+ return true;
+ }
+ for (Class<?> inter : c.getInterfaces()) {
+ if (hasSkylarkAcceptableAncestor(inter)) {
+ return true;
+ }
+ }
+ return hasSkylarkAcceptableAncestor(c.getSuperclass());
+ }
+
// TODO(bazel-team): move the following few type-related functions to SkylarkType
/**
* Return the Skylark-type of {@code c}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/java/proto/SkylarkJavaLiteProtoLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/java/proto/SkylarkJavaLiteProtoLibraryTest.java
new file mode 100644
index 0000000000..d4fae4a945
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/java/proto/SkylarkJavaLiteProtoLibraryTest.java
@@ -0,0 +1,366 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.rules.java.proto;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.actions.Artifact.ROOT_RELATIVE_PATH_STRING;
+import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.prettyArtifactNames;
+import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.prettyJarNames;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimaps;
+import com.google.common.eventbus.EventBus;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.SkylarkProviders;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.rules.java.JavaCompilationArgs;
+import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
+import com.google.devtools.build.lib.rules.java.JavaCompileAction;
+import com.google.devtools.build.lib.rules.java.JavaProvider;
+import com.google.devtools.build.lib.testutil.MoreAsserts;
+import com.google.devtools.build.runtime.Runfiles;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for the Skylark version of java_lite_proto_library rule.
+ */
+@RunWith(JUnit4.class)
+public class SkylarkJavaLiteProtoLibraryTest extends BuildViewTestCase {
+ private static final String RULE_DIRECTORY = "tools/build_rules/java_lite_proto_library";
+ private ActionsTestUtil actionsTestUtil;
+
+ @Before
+ public final void setUpMocks() throws Exception {
+ scratch.file(
+ "java/com/google/io/protocol/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_import(name = 'protocol',",
+ " jars = [ 'protocol.jar' ])");
+ scratch.file(
+ "java/com/google/io/protocol2/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_import(name = 'protocol2',",
+ " jars = [ 'protocol2.jar' ])");
+
+ scratch.file("net/proto/BUILD", "exports_files(['sawzall_message_set.proto'])");
+ scratch.file("net/proto2/compiler/public/BUILD", "exports_files(['protocol_compiler'])");
+
+ mockToolchains();
+
+ actionsTestUtil = actionsTestUtil();
+ }
+
+ @Before
+ public final void setupSkylarkRule() throws Exception {
+ File[] files = Runfiles.location(RULE_DIRECTORY).listFiles();
+ for (File file : files) {
+ scratch.file(RULE_DIRECTORY + "/" + file.getName(), Files.readAllBytes(file.toPath()));
+ }
+ scratch.file(RULE_DIRECTORY + "/BUILD", "exports_files(['java_lite_proto_library.bzl'])");
+ invalidatePackages();
+ }
+
+ private void mockToolchains() throws IOException {
+ mockRuntimes();
+
+ scratch.file(
+ "tools/proto/toolchains/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "proto_lang_toolchain(",
+ " name = 'javalite',",
+ " command_line = '--java_out=lite,immutable,no_enforce_api_compatibility:$(OUT)',",
+ " runtime = '//protobuf:javalite_runtime',",
+ ")");
+ }
+
+ private void mockRuntimes() throws IOException {
+ mockToolsConfig.overwrite(
+ "protobuf/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_library(name = 'javalite_runtime', srcs = ['javalite_runtime.java'])");
+ }
+
+ /** Tests that java_binaries which depend on proto_libraries depend on the right set of files. */
+ @Test
+ public void testBinaryDeps() throws Exception {
+ scratch.file(
+ "x/BUILD",
+ "load('//" + RULE_DIRECTORY + ":java_lite_proto_library.bzl', ",
+ "'java_lite_proto_library')",
+ "java_lite_proto_library(name = 'lite_pb2', deps = [':foo'])",
+ "proto_library(name = 'foo', srcs = ['foo.proto', 'bar.proto'], deps = [':baz'])",
+ "proto_library(name = 'baz', srcs = ['baz.proto'])");
+
+ ConfiguredTarget target = getConfiguredTarget("//x:lite_pb2");
+ NestedSet<Artifact> filesToBuild = getFilesToBuild(target);
+ Iterable<String> deps = prettyArtifactNames(actionsTestUtil.artifactClosureOf(filesToBuild));
+
+ // Should depend on compiler and Java proto1 API.
+ assertThat(deps).contains("net/proto2/compiler/public/protocol_compiler");
+
+ // Also should not depend on RPC APIs.
+ assertThat(deps).doesNotContain("apps/xplat/rpc/codegen/protoc-gen-rpc");
+
+ // Should depend on Java outputs.
+ assertThat(deps).contains("x/foo-lite-src.jar");
+ assertThat(deps).contains("x/baz-lite-src.jar");
+
+ // Should depend on Java libraries.
+ assertThat(deps).contains("x/libfoo-lite.jar");
+ assertThat(deps).contains("x/libbaz-lite.jar");
+ assertThat(deps).contains("protobuf/libjavalite_runtime-hjar.jar");
+ }
+
+ /** Tests that we pass the correct arguments to the protocol compiler. */
+ @Test
+ public void testJavaProto2CompilerArgs() throws Exception {
+ scratch.file(
+ "x/BUILD",
+ "load('//" + RULE_DIRECTORY + ":java_lite_proto_library.bzl',",
+ "'java_lite_proto_library')",
+ "java_lite_proto_library(name = 'lite_pb2', deps = [':protolib'])",
+ "proto_library(name = 'protolib', srcs = ['file.proto'])");
+
+ String genfilesDir = targetConfig.getGenfilesFragment().getPathString();
+
+ List<String> args =
+ getGeneratingSpawnAction(getConfiguredTarget("//x:lite_pb2"), "x/protolib-lite-src.jar")
+ .getRemainingArguments();
+
+ assertThat(args)
+ .contains(
+ "--java_out=lite,immutable,no_enforce_api_compatibility:"
+ + genfilesDir
+ + "/x/protolib-lite-src.jar");
+
+ MoreAsserts.assertContainsSublist(args, "-Ix/file.proto=x/file.proto", "x/file.proto");
+ }
+
+ @Test
+ public void testProtoLibraryBuildsCompiledJar() throws Exception {
+ ConfiguredTarget target =
+ scratchConfiguredTarget(
+ "java",
+ "lite_pb2",
+ "load('//tools/build_rules/java_lite_proto_library:java_lite_proto_library.bzl',",
+ "'java_lite_proto_library')",
+ "java_lite_proto_library(name = 'lite_pb2', deps = [':compiled'])",
+ "proto_library(name = 'compiled',",
+ " srcs = [ 'ok.proto' ])");
+
+ Artifact compiledJar =
+ ActionsTestUtil.getFirstArtifactEndingWith(
+ getFilesToBuild(target), "/libcompiled-lite.jar");
+ assertThat(compiledJar).isNotNull();
+ }
+
+ @Test
+ public void testEmptySrcsForJavaApi() throws Exception {
+ ConfiguredTarget target =
+ scratchConfiguredTarget(
+ "notbad",
+ "lite_pb2",
+ "load('//tools/build_rules/java_lite_proto_library:java_lite_proto_library.bzl',",
+ "'java_lite_proto_library')",
+ "java_lite_proto_library(name = 'lite_pb2', deps = [':null_lib'])",
+ "proto_library(name = 'null_lib')");
+ JavaCompilationArgsProvider provider = getJavaCompilationArgsProvider(target);
+ assertThat(provider).isNotNull();
+ assertThat(provider.getJavaCompilationArgs()).isNotNull();
+ }
+
+ @Test
+ public void testSameVersionCompilerArguments() throws Exception {
+ scratch.file(
+ "cross/BUILD",
+ "load('//tools/build_rules/java_lite_proto_library:java_lite_proto_library.bzl',",
+ "'java_lite_proto_library')",
+ "java_lite_proto_library(name = 'lite_pb2', deps = ['bravo'], strict_deps = 0)",
+ "proto_library(name = 'bravo', srcs = ['bravo.proto'], deps = [':alpha'])",
+ "proto_library(name = 'alpha')");
+
+ String genfilesDir = targetConfig.getGenfilesFragment().getPathString();
+
+ ConfiguredTarget litepb2 = getConfiguredTarget("//cross:lite_pb2");
+
+ List<String> args =
+ getGeneratingSpawnAction(litepb2, "cross/bravo-lite-src.jar").getRemainingArguments();
+ assertThat(args)
+ .contains(
+ "--java_out=lite,immutable,no_enforce_api_compatibility:"
+ + genfilesDir
+ + "/cross/bravo-lite-src.jar");
+ MoreAsserts.assertContainsSublist(
+ args, "-Icross/bravo.proto=cross/bravo.proto", "cross/bravo.proto");
+
+ List<String> directJars =
+ prettyJarNames(
+ getJavaCompilationArgsProvider(litepb2).getJavaCompilationArgs().getRuntimeJars());
+ assertThat(directJars).containsExactly("cross/libbravo-lite.jar");
+ }
+
+ /** Protobufs should always be compiled with the default and proto javacopts. */
+ @Test
+ public void testJavacOpts() throws Exception {
+ ConfiguredTarget rule =
+ scratchConfiguredTarget(
+ "x",
+ "lite_pb2",
+ "load('//tools/build_rules/java_lite_proto_library:java_lite_proto_library.bzl',",
+ "'java_lite_proto_library')",
+ "java_lite_proto_library(name = 'lite_pb2', deps = [':proto_lib'])",
+ "proto_library(name = 'proto_lib',",
+ " srcs = ['input1.proto', 'input2.proto'])");
+ JavaCompilationArgs compilationArgs =
+ getJavaCompilationArgsProvider(rule).getJavaCompilationArgs();
+ assertThat(compilationArgs.getInstrumentationMetadata()).isEmpty();
+
+ ImmutableListMultimap<String, Artifact> runtimeJars =
+ Multimaps.index(compilationArgs.getRuntimeJars(), ROOT_RELATIVE_PATH_STRING);
+
+ Artifact jar = Iterables.getOnlyElement(runtimeJars.get("x/libproto_lib-lite.jar"));
+ JavaCompileAction action = (JavaCompileAction) getGeneratingAction(jar);
+
+ List<String> commandLine = ImmutableList.copyOf(action.buildCommandLine());
+ assertThat(commandLine).contains("-protoMarkerForTest");
+ }
+
+ /**
+ * Verify that a java_lite_proto_library exposes Skylark providers for the Java code it generates.
+ */
+ @Test
+ public void testJavaProtosExposeSkylarkProviders() throws Exception {
+ scratch.file(
+ "proto/extensions.bzl",
+ "def _impl(ctx):",
+ " print (ctx.attr.dep[java_common.provider])",
+ "custom_rule = rule(",
+ " implementation=_impl,",
+ " attrs={",
+ " 'dep': attr.label()",
+ " },",
+ ")");
+ scratch.file(
+ "proto/BUILD",
+ "load('/proto/extensions', 'custom_rule')",
+ "load('//tools/build_rules/java_lite_proto_library:java_lite_proto_library.bzl',",
+ "'java_lite_proto_library')",
+ "proto_library(",
+ " name = 'proto',",
+ " srcs = [ 'file.proto' ],",
+ ")",
+ "java_lite_proto_library(name = 'lite_pb2', deps = [':proto'])",
+ "custom_rule(name = 'custom', dep = ':lite_pb2')");
+ update(
+ ImmutableList.of("//proto:custom"),
+ false /* keepGoing */,
+ 1 /* loadingPhaseThreads */,
+ true /* doAnalysis */,
+ new EventBus());
+ // Implicitly check that `update()` above didn't throw an exception. This implicitly checks that
+ // ctx.attr.dep.java.{transitive_deps, outputs}, above, is defined.
+ }
+
+ @Test
+ public void testProtoLibraryInterop() throws Exception {
+ scratch.file(
+ "proto/BUILD",
+ "load('//tools/build_rules/java_lite_proto_library:java_lite_proto_library.bzl',",
+ "'java_lite_proto_library')",
+ "proto_library(",
+ " name = 'proto',",
+ " srcs = [ 'file.proto' ],",
+ " java_api_version = 2,",
+ ")",
+ "java_lite_proto_library(name = 'lite_pb2', deps = [':proto'])");
+ update(
+ ImmutableList.of("//proto:lite_pb2"),
+ false /* keepGoing */,
+ 1 /* loadingPhaseThreads */,
+ true /* doAnalysis */,
+ new EventBus());
+ }
+
+ /**
+ * Tests that a java_lite_proto_library only provides direct jars corresponding on the
+ * proto_library rules it directly depends on, excluding anything that the proto_library rules
+ * depends on themselves. This does not concern strict-deps in the compilation of the generated
+ * Java code itself, only compilation of regular code in java_library/java_binary and similar
+ * rules.
+ */
+ @Test
+ public void jplCorrectlyDefinesDirectJars_strictDepsEnabled() throws Exception {
+ scratch.file(
+ "x/BUILD",
+ "load('//tools/build_rules/java_lite_proto_library:java_lite_proto_library.bzl',",
+ "'java_lite_proto_library')",
+ "java_lite_proto_library(name = 'foo_lite_pb2', deps = [':foo'], strict_deps = 1)",
+ "proto_library(",
+ " name = 'foo',",
+ " srcs = [ 'foo.proto' ],",
+ " deps = [ ':bar' ],",
+ ")",
+ "java_lite_proto_library(name = 'bar_lite_pb2', deps = [':bar'])",
+ "proto_library(",
+ " name = 'bar',",
+ " srcs = [ 'bar.proto' ],",
+ " deps = [ ':baz' ],",
+ ")",
+ "proto_library(",
+ " name = 'baz',",
+ " srcs = [ 'baz.proto' ],",
+ ")");
+
+ {
+ JavaCompilationArgsProvider compilationArgsProvider =
+ getJavaCompilationArgsProvider(getConfiguredTarget("//x:foo_lite_pb2"));
+
+ Iterable<String> directJars =
+ prettyJarNames(compilationArgsProvider.getJavaCompilationArgs().getCompileTimeJars());
+
+ assertThat(directJars).containsExactly("x/libfoo-lite-hjar.jar");
+ }
+
+ {
+ JavaCompilationArgsProvider compilationArgsProvider =
+ getJavaCompilationArgsProvider(getConfiguredTarget("//x:bar_lite_pb2"));
+
+ Iterable<String> directJars =
+ prettyJarNames(compilationArgsProvider.getJavaCompilationArgs().getCompileTimeJars());
+
+ assertThat(directJars).containsExactly("x/libbar-lite-hjar.jar");
+ }
+ }
+
+ private static JavaCompilationArgsProvider getJavaCompilationArgsProvider(
+ ConfiguredTarget target) {
+ SkylarkProviders skylarkProviders = target.getProvider(SkylarkProviders.class);
+ JavaProvider javaProvider =
+ (JavaProvider) skylarkProviders.getDeclaredProvider(JavaProvider.JAVA_PROVIDER.getKey());
+ return javaProvider.getJavaCompilationArgsProvider();
+ }
+}