aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java244
1 files changed, 244 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java
new file mode 100644
index 0000000000..1831ef02ab
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaLibrary.java
@@ -0,0 +1,244 @@
+// Copyright 2014 Google Inc. 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;
+
+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.ConfiguredTarget;
+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.TopLevelArtifactProvider;
+import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
+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.Type;
+import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
+import com.google.devtools.build.lib.rules.cpp.CcLinkParams;
+import com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider;
+import com.google.devtools.build.lib.rules.cpp.CcLinkParamsStore;
+import com.google.devtools.build.lib.rules.cpp.CppCompilationContext;
+import com.google.devtools.build.lib.rules.cpp.LinkerInput;
+import com.google.devtools.build.lib.rules.java.JavaCompilationArgs.ClasspathType;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Implementation for the java_library rule.
+ */
+public class JavaLibrary implements RuleConfiguredTargetFactory {
+ private final JavaSemantics semantics;
+
+ protected JavaLibrary(JavaSemantics semantics) {
+ this.semantics = semantics;
+ }
+
+ @Override
+ public ConfiguredTarget create(RuleContext ruleContext) {
+ JavaCommon common = new JavaCommon(ruleContext, semantics);
+ RuleConfiguredTargetBuilder builder = init(ruleContext, common);
+ return builder != null ? builder.build() : null;
+ }
+
+ public RuleConfiguredTargetBuilder init(RuleContext ruleContext, final JavaCommon common) {
+ common.initializeJavacOpts();
+ JavaTargetAttributes.Builder attributesBuilder = common.initCommon();
+
+ // Collect the transitive dependencies.
+ JavaCompilationHelper helper = new JavaCompilationHelper(
+ ruleContext, semantics, common.getJavacOpts(), attributesBuilder);
+ helper.addLibrariesToAttributes(common.targetsTreatedAsDeps(ClasspathType.COMPILE_ONLY));
+ helper.addProvidersToAttributes(common.compilationArgsFromSources(), common.isNeverLink());
+
+ if (ruleContext.hasErrors()) {
+ return null;
+ }
+
+ semantics.checkRule(ruleContext, common);
+
+ JavaCompilationArtifacts.Builder javaArtifactsBuilder = new JavaCompilationArtifacts.Builder();
+
+ if (ruleContext.hasErrors()) {
+ common.setJavaCompilationArtifacts(JavaCompilationArtifacts.EMPTY);
+ return null;
+ }
+
+ JavaConfiguration javaConfig = ruleContext.getFragment(JavaConfiguration.class);
+ NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder();
+
+ JavaTargetAttributes attributes = helper.getAttributes();
+ if (attributes.hasJarFiles()) {
+ // This rule is repackaging some source jars as a java library.
+ Set<Artifact> jarFiles = attributes.getJarFiles();
+ javaArtifactsBuilder.addRuntimeJars(jarFiles);
+ javaArtifactsBuilder.addCompileTimeJars(attributes.getCompileTimeJarFiles());
+
+ filesBuilder.addAll(jarFiles);
+ }
+ if (attributes.hasMessages()) {
+ helper.addTranslations(semantics.translate(ruleContext, javaConfig,
+ attributes.getMessages()));
+ }
+
+ ruleContext.checkSrcsSamePackage(true);
+
+ Artifact jar = null;
+
+ Artifact srcJar = ruleContext.getImplicitOutputArtifact(
+ JavaSemantics.JAVA_LIBRARY_SOURCE_JAR);
+
+ Artifact classJar = ruleContext.getImplicitOutputArtifact(
+ JavaSemantics.JAVA_LIBRARY_CLASS_JAR);
+
+ if (attributes.hasSourceFiles() || attributes.hasSourceJars() || attributes.hasResources()
+ || attributes.hasMessages()) {
+ // We only want to add a jar to the classpath of a dependent rule if it has content.
+ javaArtifactsBuilder.addRuntimeJar(classJar);
+ jar = classJar;
+ }
+
+ filesBuilder.add(classJar);
+
+ // The gensrcJar is only created if the target uses annotation processing. Otherwise,
+ // it is null, and the source jar action will not depend on the compile action.
+ Artifact gensrcJar = helper.createGensrcJar(classJar);
+
+ Artifact outputDepsProto = helper.createOutputDepsProtoArtifact(classJar, javaArtifactsBuilder);
+
+ helper.createCompileActionWithInstrumentation(classJar, gensrcJar, outputDepsProto,
+ javaArtifactsBuilder);
+ helper.createSourceJarAction(srcJar, gensrcJar);
+
+ if ((attributes.hasSourceFiles() || attributes.hasSourceJars()) && jar != null) {
+ helper.createCompileTimeJarAction(jar, outputDepsProto,
+ javaArtifactsBuilder);
+ }
+
+ common.setJavaCompilationArtifacts(javaArtifactsBuilder.build());
+ common.setClassPathFragment(new ClasspathConfiguredFragment(
+ common.getJavaCompilationArtifacts(), attributes, common.isNeverLink()));
+ CppCompilationContext transitiveCppDeps = common.collectTransitiveCppDeps();
+
+ NestedSet<Artifact> transitiveSourceJars = common.collectTransitiveSourceJars(srcJar);
+
+ // If sources are empty, treat this library as a forwarding node for dependencies.
+ JavaCompilationArgs javaCompilationArgs = common.collectJavaCompilationArgs(
+ false, common.isNeverLink(), common.compilationArgsFromSources());
+ JavaCompilationArgs recursiveJavaCompilationArgs = common.collectJavaCompilationArgs(
+ true, common.isNeverLink(), common.compilationArgsFromSources());
+ NestedSet<Artifact> compileTimeJavaDepArtifacts = common.collectCompileTimeDependencyArtifacts(
+ common.getJavaCompilationArtifacts().getCompileTimeDependencyArtifact());
+ NestedSet<Artifact> runTimeJavaDepArtifacts = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
+ NestedSet<LinkerInput> transitiveJavaNativeLibraries =
+ common.collectTransitiveJavaNativeLibraries();
+
+ ImmutableList<String> exportedProcessorClasses = ImmutableList.of();
+ NestedSet<Artifact> exportedProcessorClasspath =
+ NestedSetBuilder.emptySet(Order.NAIVE_LINK_ORDER);
+ ImmutableList.Builder<String> processorClasses = ImmutableList.builder();
+ NestedSetBuilder<Artifact> processorClasspath = NestedSetBuilder.naiveLinkOrder();
+ for (JavaPluginInfoProvider provider : Iterables.concat(
+ common.getPluginInfoProvidersForAttribute("exported_plugins", Mode.HOST),
+ common.getPluginInfoProvidersForAttribute("exports", Mode.TARGET))) {
+ processorClasses.addAll(provider.getProcessorClasses());
+ processorClasspath.addTransitive(provider.getProcessorClasspath());
+ }
+ exportedProcessorClasses = processorClasses.build();
+ exportedProcessorClasspath = processorClasspath.build();
+
+ CcLinkParamsStore ccLinkParamsStore = new CcLinkParamsStore() {
+ @Override
+ protected void collect(CcLinkParams.Builder builder, boolean linkingStatically,
+ boolean linkShared) {
+ Iterable<? extends TransitiveInfoCollection> deps =
+ common.targetsTreatedAsDeps(ClasspathType.BOTH);
+ builder.addTransitiveTargets(deps);
+ builder.addTransitiveLangTargets(deps, JavaCcLinkParamsProvider.TO_LINK_PARAMS);
+ }
+ };
+
+ // The "neverlink" attribute is transitive, so we don't add any
+ // runfiles from this target or its dependencies.
+ Runfiles runfiles = Runfiles.EMPTY;
+ if (!common.isNeverLink()) {
+ Runfiles.Builder runfilesBuilder = new Runfiles.Builder().addArtifacts(
+ common.getJavaCompilationArtifacts().getRuntimeJars());
+
+
+ runfilesBuilder.addRunfiles(ruleContext, RunfilesProvider.DEFAULT_RUNFILES);
+ runfilesBuilder.add(ruleContext, JavaRunfilesProvider.TO_RUNFILES);
+
+ List<TransitiveInfoCollection> depsForRunfiles = new ArrayList<>();
+ if (ruleContext.getRule().isAttrDefined("runtime_deps", Type.LABEL_LIST)) {
+ depsForRunfiles.addAll(ruleContext.getPrerequisites("runtime_deps", Mode.TARGET));
+ }
+ if (ruleContext.getRule().isAttrDefined("exports", Type.LABEL_LIST)) {
+ depsForRunfiles.addAll(ruleContext.getPrerequisites("exports", Mode.TARGET));
+ }
+
+ runfilesBuilder.addTargets(depsForRunfiles, RunfilesProvider.DEFAULT_RUNFILES);
+ runfilesBuilder.addTargets(depsForRunfiles, JavaRunfilesProvider.TO_RUNFILES);
+
+ TransitiveInfoCollection launcher = JavaHelper.launcherForTarget(semantics, ruleContext);
+ if (launcher != null) {
+ runfilesBuilder.addTarget(launcher, RunfilesProvider.DATA_RUNFILES);
+ }
+
+ semantics.addRunfilesForLibrary(ruleContext, runfilesBuilder);
+ runfiles = runfilesBuilder.build();
+ }
+
+ RuleConfiguredTargetBuilder builder =
+ new RuleConfiguredTargetBuilder(ruleContext);
+
+ semantics.addProviders(
+ ruleContext, common, ImmutableList.<String>of(), classJar, srcJar, gensrcJar,
+ ImmutableMap.<Artifact, Artifact>of(), helper, filesBuilder, builder);
+
+ NestedSet<Artifact> filesToBuild = filesBuilder.build();
+ common.addTransitiveInfoProviders(builder, filesToBuild, classJar);
+
+ builder
+ .add(RunfilesProvider.class, RunfilesProvider.simple(runfiles))
+ .setFilesToBuild(filesToBuild)
+ .add(JavaNeverlinkInfoProvider.class, new JavaNeverlinkInfoProvider(common.isNeverLink()))
+ .add(CppCompilationContext.class, transitiveCppDeps)
+ .add(JavaCompilationArgsProvider.class, new JavaCompilationArgsProvider(
+ javaCompilationArgs, recursiveJavaCompilationArgs,
+ compileTimeJavaDepArtifacts, runTimeJavaDepArtifacts))
+ .add(CcLinkParamsProvider.class, new CcLinkParamsProvider(ccLinkParamsStore))
+ .add(JavaNativeLibraryProvider.class, new JavaNativeLibraryProvider(
+ transitiveJavaNativeLibraries))
+ .add(JavaSourceJarsProvider.class, new JavaSourceJarsProvider(
+ transitiveSourceJars, ImmutableList.of(srcJar)))
+ .add(TopLevelArtifactProvider.class, new TopLevelArtifactProvider(
+ JavaSemantics.SOURCE_JARS_OUTPUT_GROUP, transitiveSourceJars))
+ // TODO(bazel-team): this should only happen for java_plugin
+ .add(JavaPluginInfoProvider.class, new JavaPluginInfoProvider(
+ exportedProcessorClasses, exportedProcessorClasspath));
+
+ if (ruleContext.hasErrors()) {
+ return null;
+ }
+
+ return builder;
+ }
+}