Use an aspect to calculate the Android neverlink libraries.

This cuts the .java -> .android dependency between Java packages, which is nice at the cost of some cavalier over-estimation of the direct dependencies in AndroidNeverlinkAspect.

--
MOS_MIGRATED_REVID=94745544
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index 93a0165..d841c2c 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -470,6 +470,8 @@
               name);
           attributes.put(attrName, attribute);
         }
+
+        advertisedProviders.addAll(parent.getAdvertisedProviders());
       }
       // TODO(bazel-team): move this testonly attribute setting to somewhere else
       // preferably to some base RuleClass implementation.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
index f0a4778..2a36d8d 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
@@ -294,7 +294,6 @@
         deployJar,
         filesBuilder,
         resourceApk,
-        applicationManifest,
         ruleContext.getPrerequisiteArtifacts(PROGUARD_SPECS, Mode.TARGET).list(),
         proguardMapping,
         tools);
@@ -629,12 +628,11 @@
   }
 
   /** Applies the proguard specifications, and creates a ProguardedJar. */
-  public static ProguardOutput applyProguard(RuleContext ruleContext,
+  private static ProguardOutput applyProguard(RuleContext ruleContext,
       AndroidCommon common,
       Artifact deployJarArtifact,
       NestedSetBuilder<Artifact> filesBuilder,
       ResourceApk resourceApk,
-      ApplicationManifest applicationManifest,
       ImmutableList<Artifact> proguardSpecs,
       Artifact proguardMapping,
       AndroidTools tools) {
@@ -658,8 +656,9 @@
         proguardSpecs, proguardMapping, tools.getAndroidJar(), proguardOutputJar, filesBuilder);
   }
 
-  public static ProguardOutput createProguardAction(RuleContext ruleContext, AndroidCommon common,
-      FilesToRunProvider proguard, Artifact jar, ImmutableList<Artifact> proguardSpecs,
+  private static ProguardOutput createProguardAction(RuleContext ruleContext, AndroidCommon common,
+      FilesToRunProvider proguard,
+      Artifact jar, ImmutableList<Artifact> proguardSpecs,
       Artifact proguardMapping, Artifact androidJar, Artifact proguardOutputJar,
       NestedSetBuilder<Artifact> filesBuilder) {
     Iterable<Artifact> libraryJars = NestedSetBuilder.<Artifact>naiveLinkOrder()
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
index 08984b4..093a7fe 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
@@ -23,6 +23,7 @@
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.actions.MiddlemanFactory;
 import com.google.devtools.build.lib.actions.ResourceSet;
+import com.google.devtools.build.lib.analysis.AnalysisUtils;
 import com.google.devtools.build.lib.analysis.FilesToRunProvider;
 import com.google.devtools.build.lib.analysis.OutputGroupProvider;
 import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
@@ -54,6 +55,7 @@
 import com.google.devtools.build.lib.rules.java.JavaCompilationArtifacts;
 import com.google.devtools.build.lib.rules.java.JavaCompilationHelper;
 import com.google.devtools.build.lib.rules.java.JavaNativeLibraryProvider;
+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.JavaTargetAttributes;
@@ -102,7 +104,7 @@
   public AndroidCommon(RuleContext ruleContext, JavaCommon javaCommon) {
     this.ruleContext = ruleContext;
     this.javaCommon = javaCommon;
-    this.asNeverLink = this.javaCommon.isNeverLink();
+    this.asNeverLink = JavaCommon.isNeverLink(ruleContext);
   }
 
   /**
@@ -123,24 +125,31 @@
 
   /**
    * Collects the transitive neverlink dependencies.
+   *
+   * @param ruleContext the context of the rule neverlink deps are to be computed for
+   * @param deps the targets to be treated as dependencies
+   * @param runtimeJars the runtime jars produced by the rule (non-transitive)
+   *
+   * @return a nested set of the neverlink deps.
    */
   public static NestedSet<Artifact> collectTransitiveNeverlinkLibraries(
-      RuleContext ruleContext, JavaCommon javaCommon) {
+      RuleContext ruleContext, Iterable<? extends TransitiveInfoCollection> deps,
+      ImmutableList<Artifact> runtimeJars) {
     NestedSetBuilder<Artifact> builder = NestedSetBuilder.naiveLinkOrder();
-    for (AndroidNeverLinkLibrariesProvider dep :
-        javaCommon.getDependencies(AndroidNeverLinkLibrariesProvider.class)) {
-      builder.addTransitive(dep.getTransitiveNeverLinkLibraries());
+
+    for (AndroidNeverLinkLibrariesProvider provider : AnalysisUtils.getProviders(deps,
+        AndroidNeverLinkLibrariesProvider.class)) {
+      builder.addTransitive(provider.getTransitiveNeverLinkLibraries());
     }
-    if (javaCommon.isNeverLink()) {
-      builder.addAll(javaCommon.getJavaCompilationArtifacts().getRuntimeJars());
-      for (TransitiveInfoCollection dep : javaCommon.getDependencies()) {
-        if (dep.getProvider(AndroidNeverLinkLibrariesProvider.class) != null) {
-          JavaCompilationArgsProvider javaArgs = dep.getProvider(JavaCompilationArgsProvider.class);
-          Preconditions.checkState(javaArgs != null, ruleContext.getLabel());
-          builder.addTransitive(javaArgs.getRecursiveJavaCompilationArgs().getRuntimeJars());
-        }
+
+    if (JavaCommon.isNeverLink(ruleContext)) {
+      builder.addAll(runtimeJars);
+      for (JavaCompilationArgsProvider provider : AnalysisUtils.getProviders(
+          deps, JavaCompilationArgsProvider.class)) {
+        builder.addTransitive(provider.getRecursiveJavaCompilationArgs().getRuntimeJars());
       }
     }
+
     return builder.build();
   }
 
@@ -419,7 +428,10 @@
     javaCommon.setClassPathFragment(new ClasspathConfiguredFragment(
         javaCommon.getJavaCompilationArtifacts(), attributes, asNeverLink));
     
-    transitiveNeverlinkLibraries = collectTransitiveNeverlinkLibraries(ruleContext, javaCommon);
+    transitiveNeverlinkLibraries = collectTransitiveNeverlinkLibraries(
+        ruleContext,
+        javaCommon.getDependencies(),
+        javaCommon.getJavaCompilationArtifacts().getRuntimeJars());
     topLevelSourceJars = ImmutableList.of(srcJar);
     transitiveSourceJars = javaCommon.collectTransitiveSourceJars(srcJar);
 
@@ -446,6 +458,8 @@
 
     return builder
         .setFilesToBuild(filesToBuild)
+        .add(JavaRuntimeJarProvider.class,
+            new JavaRuntimeJarProvider(javaCommon.getJavaCompilationArtifacts().getRuntimeJars()))
         .add(RunfilesProvider.class, RunfilesProvider.simple(runfiles))
         .add(AndroidResourcesProvider.class, new AndroidResourcesProvider(
             ruleContext.getLabel(), transitiveResources))
@@ -454,8 +468,6 @@
             javaCompilationArgs, recursiveJavaCompilationArgs,
             compileTimeDependencyArtifacts,
             NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER)))
-        .add(AndroidNeverLinkLibrariesProvider.class, new AndroidNeverLinkLibrariesProvider(
-            transitiveNeverlinkLibraries))
         .addOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL,
             collectHiddenTopLevelArtifacts(ruleContext))
         .addOutputGroup(JavaSemantics.SOURCE_JARS_OUTPUT_GROUP, transitiveSourceJars);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java
index 0d3ebb8..06e9b0e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibraryBaseRule.java
@@ -29,6 +29,7 @@
 import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.AndroidAaptBaseRule;
 import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.AndroidBaseRule;
 import com.google.devtools.build.lib.rules.android.AndroidRuleClasses.AndroidResourceSupportRule;
+import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
 import com.google.devtools.build.lib.rules.java.JavaSemantics;
 
 /**
@@ -156,6 +157,7 @@
         }))
         .add(attr("$android_manifest_merge_tool", LABEL).cfg(HOST).exec().value(env.getLabel(
             AndroidRuleClasses.MANIFEST_MERGE_TOOL_LABEL)))
+        .advertiseProvider(JavaCompilationArgsProvider.class)
         .build();
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java
new file mode 100644
index 0000000..189b6fb
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidNeverlinkAspect.java
@@ -0,0 +1,84 @@
+// Copyright 2015 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.android;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.analysis.Aspect;
+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.TransitiveInfoCollection;
+import com.google.devtools.build.lib.packages.AspectDefinition;
+import com.google.devtools.build.lib.packages.Type;
+import com.google.devtools.build.lib.rules.java.JavaCommon;
+import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
+import com.google.devtools.build.lib.rules.java.JavaRuntimeJarProvider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An aspect that collects neverlink libraries in the transitive closure.
+ *
+ * <p>Used for determining the -libraryjars argument of the Proguard invocation in Android binaries.
+ *
+ * <p>One would think that using the compile time classpath would be enough, but alas, those are
+ * ijars,
+ */
+public class AndroidNeverlinkAspect implements ConfiguredAspectFactory {
+  private static final ImmutableList<String> ATTRIBUTES = ImmutableList.of(
+      "deps", "exports", "runtime_deps", "binary_under_test", "$instrumentation_test_runner");
+
+  @Override
+  public Aspect create(ConfiguredTarget base, RuleContext ruleContext) {
+    if (!JavaCommon.getConstraints(ruleContext).contains("android")
+        && !ruleContext.getRule().getRuleClass().startsWith("android_")) {
+      return new Aspect.Builder().build();
+    }
+
+    List<TransitiveInfoCollection> deps = new ArrayList<>();
+
+    // This is probably an overestimate, but it's fine -- Proguard doesn't care if there are more
+    // jars in -libraryjars than is required. The alternative would be somehow getting
+    // JavaCommon.getDependencies() here, which would be fugly.
+    for (String attribute : ATTRIBUTES) {
+      if (!ruleContext.getRule().getRuleClassObject().hasAttr(attribute, Type.LABEL_LIST)) {
+        continue;
+      }
+
+      deps.addAll(ruleContext.getPrerequisites(attribute, Mode.TARGET));
+    }
+
+    return new Aspect.Builder()
+        .addProvider(AndroidNeverLinkLibrariesProvider.class,
+            new AndroidNeverLinkLibrariesProvider(AndroidCommon.collectTransitiveNeverlinkLibraries(
+                ruleContext,
+                deps,
+                base.getProvider(JavaRuntimeJarProvider.class).getRuntimeJars())))
+        .build();
+  }
+
+  @Override
+  public AspectDefinition getDefinition() {
+    AspectDefinition.Builder builder = new AspectDefinition.Builder("AndroidNeverlinkAspect");
+    for (String attribute : ATTRIBUTES) {
+      builder.attributeAspect(attribute, AndroidNeverlinkAspect.class);
+    }
+
+    return builder
+        .requireProvider(JavaCompilationArgsProvider.class)
+        .build();
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
index 6664288..f859fc4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidRuleClasses.java
@@ -45,6 +45,7 @@
 import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
 import com.google.devtools.build.lib.packages.TriState;
 import com.google.devtools.build.lib.packages.Type;
+import com.google.devtools.build.lib.rules.java.JavaCompilationArgsProvider;
 import com.google.devtools.build.lib.rules.java.JavaSemantics;
 import com.google.devtools.build.lib.syntax.Label;
 import com.google.devtools.build.lib.util.FileType;
@@ -551,8 +552,11 @@
           <code>cc_library</code> wrapping or producing <code>.so</code> native libraries for the
           Android target platform.
           <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
-          .override(builder.copy("deps").cfg(ANDROID_SPLIT_TRANSITION)
-              .allowedRuleClasses(ALLOWED_DEPENDENCIES).allowedFileTypes())
+          .override(builder.copy("deps")
+              .cfg(ANDROID_SPLIT_TRANSITION)
+              .allowedRuleClasses(ALLOWED_DEPENDENCIES)
+              .allowedFileTypes()
+              .aspect(AndroidNeverlinkAspect.class))
           // Proguard rule specifying master list of classes to keep during legacy multidexing.
           .add(attr("$build_incremental_dexmanifest", LABEL).cfg(HOST).exec()
               .value(env.getLabel(AndroidRuleClasses.BUILD_INCREMENTAL_DEXMANIFEST_LABEL)))
@@ -664,6 +668,7 @@
             </ul>
           <!-- #END_BLAZE_RULE.ATTRIBUTE --> */
           .add(attr("legacy_native_support", TRISTATE).value(TriState.AUTO))
+          .advertiseProvider(JavaCompilationArgsProvider.class)
           .build();
       }
 
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
index 66dafc2..ef72a40 100644
--- 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
@@ -159,6 +159,12 @@
         .build();
   }
 
+  public static ImmutableList<String> getConstraints(RuleContext ruleContext) {
+    return ruleContext.getRule().isAttrDefined("constraints", Type.STRING_LIST)
+        ? ImmutableList.copyOf(ruleContext.attributes().get("constraints", Type.STRING_LIST))
+        : ImmutableList.<String>of();
+  }
+
   public void setClassPathFragment(ClasspathConfiguredFragment classpathFragment) {
     this.classpathFragment = classpathFragment;
   }
@@ -634,7 +640,7 @@
    *
    * @return the value of the neverlink attribute.
    */
-  public final boolean isNeverLink() {
+  public static final boolean isNeverLink(RuleContext ruleContext) {
     return ruleContext.getRule().isAttrDefined("neverlink", Type.BOOLEAN) &&
         ruleContext.attributes().get("neverlink", Type.BOOLEAN);
   }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java
index 5e59311..f82eefb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaImport.java
@@ -74,11 +74,11 @@
     CppCompilationContext transitiveCppDeps = common.collectTransitiveCppDeps();
     NestedSet<LinkerInput> transitiveJavaNativeLibraries =
         common.collectTransitiveJavaNativeLibraries();
-
+    boolean neverLink = JavaCommon.isNeverLink(ruleContext);
     JavaCompilationArgs javaCompilationArgs = common.collectJavaCompilationArgs(
-        false, common.isNeverLink(), compilationArgsFromSources());
+        false, neverLink, compilationArgsFromSources());
     JavaCompilationArgs recursiveJavaCompilationArgs = common.collectJavaCompilationArgs(
-        true, common.isNeverLink(), compilationArgsFromSources());
+        true, neverLink, compilationArgsFromSources());
     NestedSet<Artifact> transitiveJavaSourceJars =
         collectTransitiveJavaSourceJars(ruleContext, srcJar);
     if (srcJar != null) {
@@ -87,7 +87,7 @@
 
     // The "neverlink" attribute is transitive, so if it is enabled, we don't add any
     // runfiles from this target or its dependencies.
-    Runfiles runfiles = common.isNeverLink() ?
+    Runfiles runfiles = neverLink ?
         Runfiles.EMPTY :
         new Runfiles.Builder()
             // add the jars to the runfiles
@@ -120,7 +120,9 @@
     common.addTransitiveInfoProviders(ruleBuilder, filesToBuild, null);
     return ruleBuilder
         .setFilesToBuild(filesToBuild)
-        .add(JavaNeverlinkInfoProvider.class, new JavaNeverlinkInfoProvider(common.isNeverLink()))
+        .add(JavaRuntimeJarProvider.class,
+            new JavaRuntimeJarProvider(common.getJavaCompilationArtifacts().getRuntimeJars()))
+        .add(JavaNeverlinkInfoProvider.class, new JavaNeverlinkInfoProvider(neverLink))
         .add(RunfilesProvider.class, RunfilesProvider.simple(runfiles))
         .add(CcLinkParamsProvider.class, new CcLinkParamsProvider(ccLinkParamsStore))
         .add(JavaCompilationArgsProvider.class, new JavaCompilationArgsProvider(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java
index 5cbfe13..8db95eb 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaImportBaseRule.java
@@ -71,6 +71,7 @@
         .add(attr("constraints", STRING_LIST)
             .orderIndependent()
             .nonconfigurable("used in Attribute.validityPredicate implementations (loading time)"))
+        .advertiseProvider(JavaCompilationArgsProvider.class)
         .build();
   }
 
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
index 8df9711d..68f5ccd 100644
--- 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
@@ -65,7 +65,8 @@
     JavaCompilationHelper helper = new JavaCompilationHelper(
         ruleContext, semantics, common.getJavacOpts(), attributesBuilder);
     helper.addLibrariesToAttributes(common.targetsTreatedAsDeps(ClasspathType.COMPILE_ONLY));
-    helper.addProvidersToAttributes(common.compilationArgsFromSources(), common.isNeverLink());
+    helper.addProvidersToAttributes(common.compilationArgsFromSources(),
+        JavaCommon.isNeverLink(ruleContext));
 
     if (ruleContext.hasErrors()) {
       return null;
@@ -131,18 +132,19 @@
           javaArtifactsBuilder);
     }
 
+    boolean neverLink = JavaCommon.isNeverLink(ruleContext);
     common.setJavaCompilationArtifacts(javaArtifactsBuilder.build());
     common.setClassPathFragment(new ClasspathConfiguredFragment(
-        common.getJavaCompilationArtifacts(), attributes, common.isNeverLink()));
+        common.getJavaCompilationArtifacts(), attributes, neverLink));
     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());
+        false, neverLink, common.compilationArgsFromSources());
     JavaCompilationArgs recursiveJavaCompilationArgs = common.collectJavaCompilationArgs(
-        true, common.isNeverLink(), common.compilationArgsFromSources());
+        true, neverLink, common.compilationArgsFromSources());
     NestedSet<Artifact> compileTimeJavaDepArtifacts = common.collectCompileTimeDependencyArtifacts(
         common.getJavaCompilationArtifacts().getCompileTimeDependencyArtifact());
     NestedSet<Artifact> runTimeJavaDepArtifacts = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
@@ -175,7 +177,7 @@
     // 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()) {
+    if (!neverLink) {
       Runfiles.Builder runfilesBuilder = new Runfiles.Builder().addArtifacts(
           common.getJavaCompilationArtifacts().getRuntimeJars());
 
@@ -217,9 +219,11 @@
     common.addTransitiveInfoProviders(builder, filesToBuild, classJar);
 
     builder
+        .add(JavaRuntimeJarProvider.class,
+            new JavaRuntimeJarProvider(common.getJavaCompilationArtifacts().getRuntimeJars()))
         .add(RunfilesProvider.class, RunfilesProvider.simple(runfiles))
         .setFilesToBuild(filesToBuild)
-        .add(JavaNeverlinkInfoProvider.class, new JavaNeverlinkInfoProvider(common.isNeverLink()))
+        .add(JavaNeverlinkInfoProvider.class, new JavaNeverlinkInfoProvider(neverLink))
         .add(CppCompilationContext.class, transitiveCppDeps)
         .add(JavaCompilationArgsProvider.class, new JavaCompilationArgsProvider(
             javaCompilationArgs, recursiveJavaCompilationArgs,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeJarProvider.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeJarProvider.java
new file mode 100644
index 0000000..7cbdca0
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaRuntimeJarProvider.java
@@ -0,0 +1,42 @@
+// Copyright 2015 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.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
+
+/**
+ * This {@link com.google.devtools.build.lib.analysis.TransitiveInfoProvider} contains the .jar
+ * files to be put on the runtime classpath by the configured target.
+ *
+ * <p>Unlike {@link com.google.devtools.build.lib.rules.java.JavaCompilationArgs#getRuntimeJars()},
+ * it does not contain transitive runtime jars, only those produced by the configured target itself.
+ *
+ * <p>The reason why this class exists is that neverlink libraries do not contain the compiled jar
+ * in {@link com.google.devtools.build.lib.rules.java.JavaCompilationArgs#getRuntimeJars()}.
+ */
+@Immutable
+public final class JavaRuntimeJarProvider implements TransitiveInfoProvider {
+  private final ImmutableList<Artifact> runtimeJars;
+
+  public JavaRuntimeJarProvider(ImmutableList<Artifact> runtimeJars) {
+    this.runtimeJars = runtimeJars;
+  }
+
+  public ImmutableList<Artifact> getRuntimeJars() {
+    return runtimeJars;
+  }
+}