diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java new file mode 100644 index 0000000000..145d6467de --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java @@ -0,0 +1,301 @@ +// 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.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.analysis.FileProvider; +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.util.FileType; + +import java.util.Collection; + +/** + * A container of Java compilation artifacts. + */ +public final class JavaCompilationArgs { + // TODO(bazel-team): It would be desirable to use LinkOrderNestedSet here so that + // parents-before-deps is preserved for graphs that are not trees. However, the legacy + // JavaLibraryCollector implemented naive link ordering and many targets in the + // depot depend on the consistency of left-to-right ordering that is not provided by + // LinkOrderNestedSet. They simply list their local dependencies before + // other targets that may use conflicting dependencies, and the local deps + // appear earlier on the classpath, as desired. Behavior of LinkOrderNestedSet + // can be very unintuitive in case of conflicting orders, because the order is + // decided by the rightmost branch in such cases. For example, if A depends on {junit4, + // B}, B depends on {C, D}, C depends on {junit3}, and D depends on {junit4}, + // the classpath of A will have junit3 before junit4. + private final NestedSet<Artifact> runtimeJars; + private final NestedSet<Artifact> compileTimeJars; + private final NestedSet<Artifact> instrumentationMetadata; + + public static final JavaCompilationArgs EMPTY_ARGS = new JavaCompilationArgs( + NestedSetBuilder.<Artifact>create(Order.NAIVE_LINK_ORDER), + NestedSetBuilder.<Artifact>create(Order.NAIVE_LINK_ORDER), + NestedSetBuilder.<Artifact>create(Order.NAIVE_LINK_ORDER)); + + private JavaCompilationArgs(NestedSet<Artifact> runtimeJars, + NestedSet<Artifact> compileTimeJars, + NestedSet<Artifact> instrumentationMetadata) { + this.runtimeJars = runtimeJars; + this.compileTimeJars = compileTimeJars; + this.instrumentationMetadata = instrumentationMetadata; + } + + /** + * Returns transitive runtime jars. + */ + public NestedSet<Artifact> getRuntimeJars() { + return runtimeJars; + } + + /** + * Returns transitive compile-time jars. + */ + public NestedSet<Artifact> getCompileTimeJars() { + return compileTimeJars; + } + + /** + * Returns transitive instrumentation metadata jars. + */ + public NestedSet<Artifact> getInstrumentationMetadata() { + return instrumentationMetadata; + } + + /** + * Returns a new builder instance. + */ + public static final Builder builder() { + return new Builder(); + } + + /** + * Builder for {@link JavaCompilationArgs}. + * + * + */ + public static final class Builder { + private final NestedSetBuilder<Artifact> runtimeJarsBuilder = + NestedSetBuilder.naiveLinkOrder(); + private final NestedSetBuilder<Artifact> compileTimeJarsBuilder = + NestedSetBuilder.naiveLinkOrder(); + private final NestedSetBuilder<Artifact> instrumentationMetadataBuilder = + NestedSetBuilder.naiveLinkOrder(); + + /** + * Use {@code TransitiveJavaCompilationArgs#builder()} to instantiate the builder. + */ + private Builder() { + } + + /** + * Legacy method for dealing with objects which construct + * {@link JavaCompilationArtifacts} objects. + */ + // TODO(bazel-team): Remove when we get rid of JavaCompilationArtifacts. + public Builder merge(JavaCompilationArtifacts other, boolean isNeverLink) { + if (!isNeverLink) { + addRuntimeJars(other.getRuntimeJars()); + } + addCompileTimeJars(other.getCompileTimeJars()); + addInstrumentationMetadata(other.getInstrumentationMetadata()); + return this; + } + + /** + * Legacy method for dealing with objects which construct + * {@link JavaCompilationArtifacts} objects. + */ + public Builder merge(JavaCompilationArtifacts other) { + return merge(other, false); + } + + public Builder addRuntimeJar(Artifact runtimeJar) { + this.runtimeJarsBuilder.add(runtimeJar); + return this; + } + + public Builder addRuntimeJars(Iterable<Artifact> runtimeJars) { + this.runtimeJarsBuilder.addAll(runtimeJars); + return this; + } + + public Builder addCompileTimeJar(Artifact compileTimeJar) { + this.compileTimeJarsBuilder.add(compileTimeJar); + return this; + } + + public Builder addCompileTimeJars(Iterable<Artifact> compileTimeJars) { + this.compileTimeJarsBuilder.addAll(compileTimeJars); + return this; + } + + public Builder addInstrumentationMetadata(Artifact instrumentationMetadata) { + this.instrumentationMetadataBuilder.add(instrumentationMetadata); + return this; + } + + public Builder addInstrumentationMetadata(Collection<Artifact> instrumentationMetadata) { + this.instrumentationMetadataBuilder.addAll(instrumentationMetadata); + return this; + } + + public Builder addTransitiveCompilationArgs( + JavaCompilationArgsProvider dep, boolean recursive, ClasspathType type) { + JavaCompilationArgs args = recursive + ? dep.getRecursiveJavaCompilationArgs() + : dep.getJavaCompilationArgs(); + addTransitiveArgs(args, type); + return this; + } + + public Builder addTransitiveCompilationArgs( + SourcesJavaCompilationArgsProvider dep, boolean recursive, ClasspathType type) { + JavaCompilationArgs args; + if (recursive) { + args = dep.getRecursiveJavaCompilationArgs(); + } else { + args = dep.getJavaCompilationArgs(); + } + addTransitiveArgs(args, type); + return this; + } + + public Builder addSourcesTransitiveCompilationArgs( + Iterable<? extends SourcesJavaCompilationArgsProvider> deps, + boolean recursive, + ClasspathType type) { + for (SourcesJavaCompilationArgsProvider dep : deps) { + addTransitiveCompilationArgs(dep, recursive, type); + } + + return this; + } + + /** + * Merges the artifacts of another target. + */ + public Builder addTransitiveTarget(TransitiveInfoCollection dep, boolean recursive, + ClasspathType type) { + JavaCompilationArgsProvider provider = dep.getProvider(JavaCompilationArgsProvider.class); + if (provider != null) { + addTransitiveCompilationArgs(provider, recursive, type); + return this; + } else { + NestedSet<Artifact> filesToBuild = + dep.getProvider(FileProvider.class).getFilesToBuild(); + for (Artifact jar : FileType.filter(filesToBuild, JavaSemantics.JAR)) { + addCompileTimeJar(jar); + addRuntimeJar(jar); + } + } + return this; + } + + /** + * Merges the artifacts of a collection of targets. + */ + public Builder addTransitiveTargets(Iterable<? extends TransitiveInfoCollection> deps, + boolean recursive, ClasspathType type) { + for (TransitiveInfoCollection dep : deps) { + addTransitiveTarget(dep, recursive, type); + } + return this; + } + + /** + * Merges the artifacts of a collection of targets. + */ + public Builder addTransitiveTargets(Iterable<? extends TransitiveInfoCollection> deps, + boolean recursive) { + return addTransitiveTargets(deps, recursive, ClasspathType.BOTH); + } + + /** + * Merges the artifacts of a collection of targets. + */ + public Builder addTransitiveDependencies(Iterable<JavaCompilationArgsProvider> deps, + boolean recursive) { + for (JavaCompilationArgsProvider dep : deps) { + addTransitiveDependency(dep, recursive, ClasspathType.BOTH); + } + return this; + } + + /** + * Merges the artifacts of another target. + */ + private Builder addTransitiveDependency(JavaCompilationArgsProvider dep, boolean recursive, + ClasspathType type) { + JavaCompilationArgs args = recursive + ? dep.getRecursiveJavaCompilationArgs() + : dep.getJavaCompilationArgs(); + addTransitiveArgs(args, type); + return this; + } + + /** + * Merges the artifacts of a collection of targets. + */ + public Builder addTransitiveTargets(Iterable<? extends TransitiveInfoCollection> deps) { + return addTransitiveTargets(deps, /*recursive=*/true, ClasspathType.BOTH); + } + + /** + * Includes the contents of another instance of JavaCompilationArgs. + * + * @param args the JavaCompilationArgs instance + * @param type the classpath(s) to consider + */ + public Builder addTransitiveArgs(JavaCompilationArgs args, ClasspathType type) { + if (!ClasspathType.RUNTIME_ONLY.equals(type)) { + compileTimeJarsBuilder.addTransitive(args.getCompileTimeJars()); + } + if (!ClasspathType.COMPILE_ONLY.equals(type)) { + runtimeJarsBuilder.addTransitive(args.getRuntimeJars()); + } + instrumentationMetadataBuilder.addTransitive( + args.getInstrumentationMetadata()); + return this; + } + + /** + * Builds a {@link JavaCompilationArgs} object. + */ + public JavaCompilationArgs build() { + return new JavaCompilationArgs( + runtimeJarsBuilder.build(), + compileTimeJarsBuilder.build(), + instrumentationMetadataBuilder.build()); + } + } + + /** + * Enum to specify transitive compilation args traversal + */ + public static enum ClasspathType { + /* treat the same for compile time and runtime */ + BOTH, + + /* Only include on compile classpath */ + COMPILE_ONLY, + + /* Only include on runtime classpath */ + RUNTIME_ONLY; + } +} |