diff options
Diffstat (limited to 'src/main')
8 files changed, 576 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD index a82f8d867e..1c93dce455 100644 --- a/src/main/java/com/google/devtools/build/lib/BUILD +++ b/src/main/java/com/google/devtools/build/lib/BUILD @@ -741,6 +741,8 @@ java_library( "rules/java/ProguardLibraryRule.java", "rules/java/ProguardSpecProvider.java", "rules/java/proto/JavaCompilationArgsAspectProvider.java", + "rules/java/proto/JavaLiteProtoAspect.java", + "rules/java/proto/JavaLiteProtoLibrary.java", "rules/java/proto/JavaProtoAspect.java", "rules/java/proto/JavaProtoLibrary.java", "rules/java/proto/JavaProtoLibraryTransitiveFilesToBuildProvider.java", 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 403acc7f8e..3a48369cb8 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 @@ -48,6 +48,8 @@ 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.BazelJavaTestRule; +import com.google.devtools.build.lib.bazel.rules.java.proto.BazelJavaLiteProtoAspect; +import com.google.devtools.build.lib.bazel.rules.java.proto.BazelJavaLiteProtoLibraryRule; import com.google.devtools.build.lib.bazel.rules.java.proto.BazelJavaProtoAspect; import com.google.devtools.build.lib.bazel.rules.java.proto.BazelJavaProtoLibraryRule; import com.google.devtools.build.lib.bazel.rules.objc.BazelJ2ObjcLibraryRule; @@ -396,12 +398,14 @@ public class BazelRuleClassProvider { new AndroidStudioInfoAspect(toolsRepository, new BazelAndroidStudioInfoSemantics()); ObjcProtoAspect objcProtoAspect = new ObjcProtoAspect(); BazelJavaProtoAspect bazelJavaProtoAspect = new BazelJavaProtoAspect(); + BazelJavaLiteProtoAspect bazelJavaLiteProtoAspect = new BazelJavaLiteProtoAspect(); builder.addNativeAspectClass(bazelJ2ObjcProtoAspect); builder.addNativeAspectClass(j2ObjcAspect); builder.addNativeAspectClass(androidStudioInfoAspect); builder.addNativeAspectClass(objcProtoAspect); builder.addNativeAspectClass(bazelJavaProtoAspect); + builder.addNativeAspectClass(bazelJavaLiteProtoAspect); builder.addRuleDefinition(new BazelShRuleClasses.ShRule()); builder.addRuleDefinition(new BazelShLibraryRule()); @@ -479,6 +483,7 @@ public class BazelRuleClassProvider { builder.addRuleDefinition(new AndroidSdkRepositoryRule()); builder.addRuleDefinition(new AndroidNdkRepositoryRule()); builder.addRuleDefinition(new BazelJavaProtoLibraryRule(bazelJavaProtoAspect)); + builder.addRuleDefinition(new BazelJavaLiteProtoLibraryRule(bazelJavaLiteProtoAspect)); builder.addConfigurationFragment(new PythonConfigurationLoader(Functions.<String>identity())); builder.addConfigurationFragment(new BazelPythonConfiguration.Loader()); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java index e3d59df802..1cd8dc97d9 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/BazelJavaRuleClasses.java @@ -126,6 +126,7 @@ public class BazelJavaRuleClasses { "java_import", "java_library", "java_proto_library", + "java_lite_proto_library", "proto_library", "sh_binary", "sh_library"); diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoAspect.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoAspect.java new file mode 100644 index 0000000000..13a456e9fa --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoAspect.java @@ -0,0 +1,32 @@ +// 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.bazel.rules.java.proto; + +import com.google.devtools.build.lib.bazel.rules.java.BazelJavaSemantics; +import com.google.devtools.build.lib.rules.java.proto.JavaLiteProtoAspect; + +/** An Aspect which BazelJavaLiteProtoLibrary injects to build Java Lite protos. */ +public class BazelJavaLiteProtoAspect extends JavaLiteProtoAspect { + static final String LITE_PROTO_RUNTIME_ATTR = "$aspect_java_lib"; + static final String LITE_PROTO_RUNTIME_LABEL = "//third_party/protobuf:protobuf"; + + public BazelJavaLiteProtoAspect() { + super( + BazelJavaSemantics.INSTANCE, + LITE_PROTO_RUNTIME_ATTR, + LITE_PROTO_RUNTIME_LABEL, + null /* jacocoLabel */); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoLibrary.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoLibrary.java new file mode 100644 index 0000000000..879bfc0e0b --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoLibrary.java @@ -0,0 +1,24 @@ +// 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.bazel.rules.java.proto; + +import com.google.devtools.build.lib.rules.java.proto.JavaLiteProtoLibrary; + +/** Implementation of the java_lite_proto_library rule. */ +public class BazelJavaLiteProtoLibrary extends JavaLiteProtoLibrary { + public BazelJavaLiteProtoLibrary() { + super(BazelJavaLiteProtoAspect.LITE_PROTO_RUNTIME_ATTR); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoLibraryRule.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoLibraryRule.java new file mode 100644 index 0000000000..b92aced757 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/java/proto/BazelJavaLiteProtoLibraryRule.java @@ -0,0 +1,125 @@ +// 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.bazel.rules.java.proto; + +import static com.google.devtools.build.lib.bazel.rules.java.proto.BazelJavaLiteProtoAspect.LITE_PROTO_RUNTIME_ATTR; +import static com.google.devtools.build.lib.bazel.rules.java.proto.BazelJavaLiteProtoAspect.LITE_PROTO_RUNTIME_LABEL; +import static com.google.devtools.build.lib.packages.Aspect.INJECTING_RULE_KIND_PARAMETER_KEY; +import static com.google.devtools.build.lib.packages.Attribute.attr; +import static com.google.devtools.build.lib.packages.BuildType.LABEL; +import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; +import static com.google.devtools.build.lib.syntax.Type.BOOLEAN; + +import com.google.common.base.Function; +import com.google.devtools.build.lib.analysis.BaseRuleClasses; +import com.google.devtools.build.lib.analysis.RuleDefinition; +import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; +import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.packages.AspectParameters; +import com.google.devtools.build.lib.packages.Rule; +import com.google.devtools.build.lib.packages.RuleClass; +import com.google.devtools.build.lib.rules.java.JavaConfiguration; +import javax.annotation.Nullable; + +/** Declaration of the {@code java_lite_proto_library} rule. */ +public class BazelJavaLiteProtoLibraryRule implements RuleDefinition { + + private static final Function<Rule, AspectParameters> ASPECT_PARAMETERS = + new Function<Rule, AspectParameters>() { + @Nullable + @Override + public AspectParameters apply(@Nullable Rule rule) { + return new AspectParameters.Builder() + .addAttribute(INJECTING_RULE_KIND_PARAMETER_KEY, "java_lite_proto_library") + .build(); + } + }; + + private final BazelJavaLiteProtoAspect javaProtoAspect; + + public BazelJavaLiteProtoLibraryRule(BazelJavaLiteProtoAspect javaProtoAspect) { + this.javaProtoAspect = javaProtoAspect; + } + + @Override + public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment environment) { + return builder + // This rule isn't ready for use yet. + .setUndocumented() + .requiresConfigurationFragments(JavaConfiguration.class) + /* <!-- #BLAZE_RULE(java_lite_proto_library).ATTRIBUTE(deps) --> + The list of <a href="protocol-buffer.html#proto_library"><code>proto_library</code></a> + rules to generate Java code for. + <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ + .override( + attr("deps", LABEL_LIST) + .allowedRuleClasses("proto_library") + .allowedFileTypes() + .aspect(javaProtoAspect, ASPECT_PARAMETERS)) + /* <!-- #BLAZE_RULE(java_lite_proto_library).ATTRIBUTE(deps) --> + When True, this rule only exposes the protos that it wraps directly. Depending on indirect + protos will break the build and print an 'add_dep' command to correct the build. + <!-- #END_BLAZE_RULE.ATTRIBUTE --> */ + .add(attr("strict_deps", BOOLEAN)) + .add( + attr(LITE_PROTO_RUNTIME_ATTR, LABEL) + .legacyAllowAnyFileType() + .value(Label.parseAbsoluteUnchecked(LITE_PROTO_RUNTIME_LABEL))) + .build(); + } + + @Override + public Metadata getMetadata() { + return RuleDefinition.Metadata.builder() + .name("java_lite_proto_library") + .factoryClass(BazelJavaLiteProtoLibrary.class) + .ancestors(BaseRuleClasses.RuleBase.class) + .build(); + } +} + +/*<!-- #BLAZE_RULE (NAME = java_lite_proto_library, TYPE = LIBRARY, FAMILY = Java) --> + +<p> +<code>java_lite_proto_library</code> generates Java code from <code>.proto</code> files. +</p> + +<p> +<code>deps</code> must point to <a href="protocol-buffer.html#proto_library"><code>proto_library +</code></a> rules. +</p> + +<p> +Example: +</p> + +<pre class="code"> +java_library( + name = "lib", + deps = [":foo"], +) + +java_lite_proto_library( + name = "foo", + deps = [":bar"], +) + +proto_library( + name = "bar", +) +</pre> + + +<!-- #END_BLAZE_RULE -->*/ diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoAspect.java b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoAspect.java new file mode 100644 index 0000000000..e96a49d3e3 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoAspect.java @@ -0,0 +1,276 @@ +// 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.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.transform; +import static com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode.TARGET; +import static com.google.devtools.build.lib.cmdline.Label.parseAbsoluteUnchecked; +import static com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition.HOST; +import static com.google.devtools.build.lib.packages.Attribute.attr; +import static com.google.devtools.build.lib.packages.BuildType.LABEL; +import static com.google.devtools.build.lib.rules.java.proto.JavaCompilationArgsAspectProvider.GET_PROVIDER; +import static com.google.devtools.build.lib.rules.java.proto.JavaProtoLibraryTransitiveFilesToBuildProvider.GET_JARS; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.ConfiguredAspect; +import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; +import com.google.devtools.build.lib.analysis.config.BuildConfiguration.StrictDepsMode; +import com.google.devtools.build.lib.cmdline.Label; +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.AspectDefinition; +import com.google.devtools.build.lib.packages.AspectParameters; +import com.google.devtools.build.lib.packages.Attribute; +import com.google.devtools.build.lib.packages.NativeAspectClass; +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.JavaConfiguration; +import com.google.devtools.build.lib.rules.java.JavaLibraryHelper; +import com.google.devtools.build.lib.rules.java.JavaRuntimeJarProvider; +import com.google.devtools.build.lib.rules.java.JavaSemantics; +import com.google.devtools.build.lib.rules.java.JavaSourceJarsProvider; +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.ProtoConfiguration; +import com.google.devtools.build.lib.rules.proto.ProtoSourcesProvider; +import com.google.devtools.build.lib.rules.proto.ProtoSupportDataProvider; +import com.google.devtools.build.lib.rules.proto.SupportData; +import java.util.Map; +import javax.annotation.Nullable; + +/** An Aspect which JavaLiteProtoLibrary injects to build Java Lite protos. */ +public class JavaLiteProtoAspect extends NativeAspectClass implements ConfiguredAspectFactory { + + private final JavaSemantics javaSemantics; + private final String protoRuntimeAttr; + private final String protoRuntimeLabel; + + @Nullable private final String jacocoLabel; + + public JavaLiteProtoAspect( + JavaSemantics javaSemantics, + String protoRuntimeAttr, + String protoRuntimeLabel, + @Nullable String jacocoLabel) { + this.javaSemantics = javaSemantics; + this.protoRuntimeAttr = protoRuntimeAttr; + this.protoRuntimeLabel = protoRuntimeLabel; + this.jacocoLabel = jacocoLabel; + } + + @Override + public ConfiguredAspect create( + ConfiguredTarget base, RuleContext ruleContext, AspectParameters parameters) + throws InterruptedException { + ConfiguredAspect.Builder aspect = + new ConfiguredAspect.Builder(getClass().getSimpleName(), ruleContext); + + // Get SupportData, which is provided by the proto_library rule we attach to. + SupportData supportData = + checkNotNull(base.getProvider(ProtoSupportDataProvider.class)).getSupportData(); + + aspect.addProviders( + new Impl(ruleContext, supportData, protoRuntimeAttr, javaSemantics) + .createProviders()); + + return aspect.build(); + } + + @Override + public AspectDefinition getDefinition(AspectParameters aspectParameters) { + AspectDefinition.Builder result = + new AspectDefinition.Builder(getClass().getSimpleName()) + .attributeAspect("deps", this) + .requiresConfigurationFragments(JavaConfiguration.class, ProtoConfiguration.class) + .requireProvider(ProtoSourcesProvider.class) + .add( + attr(protoRuntimeAttr, LABEL) + .legacyAllowAnyFileType() + .value(parseAbsoluteUnchecked(protoRuntimeLabel))) + .add(attr(":host_jdk", LABEL).cfg(HOST).value(JavaSemantics.HOST_JDK)) + .add( + attr(":java_toolchain", LABEL) + .allowedRuleClasses("java_toolchain") + .value(JavaSemantics.JAVA_TOOLCHAIN)); + + Attribute.Builder<Label> jacocoAttr = attr("$jacoco_instrumentation", LABEL).cfg(HOST); + + if (jacocoLabel != null) { + jacocoAttr.value(parseAbsoluteUnchecked(jacocoLabel)); + } + return result.add(jacocoAttr).build(); + } + + private static class Impl { + + private final RuleContext ruleContext; + private final SupportData supportData; + + /** + * A map between the ijar and the jar resulting from compiling the code generated for this + * proto. + */ + private final BiMap<Artifact, Artifact> compileTimeJarToRuntimeJar = HashBiMap.create(); + + /** + * Compilation-args from all dependencies, merged together. This is typically the input to a + * Java compilation action. + */ + private final JavaCompilationArgsProvider dependencyCompilationArgs; + private final String protoRuntimeAttr; + private final JavaSemantics javaSemantics; + + Impl( + final RuleContext ruleContext, + final SupportData supportData, + String protoRuntimeAttr, + JavaSemantics javaSemantics) { + this.ruleContext = ruleContext; + this.supportData = supportData; + this.protoRuntimeAttr = protoRuntimeAttr; + this.javaSemantics = javaSemantics; + + dependencyCompilationArgs = + JavaCompilationArgsProvider.merge( + Iterables.<JavaCompilationArgsAspectProvider, JavaCompilationArgsProvider>transform( + this.<JavaCompilationArgsAspectProvider>getDeps( + JavaCompilationArgsAspectProvider.class), + GET_PROVIDER)); + } + + Map<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> createProviders() { + ImmutableMap.Builder<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> result = + ImmutableMap.builder(); + + // Represents the result of compiling the code generated for this proto, including all of its + // dependencies. + JavaCompilationArgsProvider generatedCompilationArgsProvider; + + // The jars that this proto and its dependencies produce. Used to roll-up jars up to the + // java_proto_library, to be put into filesToBuild. + NestedSetBuilder<Artifact> transitiveOutputJars = + NestedSetBuilder.fromNestedSets( + transform(getDeps(JavaProtoLibraryTransitiveFilesToBuildProvider.class), GET_JARS)); + + if (supportData.hasProtoSources()) { + Artifact sourceJar = getSourceJarArtifact(); + createProtoCompileAction(sourceJar); + Artifact outputJar = getOutputJarArtifact(); + + generatedCompilationArgsProvider = createJavaCompileAction(sourceJar, outputJar); + + NestedSet<Artifact> javaSourceJars = + NestedSetBuilder.<Artifact>stableOrder().add(sourceJar).build(); + transitiveOutputJars.add(outputJar); + + result + .put( + JavaRuntimeJarAspectProvider.class, + new JavaRuntimeJarAspectProvider( + new JavaRuntimeJarProvider(ImmutableList.of(outputJar)))) + .put( + JavaSourceJarsAspectProvider.class, + new JavaSourceJarsAspectProvider( + new JavaSourceJarsProvider( + NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER), javaSourceJars))); + } else { + // No sources - this proto_library is an alias library, which exports its dependencies. + // Simply propagate the compilation-args from its dependencies. + generatedCompilationArgsProvider = dependencyCompilationArgs; + } + + return result + .put( + JavaProtoLibraryTransitiveFilesToBuildProvider.class, + new JavaProtoLibraryTransitiveFilesToBuildProvider(transitiveOutputJars.build())) + .put( + JavaCompilationArgsAspectProvider.class, + new JavaCompilationArgsAspectProvider(generatedCompilationArgsProvider)) + .build(); + } + + private void createProtoCompileAction(Artifact sourceJar) { + ProtoCompileActionBuilder actionBuilder = + new ProtoCompileActionBuilder( + ruleContext, supportData, "Java", "java", ImmutableList.of(sourceJar)) + .allowServices(true) + .setLangParameter( + ProtoCompileActionBuilder.buildProtoArg( + "java_out", + sourceJar.getExecPathString(), + ImmutableList.of("lite", "immutable", "no_enforce_api_compatibility"))); + ruleContext.registerAction(actionBuilder.build()); + } + + private JavaCompilationArgsProvider createJavaCompileAction( + Artifact sourceJar, Artifact outputJar) { + JavaLibraryHelper helper = + new JavaLibraryHelper(ruleContext) + .setOutput(outputJar) + .addSourceJars(sourceJar) + .setJavacOpts(getAndroidCompatibleJavacOpts()); + helper.addDep(dependencyCompilationArgs); + helper + .addDep( + ruleContext.getPrerequisite( + protoRuntimeAttr, Mode.TARGET, JavaCompilationArgsProvider.class)) + .setCompilationStrictDepsMode(StrictDepsMode.OFF); + JavaCompilationArgs artifacts = helper.build(javaSemantics); + compileTimeJarToRuntimeJar.put( + Iterables.getOnlyElement(artifacts.getCompileTimeJars()), + Iterables.getOnlyElement(artifacts.getRuntimeJars())); + return helper.buildCompilationArgsProvider(artifacts, true /* isReportedAsStrict */); + } + + private Artifact getSourceJarArtifact() { + return ruleContext.getGenfilesArtifact(ruleContext.getLabel().getName() + "-lite-src.jar"); + } + + private Artifact getOutputJarArtifact() { + return ruleContext.getBinArtifact("lib" + ruleContext.getLabel().getName() + "-lite.jar"); + } + + /** + * Returns javacopts for compiling the Java source files generated by the proto compiler. + * Ensures that they are compiled so that they can be used by Android targets. + * + * <p>See java_toolchain.compatible_javacopts for the javacopts required for android. + */ + private ImmutableList<String> getAndroidCompatibleJavacOpts() { + JavaToolchainProvider toolchain = JavaToolchainProvider.fromRuleContext(ruleContext); + ImmutableList.Builder<String> listBuilder = ImmutableList.builder(); + listBuilder.addAll(toolchain.getJavacOptions()); + // TODO(b/30890416): Get this from AndroidSemantics.getJavacArguments() + listBuilder.addAll( + toolchain.getCompatibleJavacOptions("android")); + return listBuilder.build(); + } + + private <C extends TransitiveInfoProvider> Iterable<C> getDeps(Class<C> clazz) { + return ruleContext.getPrerequisites("deps", TARGET, clazz); + } + } +} diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoLibrary.java new file mode 100644 index 0000000000..62ae5595d8 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/java/proto/JavaLiteProtoLibrary.java @@ -0,0 +1,111 @@ +// 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.collect.Iterables.transform; +import static com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode.TARGET; +import static com.google.devtools.build.lib.collect.nestedset.Order.STABLE_ORDER; + +import com.google.common.collect.ImmutableMultimap; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.OutputGroupProvider; +import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; +import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder; +import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.Runfiles; +import com.google.devtools.build.lib.analysis.RunfilesProvider; +import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; +import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; +import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; +import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider; +import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider; +import com.google.devtools.build.lib.rules.java.JavaRunfilesProvider; +import com.google.devtools.build.lib.rules.java.JavaRuntimeJarProvider; +import com.google.devtools.build.lib.rules.java.JavaSkylarkApiProvider; +import com.google.devtools.build.lib.rules.java.JavaSourceJarsProvider; +import com.google.devtools.build.lib.rules.java.ProguardLibrary; +import com.google.devtools.build.lib.rules.java.ProguardSpecProvider; + +/** Implementation of the java_lite_proto_library rule. */ +public class JavaLiteProtoLibrary implements RuleConfiguredTargetFactory { + + private final String protoRuntimeAttr; + + public JavaLiteProtoLibrary(String protoRuntimeAttr) { + this.protoRuntimeAttr = protoRuntimeAttr; + } + + @Override + public ConfiguredTarget create(final RuleContext ruleContext) + throws InterruptedException, RuleErrorException { + + JavaCompilationArgsProvider dependencyArgsProviders = + JavaCompilationArgsProvider.merge( + transform( + getDeps(ruleContext, JavaCompilationArgsAspectProvider.class), + JavaCompilationArgsAspectProvider.GET_PROVIDER)); + + if (!StrictDepsUtils.isStrictDepsJavaProtoLibrary(ruleContext)) { + dependencyArgsProviders = StrictDepsUtils.makeNonStrict(dependencyArgsProviders); + } + + Runfiles runfiles = new Runfiles.Builder(ruleContext.getWorkspaceName()).addArtifacts( + dependencyArgsProviders.getRecursiveJavaCompilationArgs().getRuntimeJars()).build(); + + JavaSourceJarsProvider sourceJarsProvider = + JavaSourceJarsProvider.merge( + transform( + getDeps(ruleContext, JavaSourceJarsAspectProvider.class), + JavaSourceJarsAspectProvider.GET_PROVIDER)); + + NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.stableOrder(); + + filesToBuild.addAll(sourceJarsProvider.getSourceJars()); + + for (JavaProtoLibraryTransitiveFilesToBuildProvider provider : ruleContext.getPrerequisites( + "deps", Mode.TARGET, JavaProtoLibraryTransitiveFilesToBuildProvider.class)) { + filesToBuild.addTransitive(provider.getJars()); + } + + return new RuleConfiguredTargetBuilder(ruleContext) + .setFilesToBuild(filesToBuild.build()) + .addProvider(RunfilesProvider.class, RunfilesProvider.withData(Runfiles.EMPTY, runfiles)) + .addOutputGroup( + OutputGroupProvider.DEFAULT, NestedSetBuilder.<Artifact>emptySet(STABLE_ORDER)) + .add( + JavaRuntimeJarProvider.class, + JavaRuntimeJarProvider.merge( + transform( + getDeps(ruleContext, JavaRuntimeJarAspectProvider.class), + JavaRuntimeJarAspectProvider.GET_PROVIDER))) + .add(JavaCompilationArgsProvider.class, dependencyArgsProviders) + .add(JavaSourceJarsProvider.class, sourceJarsProvider) + .add(JavaRunfilesProvider.class, new JavaRunfilesProvider(runfiles)) + .add( + ProguardSpecProvider.class, + new ProguardSpecProvider( + new ProguardLibrary(ruleContext) + .collectProguardSpecs(ImmutableMultimap.of(Mode.TARGET, protoRuntimeAttr)))) + .add(JavaRuleOutputJarsProvider.class, JavaRuleOutputJarsProvider.builder().build()) + .addSkylarkTransitiveInfo(JavaSkylarkApiProvider.NAME, new JavaSkylarkApiProvider()) + .build(); + } + + private <C extends TransitiveInfoProvider> Iterable<C> getDeps( + RuleContext ruleContext, Class<C> clazz) { + return ruleContext.getPrerequisites("deps", TARGET, clazz); + } +} |