public Result createBuildableForAndroidResources(
      BuildRuleResolver ruleResolver, boolean createBuildableIfEmptyDeps) {
    ImmutableSortedSet<BuildRule> originalDeps = originalBuildRuleParams.getDeps();
    ImmutableList<HasAndroidResourceDeps> androidResourceDeps =
        UberRDotJavaUtil.getAndroidResourceDeps(originalDeps);

    if (androidResourceDeps.isEmpty() && !createBuildableIfEmptyDeps) {
      return new Result(originalBuildRuleParams, Optional.<DummyRDotJava>absent());
    }

    BuildRule dummyRDotJavaBuildRule =
        ruleResolver.buildAndAddToIndex(
            DummyRDotJava.newDummyRDotJavaBuildableBuilder(buildRuleBuilderParams)
                .setBuildTarget(dummyRDotJavaBuildTarget)
                .setAndroidResourceDeps(androidResourceDeps));
    final DummyRDotJava dummyRDotJava = (DummyRDotJava) dummyRDotJavaBuildRule.getBuildable();

    ImmutableSortedSet<BuildRule> totalDeps =
        ImmutableSortedSet.<BuildRule>naturalOrder()
            .addAll(originalDeps)
            .add(dummyRDotJavaBuildRule)
            .build();

    BuildRuleParams newBuildRuleParams = originalBuildRuleParams.copyWithChangedDeps(totalDeps);

    return new Result(newBuildRuleParams, Optional.of(dummyRDotJava));
  }
  @Override
  protected ImmutableList<HasAndroidResourceDeps> getAndroidResourceDepsInternal(
      DependencyGraph graph) {
    // Filter out the AndroidResourceRules that are needed by this APK but not the APK under test.
    ImmutableSet<HasAndroidResourceDeps> originalResources =
        ImmutableSet.copyOf(UberRDotJavaUtil.getAndroidResourceDeps(apkUnderTest, graph));
    ImmutableList<HasAndroidResourceDeps> instrumentationResources =
        UberRDotJavaUtil.getAndroidResourceDeps(this, graph);

    // Include all of the instrumentation resources first, in their original order.
    ImmutableList.Builder<HasAndroidResourceDeps> allResources = ImmutableList.builder();
    for (HasAndroidResourceDeps resource : instrumentationResources) {
      if (!originalResources.contains(resource)) {
        allResources.add(resource);
      }
    }
    return allResources.build();
  }
Example #3
0
  @Override
  public List<Step> getBuildSteps(BuildContext context, final BuildableContext buildableContext) {
    ImmutableList.Builder<Step> steps = ImmutableList.builder();
    final Path rDotJavaSrcFolder = getRDotJavaSrcFolder(buildTarget);
    steps.add(new MakeCleanDirectoryStep(rDotJavaSrcFolder));

    // Generate the .java files and record where they will be written in javaSourceFilePaths.
    Set<SourcePath> javaSourceFilePaths = Sets.newHashSet();
    if (androidResourceDeps.isEmpty()) {
      // In this case, the user is likely running a Robolectric test that does not happen to
      // depend on any resources. However, if Robolectric doesn't find an R.java file, it flips
      // out, so we have to create one, anyway.

      // TODO(mbolin): Stop hardcoding com.facebook. This should match the package in the
      // associated TestAndroidManifest.xml file.
      String rDotJavaPackage = "com.facebook";
      String javaCode =
          MergeAndroidResourcesStep.generateJavaCodeForPackageWithoutResources(rDotJavaPackage);
      steps.add(new MakeCleanDirectoryStep(rDotJavaSrcFolder.resolve("com/facebook")));
      Path rDotJavaFile = rDotJavaSrcFolder.resolve("com/facebook/R.java");
      steps.add(new WriteFileStep(javaCode, rDotJavaFile));
      javaSourceFilePaths.add(new PathSourcePath(rDotJavaFile));
    } else {
      Map<Path, String> symbolsFileToRDotJavaPackage = Maps.newHashMap();
      for (HasAndroidResourceDeps res : androidResourceDeps) {
        String rDotJavaPackage = res.getRDotJavaPackage();
        symbolsFileToRDotJavaPackage.put(res.getPathToTextSymbolsFile(), rDotJavaPackage);
        Path rDotJavaFilePath =
            MergeAndroidResourcesStep.getOutputFilePath(rDotJavaSrcFolder, rDotJavaPackage);
        javaSourceFilePaths.add(new PathSourcePath(rDotJavaFilePath));
      }
      steps.add(new MergeAndroidResourcesStep(symbolsFileToRDotJavaPackage, rDotJavaSrcFolder));
    }

    // Clear out the directory where the .class files will be generated.
    final Path rDotJavaClassesFolder = getRDotJavaBinFolder();
    steps.add(new MakeCleanDirectoryStep(rDotJavaClassesFolder));

    Path pathToAbiOutputDir = getPathToAbiOutputDir(buildTarget);
    steps.add(new MakeCleanDirectoryStep(pathToAbiOutputDir));
    Path pathToAbiOutputFile = pathToAbiOutputDir.resolve("abi");

    // Compile the .java files.
    final JavacStep javacStep =
        UberRDotJavaUtil.createJavacStepForDummyRDotJavaFiles(
            javaSourceFilePaths,
            rDotJavaClassesFolder,
            Optional.of(pathToAbiOutputFile),
            javacOptions,
            buildTarget);
    steps.add(javacStep);

    steps.add(
        new AbstractExecutionStep("record_abi_key") {
          @Override
          public int execute(ExecutionContext context) {
            Sha1HashCode abiKey = javacStep.getAbiKey();
            Preconditions.checkNotNull(
                abiKey, "Javac step must create a non-null ABI key for this rule.");
            buildableContext.addMetadata(METADATA_KEY_FOR_ABI_KEY, abiKey.getHash());
            return 0;
          }
        });

    buildableContext.recordArtifactsInDirectory(rDotJavaClassesFolder);
    return steps.build();
  }