kleaf: Allow absolute_out_dir (out/) to be overridden.

Allow to redirect the whole output directory to a different value.

Also fix previously broken test_override_javatmp test.

Test: KleafIntegrationTest.test_override_absolute_out_dir
Bug: 267580482
Change-Id: I4606567ad95537131ea043f05857e121fe2fe4bd
diff --git a/kleaf/bazel.py b/kleaf/bazel.py
index 624ce78..30bbdef 100755
--- a/kleaf/bazel.py
+++ b/kleaf/bazel.py
@@ -66,7 +66,6 @@
         self.env = env.copy()
 
         self.bazel_path = f"{self.root_dir}/{_BAZEL_REL_PATH}"
-        self.absolute_out_dir = f"{self.root_dir}/out"
 
         command_idx = None
         for idx, arg in enumerate(bazel_args):
@@ -102,11 +101,15 @@
         """
 
         parser = argparse.ArgumentParser(add_help=False)
-        parser.add_argument("--output_user_root",
+        parser.add_argument("--output_root",
                             type=_require_absolute_path,
-                            default=_require_absolute_path(f"{self.absolute_out_dir}/bazel/output_user_root"))
+                            default=_require_absolute_path(f"{self.root_dir}/out"))
+        parser.add_argument("--output_user_root",
+                            type=_require_absolute_path)
         known_startup_options, user_startup_options = parser.parse_known_args(self.startup_options)
-        self.absolute_user_root = known_startup_options.output_user_root
+        self.absolute_out_dir = known_startup_options.output_root
+        self.absolute_user_root = known_startup_options.output_user_root or \
+                                  f"{self.absolute_out_dir}/bazel/output_user_root"
         self.transformed_startup_options = [
             f"--host_jvm_args=-Djava.io.tmpdir={self.absolute_out_dir}/bazel/javatmp",
         ]
diff --git a/kleaf/tests/integration_test/integration_test.py b/kleaf/tests/integration_test/integration_test.py
index f894f04..6eae204 100644
--- a/kleaf/tests/integration_test/integration_test.py
+++ b/kleaf/tests/integration_test/integration_test.py
@@ -33,6 +33,7 @@
 """
 
 import argparse
+import functools
 import hashlib
 import os
 import shlex
@@ -261,16 +262,41 @@
 
         See b/267580482."""
         default_java_tmp = pathlib.Path("out/bazel/javatmp")
+        new_java_tmp = tempfile.TemporaryDirectory()
+        self.addCleanup(new_java_tmp.cleanup)
         try:
             shutil.rmtree(default_java_tmp)
         except FileNotFoundError:
             pass
         self._check_call(
-            startup_options=[f"--host_jvm_args=-Djava.io.tmpdir=/tmp/bazel/javatmp"],
+            startup_options=[f"--host_jvm_args=-Djava.io.tmpdir={new_java_tmp.name}"],
             command="build",
             command_args=["//build/kernel/kleaf:empty_test"] + _FASTEST)
         self.assertFalse(default_java_tmp.exists())
 
+    def test_override_absolute_out_dir(self):
+        """Tests that out/ can be overridden.
+
+        See b/267580482."""
+        default_out = pathlib.Path("out")
+        new_out = tempfile.TemporaryDirectory()
+        self.addCleanup(new_out.cleanup)
+        try:
+            shutil.rmtree(default_out)
+        except FileNotFoundError:
+            pass
+        self._check_call(
+            command="build",
+            command_args=["//build/kernel/kleaf:empty_test"] + _FASTEST)
+        self.assertTrue(default_out.exists())
+        shutil.rmtree(default_out)
+        self._check_call(
+            startup_options=[f"--output_root={new_out.name}"],
+            command="build",
+            command_args=["//build/kernel/kleaf:empty_test"] + _FASTEST)
+        self.assertFalse(default_out.exists())
+
+
 if __name__ == "__main__":
     arguments, unknown = load_arguments()
     sys.argv[1:] = unknown