diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java | 651 |
1 files changed, 651 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java new file mode 100644 index 0000000000..c55a74e0bb --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCommon.java @@ -0,0 +1,651 @@ +// 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.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; +import com.google.devtools.build.lib.Constants; +import com.google.devtools.build.lib.actions.Action; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.AnalysisEnvironment; +import com.google.devtools.build.lib.analysis.AnalysisUtils; +import com.google.devtools.build.lib.analysis.FileProvider; +import com.google.devtools.build.lib.analysis.FilesToCompileProvider; +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.TransitiveInfoCollection; +import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; +import com.google.devtools.build.lib.analysis.Util; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; +import com.google.devtools.build.lib.packages.TargetUtils; +import com.google.devtools.build.lib.packages.Type; +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.DirectDependencyProvider.Dependency; +import com.google.devtools.build.lib.rules.java.JavaCompilationArgs.ClasspathType; +import com.google.devtools.build.lib.rules.test.BaselineCoverageAction; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector.LocalMetadataCollector; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesProviderImpl; +import com.google.devtools.build.lib.syntax.Label; +import com.google.devtools.build.lib.util.FileType; +import com.google.devtools.build.lib.vfs.FileSystemUtils; +import com.google.devtools.build.lib.vfs.PathFragment; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import javax.annotation.Nullable; + +/** + * A helper class to create configured targets for Java rules. + */ +public class JavaCommon { + private static final Function<TransitiveInfoCollection, Label> GET_COLLECTION_LABEL = + new Function<TransitiveInfoCollection, Label>() { + @Override + public Label apply(TransitiveInfoCollection collection) { + return collection.getLabel(); + } + }; + + /** + * Collects all metadata files generated by Java compilation actions. + */ + private static final LocalMetadataCollector JAVA_METADATA_COLLECTOR = + new LocalMetadataCollector() { + @Override + public void collectMetadataArtifacts(Iterable<Artifact> objectFiles, + AnalysisEnvironment analysisEnvironment, NestedSetBuilder<Artifact> metadataFilesBuilder) { + for (Artifact artifact : objectFiles) { + Action action = analysisEnvironment.getLocalGeneratingAction(artifact); + if (action instanceof JavaCompileAction) { + addOutputs(metadataFilesBuilder, action, JavaSemantics.COVERAGE_METADATA); + } + } + } + }; + + private ClasspathConfiguredFragment classpathFragment = new ClasspathConfiguredFragment(); + private JavaCompilationArtifacts javaArtifacts = JavaCompilationArtifacts.EMPTY; + private ImmutableList<String> javacOpts; + + // Targets treated as deps in compilation time, runtime time and both + private final ImmutableMap<ClasspathType, ImmutableList<TransitiveInfoCollection>> + targetsTreatedAsDeps; + + private ImmutableList<Artifact> sources = ImmutableList.of(); + private ImmutableList<JavaPluginInfoProvider> activePlugins = ImmutableList.of(); + + private final RuleContext ruleContext; + private final JavaSemantics semantics; + + public JavaCommon(RuleContext ruleContext, JavaSemantics semantics) { + this(ruleContext, semantics, + collectTargetsTreatedAsDeps(ruleContext, semantics, ClasspathType.COMPILE_ONLY), + collectTargetsTreatedAsDeps(ruleContext, semantics, ClasspathType.RUNTIME_ONLY), + collectTargetsTreatedAsDeps(ruleContext, semantics, ClasspathType.BOTH)); + } + + public JavaCommon(RuleContext ruleContext, + JavaSemantics semantics, + ImmutableList<TransitiveInfoCollection> compileDeps, + ImmutableList<TransitiveInfoCollection> runtimeDeps, + ImmutableList<TransitiveInfoCollection> bothDeps) { + this.ruleContext = ruleContext; + this.semantics = semantics; + this.targetsTreatedAsDeps = ImmutableMap.of( + ClasspathType.COMPILE_ONLY, compileDeps, + ClasspathType.RUNTIME_ONLY, runtimeDeps, + ClasspathType.BOTH, bothDeps); + } + + public void setClassPathFragment(ClasspathConfiguredFragment classpathFragment) { + this.classpathFragment = classpathFragment; + } + + public void setJavaCompilationArtifacts(JavaCompilationArtifacts javaArtifacts) { + this.javaArtifacts = javaArtifacts; + } + + public JavaCompilationArtifacts getJavaCompilationArtifacts() { + return javaArtifacts; + } + + public ImmutableList<Artifact> getProcessorClasspathJars() { + Set<Artifact> processorClasspath = new LinkedHashSet<>(); + for (JavaPluginInfoProvider plugin : activePlugins) { + for (Artifact classpathJar : plugin.getProcessorClasspath()) { + processorClasspath.add(classpathJar); + } + } + return ImmutableList.copyOf(processorClasspath); + } + + public ImmutableList<String> getProcessorClassNames() { + Set<String> processorNames = new LinkedHashSet<>(); + for (JavaPluginInfoProvider plugin : activePlugins) { + processorNames.addAll(plugin.getProcessorClasses()); + } + return ImmutableList.copyOf(processorNames); + } + + /** + * Creates the java.library.path from a list of the native libraries. + * Concatenates the parent directories of the shared libraries into a Java + * search path. Each relative path entry is prepended with "${JAVA_RUNFILES}/" + * so it can be resolved at runtime. + * + * @param sharedLibraries a collection of native libraries to create the java + * library path from + * @return a String containing the ":" separated java library path + */ + public static String javaLibraryPath(Collection<Artifact> sharedLibraries) { + StringBuilder buffer = new StringBuilder(); + Set<PathFragment> entries = new HashSet<>(); + for (Artifact sharedLibrary : sharedLibraries) { + PathFragment entry = sharedLibrary.getRootRelativePath().getParentDirectory(); + if (entries.add(entry)) { + if (buffer.length() > 0) { + buffer.append(':'); + } + buffer.append("${JAVA_RUNFILES}/" + Constants.RUNFILES_PREFIX + "/"); + buffer.append(entry.getPathString()); + } + } + return buffer.toString(); + } + + /** + * Collects Java compilation arguments for this target. + * + * @param recursive Whether to scan dependencies recursively. + * @param isNeverLink Whether the target has the 'neverlink' attr. + */ + JavaCompilationArgs collectJavaCompilationArgs(boolean recursive, boolean isNeverLink, + Iterable<SourcesJavaCompilationArgsProvider> compilationArgsFromSources) { + ClasspathType type = isNeverLink ? ClasspathType.COMPILE_ONLY : ClasspathType.BOTH; + JavaCompilationArgs.Builder builder = JavaCompilationArgs.builder() + .merge(getJavaCompilationArtifacts(), isNeverLink) + .addTransitiveTargets(getExports(ruleContext), recursive, type); + if (recursive) { + builder + .addTransitiveTargets(targetsTreatedAsDeps(ClasspathType.COMPILE_ONLY), recursive, type) + .addTransitiveTargets(getRuntimeDeps(ruleContext), recursive, ClasspathType.RUNTIME_ONLY) + .addSourcesTransitiveCompilationArgs(compilationArgsFromSources, recursive, type); + } + return builder.build(); + } + + /** + * Collects Java dependency artifacts for this target. + * + * @param outDeps output (compile-time) dependency artifact of this target + */ + NestedSet<Artifact> collectCompileTimeDependencyArtifacts(Artifact outDeps) { + NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder(); + if (outDeps != null) { + builder.add(outDeps); + } + + for (JavaCompilationArgsProvider provider : AnalysisUtils.getProviders( + getExports(ruleContext), JavaCompilationArgsProvider.class)) { + builder.addTransitive(provider.getCompileTimeJavaDependencyArtifacts()); + } + return builder.build(); + } + + public static List<TransitiveInfoCollection> getExports(RuleContext ruleContext) { + // We need to check here because there are classes inheriting from this class that implement + // rules that don't have this attribute. + if (ruleContext.getRule().getRuleClassObject().hasAttr("exports", Type.LABEL_LIST)) { + return ImmutableList.copyOf(ruleContext.getPrerequisites("exports", Mode.TARGET)); + } else { + return ImmutableList.of(); + } + } + + /** + * Sanity checks the given runtime dependencies, and emits errors if there is a problem. + * Also called by {@link #initCommon()} for the current target's runtime dependencies. + */ + public void checkRuntimeDeps(List<TransitiveInfoCollection> runtimeDepInfo) { + for (TransitiveInfoCollection c : runtimeDepInfo) { + JavaNeverlinkInfoProvider neverLinkedness = + c.getProvider(JavaNeverlinkInfoProvider.class); + if (neverLinkedness == null) { + continue; + } + boolean reportError = !ruleContext.getConfiguration().getAllowRuntimeDepsOnNeverLink(); + if (neverLinkedness.isNeverlink()) { + String msg = String.format("neverlink dep %s not allowed in runtime deps", c.getLabel()); + if (reportError) { + ruleContext.attributeError("runtime_deps", msg); + } else { + ruleContext.attributeWarning("runtime_deps", msg); + } + } + } + } + + /** + * Returns transitive Java native libraries. + * + * @see JavaNativeLibraryProvider + */ + protected NestedSet<LinkerInput> collectTransitiveJavaNativeLibraries() { + NativeLibraryNestedSetBuilder builder = new NativeLibraryNestedSetBuilder(); + builder.addJavaTargets(targetsTreatedAsDeps(ClasspathType.BOTH)); + + if (ruleContext.getRule().isAttrDefined("data", Type.LABEL_LIST)) { + builder.addJavaTargets(ruleContext.getPrerequisites("data", Mode.DATA)); + } + return builder.build(); + } + + /** + * Collects transitive source jars for the current rule. + * + * @param targetSrcJar The source jar artifact corresponding to the output of the current rule. + * @return A nested set containing all of the source jar artifacts on which the current rule + * transitively depends. + */ + public NestedSet<Artifact> collectTransitiveSourceJars(Artifact targetSrcJar) { + NestedSetBuilder<Artifact> builder = NestedSetBuilder.stableOrder(); + + builder.add(targetSrcJar); + for (JavaSourceJarsProvider dep : getDependencies(JavaSourceJarsProvider.class)) { + builder.addTransitive(dep.getTransitiveSourceJars()); + } + return builder.build(); + } + + /** + * Collects transitive C++ dependencies. + */ + protected CppCompilationContext collectTransitiveCppDeps() { + CppCompilationContext.Builder builder = new CppCompilationContext.Builder(ruleContext); + for (TransitiveInfoCollection dep : targetsTreatedAsDeps(ClasspathType.BOTH)) { + CppCompilationContext context = + dep.getProvider(CppCompilationContext.class); + if (context != null) { + builder.mergeDependentContext(context); + } + } + return builder.build(); + } + + /** + * Collects labels of targets and artifacts reached transitively via the "exports" attribute. + */ + protected NestedSet<Label> collectTransitiveExports() { + NestedSetBuilder<Label> builder = NestedSetBuilder.stableOrder(); + List<TransitiveInfoCollection> currentRuleExports = getExports(ruleContext); + + builder.addAll(Iterables.transform(currentRuleExports, GET_COLLECTION_LABEL)); + + for (TransitiveInfoCollection dep : currentRuleExports) { + JavaExportsProvider exportsProvider = dep.getProvider(JavaExportsProvider.class); + + if (exportsProvider != null) { + builder.addTransitive(exportsProvider.getTransitiveExports()); + } + } + + return builder.build(); + } + + public final void initializeJavacOpts() { + initializeJavacOpts(semantics.getExtraJavacOpts(ruleContext)); + } + + public final void initializeJavacOpts(Iterable<String> extraJavacOpts) { + javacOpts = ImmutableList.copyOf(Iterables.concat( + JavaToolchainProvider.getDefaultJavacOptions(ruleContext), + ruleContext.getTokenizedStringListAttr("javacopts"), extraJavacOpts)); + } + + /** + * Returns the string that the stub should use to determine the JVM + * @param launcher if non-null, the cc_binary used to launch the Java Virtual Machine + */ + public String getJavaBinSubstitution(@Nullable Artifact launcher) { + PathFragment javaExecutable; + + if (launcher != null) { + javaExecutable = launcher.getRootRelativePath(); + } else { + javaExecutable = ruleContext.getFragment(Jvm.class).getJavaExecutable(); + } + + String pathPrefix = + javaExecutable.isAbsolute() ? "" : "${JAVA_RUNFILES}/" + Constants.RUNFILES_PREFIX + "/"; + return "JAVABIN=${JAVABIN:-" + pathPrefix + javaExecutable.getPathString() + "}"; + } + + /** + * Heuristically determines the name of the primary Java class for this + * executable, based on the rule name and the "srcs" list. + * + * <p>(This is expected to be the class containing the "main" method for a + * java_binary, or a JUnit Test class for a java_test.) + * + * @param sourceFiles the source files for this rule + * @return a fully qualified Java class name, or null if none could be + * determined. + */ + public String determinePrimaryClass(Collection<Artifact> sourceFiles) { + if (!sourceFiles.isEmpty()) { + String mainSource = ruleContext.getTarget().getName() + ".java"; + for (Artifact sourceFile : sourceFiles) { + PathFragment path = sourceFile.getRootRelativePath(); + if (path.getBaseName().equals(mainSource)) { + return JavaUtil.getJavaFullClassname(FileSystemUtils.removeExtension(path)); + } + } + } + // Last resort: Use the name and package name of the target. + // TODO(bazel-team): this should be fixed to use a source file from the dependencies to + // determine the package of the Java class. + return JavaUtil.getJavaFullClassname(Util.getWorkspaceRelativePath(ruleContext.getTarget())); + } + + /** + * Gets the value of the "jvm_flags" attribute combining it with the default + * options and expanding any make variables. + */ + public List<String> getJvmFlags() { + List<String> jvmFlags = new ArrayList<>(); + jvmFlags.addAll(ruleContext.getFragment(JavaConfiguration.class).getDefaultJvmFlags()); + jvmFlags.addAll(ruleContext.expandedMakeVariablesList("jvm_flags")); + return jvmFlags; + } + + private static List<TransitiveInfoCollection> getRuntimeDeps(RuleContext ruleContext) { + // We need to check here because there are classes inheriting from this class that implement + // rules that don't have this attribute. + if (ruleContext.getRule().getRuleClassObject().hasAttr("runtime_deps", Type.LABEL_LIST)) { + return ImmutableList.copyOf(ruleContext.getPrerequisites("runtime_deps", Mode.TARGET)); + } else { + return ImmutableList.of(); + } + } + + public JavaTargetAttributes.Builder initCommon() { + return initCommon(Collections.<Artifact>emptySet()); + } + + /** + * Initialize the common actions and build various collections of artifacts + * for the initializationHook() methods of the subclasses. + * + * <p>Note that not all subclasses call this method. + * + * @return the processed attributes + */ + public JavaTargetAttributes.Builder initCommon(Collection<Artifact> extraSrcs) { + Preconditions.checkState(javacOpts != null); + sources = ruleContext.getPrerequisiteArtifacts("srcs", Mode.TARGET).list(); + activePlugins = collectPlugins(); + + JavaTargetAttributes.Builder javaTargetAttributes = new JavaTargetAttributes.Builder(semantics); + processSrcs(javaTargetAttributes, javacOpts); + javaTargetAttributes.addSourceArtifacts(extraSrcs); + processRuntimeDeps(javaTargetAttributes); + + semantics.commonDependencyProcessing(ruleContext, javaTargetAttributes, + targetsTreatedAsDeps(ClasspathType.COMPILE_ONLY)); + + // Check that we have do not have both sources and jars. + if ((javaTargetAttributes.hasSourceFiles() || javaTargetAttributes.hasSourceJars()) + && javaTargetAttributes.hasJarFiles()) { + ruleContext.attributeWarning("srcs", "cannot use both Java sources - source " + + "jars or source files - and precompiled jars"); + } + + if (disallowDepsWithoutSrcs(ruleContext.getRule().getRuleClass()) + && ruleContext.attributes().get("srcs", Type.LABEL_LIST).isEmpty() + && ruleContext.getRule().isAttributeValueExplicitlySpecified("deps")) { + ruleContext.attributeError("deps", "deps not allowed without srcs; move to runtime_deps?"); + } + + javaTargetAttributes.addResources(semantics.collectResources(ruleContext)); + addPlugins(javaTargetAttributes); + + javaTargetAttributes.setRuleKind(ruleContext.getRule().getRuleClass()); + javaTargetAttributes.setTargetLabel(ruleContext.getLabel()); + + return javaTargetAttributes; + } + + private boolean disallowDepsWithoutSrcs(String ruleClass) { + return ruleClass.equals("java_library") + || ruleClass.equals("java_binary") + || ruleClass.equals("java_test"); + } + + public ImmutableList<? extends TransitiveInfoCollection> targetsTreatedAsDeps( + ClasspathType type) { + return targetsTreatedAsDeps.get(type); + } + + private static ImmutableList<TransitiveInfoCollection> collectTargetsTreatedAsDeps( + RuleContext ruleContext, JavaSemantics semantics, ClasspathType type) { + ImmutableList.Builder<TransitiveInfoCollection> builder = new Builder<>(); + + if (!type.equals(ClasspathType.COMPILE_ONLY)) { + builder.addAll(getRuntimeDeps(ruleContext)); + builder.addAll(getExports(ruleContext)); + } + builder.addAll(ruleContext.getPrerequisites("deps", Mode.TARGET)); + + semantics.collectTargetsTreatedAsDeps(ruleContext, builder); + + // Implicitly add dependency on java launcher cc_binary when --java_launcher= is enabled, + // or when launcher attribute is specified in a build rule. + TransitiveInfoCollection launcher = JavaHelper.launcherForTarget(semantics, ruleContext); + if (launcher != null) { + builder.add(launcher); + } + + return builder.build(); + } + + public void addTransitiveInfoProviders(RuleConfiguredTargetBuilder builder, + NestedSet<Artifact> filesToBuild, @Nullable Artifact classJar) { + InstrumentedFilesCollector instrumentedFilesCollector = + new InstrumentedFilesCollector(ruleContext, semantics.getCoverageInstrumentationSpec(), + JAVA_METADATA_COLLECTOR, filesToBuild); + + builder + .add(InstrumentedFilesProvider.class, new InstrumentedFilesProviderImpl( + instrumentedFilesCollector)) + .add(FilesToCompileProvider.class, + new FilesToCompileProvider(getFilesToCompile(classJar))) + .add(JavaExportsProvider.class, new JavaExportsProvider(collectTransitiveExports())); + + if (!TargetUtils.isTestRule(ruleContext.getTarget())) { + ImmutableList<Artifact> baselineCoverageArtifacts = + BaselineCoverageAction.getBaselineCoverageArtifacts(ruleContext, + instrumentedFilesCollector.getInstrumentedFiles()); + builder.setBaselineCoverageArtifacts(baselineCoverageArtifacts); + } + } + + /** + * Processes the sources of this target, adding them as messages, proper + * sources or to the list of targets treated as deps as required. + */ + private void processSrcs(JavaTargetAttributes.Builder attributes, + ImmutableList<String> javacOpts) { + for (MessageBundleProvider srcItem : ruleContext.getPrerequisites( + "srcs", Mode.TARGET, MessageBundleProvider.class)) { + attributes.addMessages(srcItem.getMessages()); + } + + attributes.addSourceArtifacts(sources); + + addCompileTimeClassPathEntriesMaybeThroughIjar(attributes, javacOpts); + } + + /** + * Processes the transitive runtime_deps of this target. + */ + private void processRuntimeDeps(JavaTargetAttributes.Builder attributes) { + List<TransitiveInfoCollection> runtimeDepInfo = getRuntimeDeps(ruleContext); + checkRuntimeDeps(runtimeDepInfo); + JavaCompilationArgs args = JavaCompilationArgs.builder() + .addTransitiveTargets(runtimeDepInfo, true, ClasspathType.RUNTIME_ONLY) + .build(); + attributes.addRuntimeClassPathEntries(args.getRuntimeJars()); + attributes.addInstrumentationMetadataEntries(args.getInstrumentationMetadata()); + } + + public Iterable<SourcesJavaCompilationArgsProvider> compilationArgsFromSources() { + return ruleContext.getPrerequisites("srcs", Mode.TARGET, + SourcesJavaCompilationArgsProvider.class); + } + + /** + * Adds jars in the given group of entries to the compile time classpath after + * using ijar to create jar interfaces for the generated jars. + */ + private void addCompileTimeClassPathEntriesMaybeThroughIjar( + JavaTargetAttributes.Builder attributes, ImmutableList<String> javacOpts) { + JavaCompilationHelper helper = new JavaCompilationHelper( + ruleContext, semantics, javacOpts, attributes); + for (FileProvider provider : ruleContext + .getPrerequisites("srcs", Mode.TARGET, FileProvider.class)) { + Iterable<Artifact> jarFiles = helper.filterGeneratedJarsThroughIjar( + FileType.filter(provider.getFilesToBuild(), JavaSemantics.JAR)); + List<Artifact> jarsWithOwners = Lists.newArrayList(jarFiles); + attributes.addDirectCompileTimeClassPathEntries(jarsWithOwners); + attributes.addCompileTimeJarFiles(jarsWithOwners); + } + } + + /** + * Adds information about the annotation processors that should be run for this java target to + * the target attributes. + */ + private void addPlugins(JavaTargetAttributes.Builder attributes) { + for (JavaPluginInfoProvider plugin : activePlugins) { + for (String name : plugin.getProcessorClasses()) { + attributes.addProcessorName(name); + } + // Now get the plugin-libraries runtime classpath. + attributes.addProcessorPath(plugin.getProcessorClasspath()); + } + } + + private ImmutableList<JavaPluginInfoProvider> collectPlugins() { + List<JavaPluginInfoProvider> result = new ArrayList<>(); + Iterables.addAll(result, getPluginInfoProvidersForAttribute(":java_plugins", Mode.HOST)); + Iterables.addAll(result, getPluginInfoProvidersForAttribute("plugins", Mode.HOST)); + Iterables.addAll(result, getPluginInfoProvidersForAttribute("deps", Mode.TARGET)); + return ImmutableList.copyOf(result); + } + + Iterable<JavaPluginInfoProvider> getPluginInfoProvidersForAttribute(String attribute, + Mode mode) { + if (ruleContext.getRule().getRuleClassObject().hasAttr(attribute, Type.LABEL_LIST)) { + return ruleContext.getPrerequisites(attribute, mode, JavaPluginInfoProvider.class); + } + return ImmutableList.of(); + } + + /** + * Gets all the deps. + */ + public final Iterable<? extends TransitiveInfoCollection> getDependencies() { + return targetsTreatedAsDeps(ClasspathType.BOTH); + } + + /** + * Gets all the deps that implement a particular provider. + */ + public final <P extends TransitiveInfoProvider> Iterable<P> getDependencies( + Class<P> provider) { + return AnalysisUtils.getProviders(getDependencies(), provider); + } + + /** + * Returns true if and only if this target has the neverlink attribute set to + * 1, or false if the neverlink attribute does not exist (for example, on + * *_binary targets) + * + * @return the value of the neverlink attribute. + */ + public final boolean isNeverLink() { + return ruleContext.getRule().isAttrDefined("neverlink", Type.BOOLEAN) && + ruleContext.attributes().get("neverlink", Type.BOOLEAN); + } + + private ImmutableList<Artifact> getFilesToCompile(Artifact classJar) { + if (classJar == null) { + // Some subclasses don't produce jars + return ImmutableList.of(); + } + return ImmutableList.of(classJar); + } + + public ImmutableList<Dependency> computeStrictDepsFromJavaAttributes( + JavaTargetAttributes javaTargetAttributes) { + Multimap<Label, String> depMap = HashMultimap.<Label, String>create(); + for (Artifact jar : javaTargetAttributes.getDirectJars()) { + depMap.put(Preconditions.checkNotNull(jar.getOwner()), + jar.getExecPathString()); + } + ImmutableList.Builder<Dependency> depOuts = ImmutableList.builder(); + for (Label label : depMap.keySet()) { + depOuts.add(new Dependency(label, depMap.get(label))); + } + return depOuts.build(); + } + + public ImmutableList<Artifact> getSrcsArtifacts() { + return sources; + } + + public ImmutableList<String> getJavacOpts() { + return javacOpts; + } + + public ImmutableList<Artifact> getBootClasspath() { + return classpathFragment.getBootClasspath(); + } + + public NestedSet<Artifact> getRuntimeClasspath() { + return classpathFragment.getRuntimeClasspath(); + } + + public NestedSet<Artifact> getCompileTimeClasspath() { + return classpathFragment.getCompileTimeClasspath(); + } +} |