aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/java/JavaCompilationArgs.java
diff options
context:
space:
mode:
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.java301
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;
+ }
+}