David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # |
| 3 | # Copyright (C) 2021 The Android Open Source Project |
| 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | # you may not use this file except in compliance with the License. |
| 7 | # You may obtain a copy of the License at |
| 8 | # |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | # See the License for the specific language governing permissions and |
| 15 | # limitations under the License. |
| 16 | |
| 17 | """ |
| 18 | This scripts compiles Java files which are needed to execute run-tests. |
| 19 | It is intended to be used only from soong genrule. |
| 20 | """ |
| 21 | |
| 22 | import argparse, os, tempfile, shutil, subprocess, glob, textwrap, re, json, concurrent.futures |
| 23 | |
| 24 | ZIP = "prebuilts/build-tools/linux-x86/bin/soong_zip" |
David Srbecky | 9292b88 | 2022-03-23 13:24:15 +0000 | [diff] [blame] | 25 | BUILDFAILURES = json.loads(open(os.path.join("art", "test", "buildfailures.json"), "rt").read()) |
David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 26 | |
David Srbecky | 271d572 | 2021-10-06 13:40:20 +0100 | [diff] [blame] | 27 | def copy_sources(args, tmp, mode, srcdir): |
| 28 | """Copy test files from Android tree into the build sandbox and return its path.""" |
| 29 | |
David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 30 | join = os.path.join |
| 31 | test = os.path.basename(srcdir) |
| 32 | dstdir = join(tmp, mode, test) |
| 33 | |
| 34 | # Don't build tests that are disabled since they might not compile (e.g. on jvm). |
David Srbecky | 9292b88 | 2022-03-23 13:24:15 +0000 | [diff] [blame] | 35 | def is_buildfailure(kf): |
David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 36 | return test in kf.get("tests", []) and mode == kf.get("variant") and not kf.get("env_vars") |
David Srbecky | 9292b88 | 2022-03-23 13:24:15 +0000 | [diff] [blame] | 37 | if any(is_buildfailure(kf) for kf in BUILDFAILURES): |
David Srbecky | 271d572 | 2021-10-06 13:40:20 +0100 | [diff] [blame] | 38 | return None |
David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 39 | |
| 40 | # Copy all source files to the temporary directory. |
| 41 | shutil.copytree(srcdir, dstdir) |
| 42 | |
| 43 | # Copy the default scripts if the test does not have a custom ones. |
| 44 | for name in ["build", "run", "check"]: |
| 45 | src, dst = f"art/test/etc/default-{name}", join(dstdir, name) |
| 46 | if os.path.exists(dst): |
| 47 | shutil.copy2(src, dstdir) # Copy default script next to the custom script. |
| 48 | else: |
| 49 | shutil.copy2(src, dst) # Use just the default script. |
| 50 | os.chmod(dst, 0o755) |
David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 51 | |
David Srbecky | 271d572 | 2021-10-06 13:40:20 +0100 | [diff] [blame] | 52 | return dstdir |
| 53 | |
| 54 | def build_test(args, mode, dstdir): |
| 55 | """Run the build script for single run-test""" |
| 56 | |
| 57 | join = os.path.join |
David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 58 | build_top = os.getcwd() |
| 59 | java_home = os.environ.get("JAVA_HOME") |
| 60 | tools_dir = os.path.abspath(join(os.path.dirname(__file__), "../../../out/bin")) |
| 61 | env = { |
| 62 | "PATH": os.environ.get("PATH"), |
| 63 | "ANDROID_BUILD_TOP": build_top, |
| 64 | "ART_TEST_RUN_TEST_BOOTCLASSPATH": join(build_top, args.bootclasspath), |
David Srbecky | 271d572 | 2021-10-06 13:40:20 +0100 | [diff] [blame] | 65 | "TEST_NAME": os.path.basename(dstdir), |
David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 66 | "SOONG_ZIP": join(build_top, "prebuilts/build-tools/linux-x86/bin/soong_zip"), |
| 67 | "ZIPALIGN": join(build_top, "prebuilts/build-tools/linux-x86/bin/zipalign"), |
| 68 | "JAVA": join(java_home, "bin/java"), |
David Srbecky | 9de71a4 | 2022-04-07 21:32:43 +0100 | [diff] [blame] | 69 | "JAVAC": join(java_home, "bin/javac"), |
| 70 | "JAVAC_ARGS": "-g -Xlint:-options -source 1.8 -target 1.8", |
David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 71 | "D8": join(tools_dir, "d8"), |
| 72 | "HIDDENAPI": join(tools_dir, "hiddenapi"), |
| 73 | "JASMIN": join(tools_dir, "jasmin"), |
| 74 | "SMALI": join(tools_dir, "smali"), |
| 75 | "NEED_DEX": {"host": "true", "target": "true", "jvm": "false"}[mode], |
| 76 | "USE_DESUGAR": "true", |
| 77 | } |
| 78 | proc = subprocess.run([join(dstdir, "build"), "--" + mode], |
| 79 | cwd=dstdir, |
| 80 | env=env, |
| 81 | encoding=os.sys.stdout.encoding, |
| 82 | stderr=subprocess.STDOUT, |
| 83 | stdout=subprocess.PIPE) |
| 84 | return proc.stdout, proc.returncode |
| 85 | |
| 86 | def main(): |
| 87 | parser = argparse.ArgumentParser(description=__doc__) |
| 88 | parser.add_argument("--out", help="Path of the generated ZIP file with the build data") |
| 89 | parser.add_argument('--mode', choices=['host', 'jvm', 'target']) |
| 90 | parser.add_argument("--shard", help="Identifies subset of tests to build (00..99)") |
| 91 | parser.add_argument("--bootclasspath", help="JAR files used for javac compilation") |
| 92 | args = parser.parse_args() |
| 93 | |
| 94 | with tempfile.TemporaryDirectory(prefix=os.path.basename(__file__)) as tmp: |
| 95 | srcdirs = sorted(glob.glob(os.path.join("art", "test", "*"))) |
| 96 | srcdirs = filter(lambda srcdir: re.match(".*/\d*{}-.*".format(args.shard), srcdir), srcdirs) |
David Srbecky | 271d572 | 2021-10-06 13:40:20 +0100 | [diff] [blame] | 97 | dstdirs = [copy_sources(args, tmp, args.mode, srcdir) for srcdir in srcdirs] |
| 98 | dstdirs = filter(lambda dstdir: dstdir, dstdirs) # Remove None (skipped tests). |
David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 99 | with concurrent.futures.ThreadPoolExecutor() as pool: |
David Srbecky | 271d572 | 2021-10-06 13:40:20 +0100 | [diff] [blame] | 100 | for stdout, exitcode in pool.map(lambda dstdir: build_test(args, args.mode, dstdir), dstdirs): |
David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 101 | if stdout: |
| 102 | print(stdout.strip()) |
David Srbecky | 9292b88 | 2022-03-23 13:24:15 +0000 | [diff] [blame] | 103 | assert(exitcode == 0) # Build failed. Add test to buildfailures.json if this is expected. |
David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 104 | |
| 105 | # Create the final zip file which contains the content of the temporary directory. |
David Srbecky | 271d572 | 2021-10-06 13:40:20 +0100 | [diff] [blame] | 106 | proc = subprocess.run([ZIP, "-o", args.out, "-C", tmp, "-D", tmp], check=True) |
David Srbecky | 7cf6c58 | 2021-07-20 16:56:06 +0100 | [diff] [blame] | 107 | |
| 108 | if __name__ == "__main__": |
| 109 | main() |