diff options
author | 2017-01-16 09:11:33 +0000 | |
---|---|---|
committer | 2017-01-16 13:47:07 +0000 | |
commit | e9674fb187b5b95136eb93058eab9d48dcfdbeca (patch) | |
tree | 450ff9f6a59166a0767a1f39ed60aee3ab3aa52c /src/main/java | |
parent | 266bb166293c44cd6fb25d66fc2b2aff328ed69e (diff) |
Adding Java compilation to java_lite_proto_library Skylark version.
--
PiperOrigin-RevId: 144608820
MOS_MIGRATED_REVID=144608820
Diffstat (limited to 'src/main/java')
4 files changed, 202 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} |