Skip to content

Commit

Permalink
Adding Java compilation to java_lite_proto_library Skylark version.
Browse files Browse the repository at this point in the history
--
PiperOrigin-RevId: 144608820
MOS_MIGRATED_REVID=144608820
  • Loading branch information
iirina authored and vladmos committed Jan 16, 2017
1 parent 266bb16 commit e9674fb
Show file tree
Hide file tree
Showing 5 changed files with 568 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
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;
Expand Down Expand Up @@ -550,8 +551,9 @@ public void init(Builder builder) {
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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@
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;
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.
Expand Down Expand Up @@ -77,6 +83,47 @@ public static void createProtoCompileAction(
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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,28 @@ public static boolean isSkylarkAcceptable(Class<?> c) {
|| 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}
Expand Down
Loading

0 comments on commit e9674fb

Please sign in to comment.