Correctly create output artifact paths for the Databinding Resource Processor action.

The wrapper code around the databinding resource processor appends the input
resource root to the output resource base directory, and Blaze has to create
output artifacts to match. Blaze was creating incorrect artifact output paths
for resources in bin and genfiles by not including the bin / genfiles roots.

RELNOTES: None.
PiperOrigin-RevId: 239234939
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataBindingProcessorBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataBindingProcessorBuilder.java
index 1cf6eb7..8c7f304 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataBindingProcessorBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataBindingProcessorBuilder.java
@@ -45,8 +45,8 @@
       // <bazel-pkg>/databinding-processed-resources/<rule-name>/<bazal-pkg>/<resource-dir>
 
       Artifact databindingProcessedResource =
-          dataContext.getUniqueDirectoryArtifact("databinding-processed-resources",
-              resource.getRootRelativePath());
+          dataContext.getUniqueDirectoryArtifact(
+              "databinding-processed-resources", resource.getExecPath());
 
       databindingProcessedResourcesBuilder.add(databindingProcessedResource);
     }
@@ -58,28 +58,24 @@
     // Create output resource roots that correspond to the paths of the resources created above:
     //
     //   <bazel-pkg>/databinding-processed-resources/<rule-name>/<resource-root>
-    //
-    // AndroidDataBindingProcessingAction will append each value of --resource_root to its
-    // corresponding --output_resource_root, so the only part that needs to be constructed here is
-    //
-    //   <bazel-pkg>/databinding-processed-resources/<rule-name>
     ArtifactRoot binOrGenfiles = dataContext.getBinOrGenfilesDirectory();
     PathFragment uniqueDir =
         dataContext.getUniqueDirectory(PathFragment.create("databinding-processed-resources"));
     PathFragment outputResourceRoot = binOrGenfiles.getExecPath().getRelative(uniqueDir);
 
+    // AndroidDataBindingProcessingAction will append each value of --resource_root to its
+    // corresponding --output_resource_directory, so the only part that needs to be constructed here
+    // is:
+    //
+    //   <bazel-pkg>/databinding-processed-resources/<rule-name>
+    builder.addFlag("--output_resource_directory", outputResourceRoot.toString());
+
     ImmutableList.Builder<PathFragment> outputResourceRootsBuilder = ImmutableList.builder();
     for (PathFragment resourceRoot : androidResources.getResourceRoots()) {
 
-      outputResourceRootsBuilder.add(outputResourceRoot);
-
-      // The order of these matter, the input root and the output root have to be matched up
-      // because the resource processor will iterate over them in pairs.
-      // TODO(ahumesky): This is currently sets the output resource root to the same root for
-      // all input roots, but separate output roots may still need to be maintained since this
-      // is doing a sort of merge before the real resource merger runs.
       builder.addFlag("--resource_root", resourceRoot.toString());
-      builder.addFlag("--output_resource_root", outputResourceRoot.toString());
+
+      outputResourceRootsBuilder.add(outputResourceRoot.getRelative(resourceRoot));
     }
 
     // Even though the databinding processor really only cares about layout files, we send
diff --git a/src/test/java/com/google/devtools/build/android/AndroidDataBindingProcessingActionTest.java b/src/test/java/com/google/devtools/build/android/AndroidDataBindingProcessingActionTest.java
index dbc0cd4..e9d30b2 100644
--- a/src/test/java/com/google/devtools/build/android/AndroidDataBindingProcessingActionTest.java
+++ b/src/test/java/com/google/devtools/build/android/AndroidDataBindingProcessingActionTest.java
@@ -23,7 +23,6 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 import org.junit.After;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -55,8 +54,9 @@
   public void testNoResourceRoots() throws Exception {
 
     String[] args = {
-        "--dataBindingInfoOut=" + dataBindingInfoOut,
-        "--appId=foo.bar",
+      "--output_resource_directory=" + tempDir.resolve("res"),
+      "--dataBindingInfoOut=" + dataBindingInfoOut,
+      "--appId=foo.bar",
     };
     AndroidDataBindingProcessingAction.main(args);
 
@@ -73,10 +73,10 @@
         testDataPrefix + "src/test/java/com/google/devtools/build/android/testing/databinding/res";
 
     String[] args = {
-        "--resource_root=" + resourceRoot,
-        "--output_resource_root=" + tempDir.resolve("res"),
-        "--dataBindingInfoOut=" + dataBindingInfoOut,
-        "--appId=foo.bar",
+      "--output_resource_directory=" + tempDir.resolve("res"),
+      "--resource_root=" + resourceRoot,
+      "--dataBindingInfoOut=" + dataBindingInfoOut,
+      "--appId=foo.bar",
     };
     AndroidDataBindingProcessingAction.main(args);
 
@@ -96,12 +96,11 @@
         testDataPrefix + "src/test/java/com/google/devtools/build/android/testing/databinding/res2";
 
     String[] args = {
-        "--resource_root=" + resourceRoot,
-        "--output_resource_root=" + tempDir.resolve("res"),
-        "--resource_root=" + resourceRoot2,
-        "--output_resource_root=" + tempDir.resolve("res2"),
-        "--dataBindingInfoOut=" + dataBindingInfoOut,
-        "--appId=foo.bar",
+      "--output_resource_directory=" + tempDir.resolve("res"),
+      "--resource_root=" + resourceRoot,
+      "--resource_root=" + resourceRoot2,
+      "--dataBindingInfoOut=" + dataBindingInfoOut,
+      "--appId=foo.bar",
     };
     AndroidDataBindingProcessingAction.main(args);
 
@@ -111,56 +110,4 @@
     List<? extends ZipEntry> zipEntries = Collections.list(layoutInfo.entries());
     assertThat(zipEntries).hasSize(2);
   }
-
-  @Test
-  public void testInputOutputResourceRootsMismatchThrows() throws Exception {
-
-    // resource_root, no output_resource_root
-    String[] args1 = {
-        "--resource_root=foo",
-        "--dataBindingInfoOut=" + dataBindingInfoOut,
-        "--appId=foo.bar",
-    };
-
-    Assert.assertThrows(
-        IllegalArgumentException.class,
-        () -> AndroidDataBindingProcessingAction.main(args1));
-
-    // output_resource_root, no resource_root
-    String[] args2 = {
-        "--output_resource_root=foo",
-        "--dataBindingInfoOut=" + dataBindingInfoOut,
-        "--appId=foo.bar",
-    };
-
-    Assert.assertThrows(
-        IllegalArgumentException.class,
-        () -> AndroidDataBindingProcessingAction.main(args2));
-
-    // 2 resource_roots, but 1 output_resource_root
-    String[] args3 = {
-        "--resource_root=foo",
-        "--output_resource_root=bar",
-        "--resource_root=baz",
-        "--dataBindingInfoOut=" + dataBindingInfoOut,
-        "--appId=foo.bar",
-    };
-
-    Assert.assertThrows(
-        IllegalArgumentException.class,
-        () -> AndroidDataBindingProcessingAction.main(args3));
-
-    // 2 output_resource_root, but 1 resource_root
-    String[] args4 = {
-        "--resource_root=foo",
-        "--output_resource_root=bar",
-        "--output_resource_root=baz",
-        "--dataBindingInfoOut=" + dataBindingInfoOut,
-        "--appId=foo.bar",
-    };
-
-    Assert.assertThrows(
-        IllegalArgumentException.class,
-        () -> AndroidDataBindingProcessingAction.main(args4));
-  }
 }
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidDataBindingProcessingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidDataBindingProcessingAction.java
index b2b470b..50eb067 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidDataBindingProcessingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidDataBindingProcessingAction.java
@@ -54,16 +54,16 @@
     public List<Path> resourceRoots;
 
     @Option(
-        name = "output_resource_root",
-        defaultValue =  "null",
-        converter =  PathConverter.class,
-        allowMultiple =  true,
+        name = "output_resource_directory",
+        defaultValue = "null",
+        converter = PathConverter.class,
         category = "input",
         documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
         effectTags = {OptionEffectTag.UNKNOWN},
-        help = "The output resource root. A corresponding input resource root must be passed to "
-            + "--resource_root. Multiple roots will be paired in the order they're passed.")
-    public List<Path> outputResourceRoots;
+        help =
+            "The output resource directory. Input source roots will be appended to this to "
+                + "create the output resource roots.")
+    public Path outputResourceDirectory;
 
     @Option(
         name = "packageType",
@@ -114,28 +114,22 @@
       throw new IllegalArgumentException("--appId is required");
     }
 
+    if (options.outputResourceDirectory == null) {
+      throw new IllegalArgumentException("--output_resource_directory is required");
+    }
+
     List<Path> resourceRoots = options.resourceRoots == null
         ? Collections.emptyList()
         : options.resourceRoots;
-    List<Path> outputResourceRoots = options.outputResourceRoots == null
-        ? Collections.emptyList()
-        : options.outputResourceRoots;
-
-    if (resourceRoots.size() != outputResourceRoots.size()) {
-      throw new IllegalArgumentException("--resource_root and --output_resource_root must be "
-          + "specified the same number of times");
-    }
 
     try (ScopedTemporaryDirectory dataBindingInfoOutDir =
         new ScopedTemporaryDirectory("android_data_binding_layout_info_tmp")) {
 
       // 1. Process databinding resources for each source root.
-      for (int i = 0; i < resourceRoots.size(); i++) {
+      for (Path resourceRoot : resourceRoots) {
 
-        Path resourceRoot = resourceRoots.get(i);
-        Path outputResourceRoot = outputResourceRoots.get(i);
         AndroidResourceProcessor.processDataBindings(
-            outputResourceRoot,
+            options.outputResourceDirectory,
             resourceRoot,
             dataBindingInfoOutDir.getPath(),
             options.appId,