blob: 08f6b4425580d1671544380e07a797bd988ef0d3 [file] [log] [blame]
// Copyright 2018 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.base.Preconditions.checkNotNull;
import static com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode.TARGET;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.config.CoreOptionConverters.StrictDepsMode;
import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
import com.google.devtools.build.lib.rules.java.JavaCompilationArtifacts;
import com.google.devtools.build.lib.rules.java.JavaInfo;
import com.google.devtools.build.lib.rules.java.JavaLibraryHelper;
import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider;
import com.google.devtools.build.lib.rules.java.JavaRuntimeInfo;
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.ProtoLangToolchainProvider;
/** Common logic used by java*_proto aspects (e.g. {@link JavaLiteProtoAspect}). */
public class JavaProtoAspectCommon {
// The name of an attribute of {@link JavaProtoAspect} used for storing the {@link Label} of
// the proto toolchain for Java.
public static final String SPEED_PROTO_TOOLCHAIN_ATTR = ":aspect_java_proto_toolchain";
// The name of an attribute of {@link JavaLiteProtoLibrary} and {@link JavaLiteProtoAspect} used
// for storing the {@link Label} of the proto toolchain for Java-lite.
public static final String LITE_PROTO_TOOLCHAIN_ATTR = ":aspect_proto_toolchain_for_javalite";
private static final String SPEED_JAR_SUFFIX = "-speed";
private static final String LITE_JAR_SUFFIX = "-lite";
private static final String MUTABLE_JAR_SUFFIX = "-new-mutable";
private final RuleContext ruleContext;
private final JavaSemantics javaSemantics;
private final String protoToolchainAttr;
private final String jarSuffix;
private final RpcSupport rpcSupport;
/**
* Returns a {@link JavaProtoAspectCommon} instance that handles logic for {@code
* java_proto_library}.
*/
static JavaProtoAspectCommon getSpeedInstance(
RuleContext ruleContext, JavaSemantics javaSemantics, RpcSupport rpcSupport) {
return new JavaProtoAspectCommon(
ruleContext, javaSemantics, rpcSupport, SPEED_PROTO_TOOLCHAIN_ATTR, SPEED_JAR_SUFFIX);
}
/**
* Returns a {@link JavaProtoAspectCommon} instance that handles logic for {@code
* java_lite_proto_library}.
*/
static JavaProtoAspectCommon getLiteInstance(
RuleContext ruleContext, JavaSemantics javaSemantics) {
return new JavaProtoAspectCommon(
ruleContext, javaSemantics, null, LITE_PROTO_TOOLCHAIN_ATTR, LITE_JAR_SUFFIX);
}
/**
* Returns a {@link JavaProtoAspectCommon} instance that handles logic for {@code
* java_mutable_proto_library}.
*/
public static JavaProtoAspectCommon getMutableInstance(
RuleContext ruleContext,
JavaSemantics javaSemantics,
RpcSupport rpcSupport,
String protoToolchainAttr) {
return new JavaProtoAspectCommon(
ruleContext, javaSemantics, rpcSupport, protoToolchainAttr, MUTABLE_JAR_SUFFIX);
}
private JavaProtoAspectCommon(
RuleContext ruleContext,
JavaSemantics javaSemantics,
RpcSupport rpcSupport,
String protoToolchainAttr,
String jarSuffix) {
this.ruleContext = ruleContext;
this.javaSemantics = javaSemantics;
this.protoToolchainAttr = protoToolchainAttr;
this.jarSuffix = jarSuffix;
this.rpcSupport = rpcSupport;
}
/**
* Registers an action that compiles the given {@code sourceJar} and archives the compiled classes
* into {@code outputJar}, using {@code dep} as information about the dependencies compilation.
*
* @return a {@JavaCompilationArgsProvider} wrapping information about the compilation action that
* was registered.
*/
public JavaCompilationArgsProvider createJavaCompileAction(
String injectingRuleKind,
Artifact sourceJar,
Artifact outputJar,
JavaCompilationArgsProvider dep)
throws InterruptedException {
JavaLibraryHelper helper =
new JavaLibraryHelper(ruleContext)
.setInjectingRuleKind(injectingRuleKind)
.setOutput(outputJar)
.addSourceJars(sourceJar)
.setJavacOpts(ProtoJavacOpts.constructJavacOpts(ruleContext))
.addDep(dep)
.setCompilationStrictDepsMode(StrictDepsMode.ERROR);
for (TransitiveInfoCollection t : getProtoRuntimeDeps()) {
JavaCompilationArgsProvider provider =
JavaInfo.getProvider(JavaCompilationArgsProvider.class, t);
if (provider != null) {
helper.addDep(provider);
}
}
JavaCompilationArtifacts artifacts =
helper.build(
javaSemantics,
JavaToolchainProvider.from(ruleContext),
JavaRuntimeInfo.forHost(ruleContext),
JavaRuleOutputJarsProvider.builder(),
/*createOutputSourceJar*/ false,
/*outputSourceJar=*/ null);
return helper.buildCompilationArgsProvider(
artifacts, /*isReportedAsStrict=*/ true, /*isNeverlink=*/ false);
}
/**
* Returns a list of all the target needed by proto libraries (e.g. {@code java_proto_library}) at
* runtime.
*/
public ImmutableList<TransitiveInfoCollection> getProtoRuntimeDeps() {
ImmutableList.Builder<TransitiveInfoCollection> result = ImmutableList.builder();
TransitiveInfoCollection runtime = getProtoToolchainProvider().runtime();
if (runtime != null) {
result.add(runtime);
}
if (rpcSupport != null) {
result.addAll(rpcSupport.getRuntimes(ruleContext));
}
return result.build();
}
/** Returns the toolchain that specifies how to generate code from {@code .proto} files. */
public ProtoLangToolchainProvider getProtoToolchainProvider() {
return checkNotNull(
ruleContext.getPrerequisite(protoToolchainAttr, TARGET, ProtoLangToolchainProvider.class));
}
/**
* Returns the toolchain that specifies how to generate Java-lite code from {@code .proto} files.
*/
static ProtoLangToolchainProvider getLiteProtoToolchainProvider(RuleContext ruleContext) {
return ruleContext.getPrerequisite(
LITE_PROTO_TOOLCHAIN_ATTR, TARGET, ProtoLangToolchainProvider.class);
}
/**
* Returns an {@link Artifact} corresponding to a source jar. Its name is computed from the label
* name and the library type of the current instance. For example, if the instance is created with
* {@link getLiteInstance} the name of the jar will be "<label>-lite-src.jar".
*
* <p>The {@link Artifact} will be created in the bazel-genfiles directory.
*/
public Artifact getSourceJarArtifact() {
return ruleContext.getGenfilesArtifact(
ruleContext.getLabel().getName() + jarSuffix + "-src.jar");
}
/**
* Returns an {@link Artifact} corresponding to an output jar. Its name is computed from the label
* name and the library type of the current instance. For example, if the instance is created with
* {@link getLiteInstance} the name of the jar will be "lib<label>-lite.jar".
*
* <p>The {@link Artifact} will be created in the bazel-bin directory.
*/
public Artifact getOutputJarArtifact() {
return ruleContext.getBinArtifact(
"lib" + ruleContext.getLabel().getName() + jarSuffix + ".jar");
}
}