diff options
author | Pierre Labatut <plabatut@google.com> | 2023-11-20 15:23:34 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-11-20 15:23:34 +0000 |
commit | 266c56b217853ac85309097d0ebe8eadf69685d9 (patch) | |
tree | d1955d68356e0ba70f865f6f7d41f2168a477df7 | |
parent | 26574ad76d80ba29ab9b372491a2b71f62a3b40c (diff) | |
parent | e9870d118c6e9077149edff04fd87033b3aea13c (diff) | |
download | cuttlefish_vmm-266c56b217853ac85309097d0ebe8eadf69685d9.tar.gz |
Migrate code generation to typed python. am: 32e6044366 am: 4c873fa67e am: e9870d118c
Original change: https://android-review.googlesource.com/c/device/google/cuttlefish_vmm/+/2818639
Change-Id: Ic48e6c0c8cc91c02a170c14619ae534c2445065e
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | Android.bp | 78 | ||||
-rw-r--r-- | aarch64-linux-gnu/Android.bp | 28 | ||||
-rw-r--r-- | gen_android_bp.py | 322 | ||||
-rw-r--r-- | x86_64-linux-gnu/Android.bp | 40 |
4 files changed, 387 insertions, 81 deletions
@@ -1,6 +1,6 @@ -// Autogenerated via gen_android_bp.sh +// Autogenerated via gen_android_bp.py // -// Copyright (C) 2019 The Android Open Source Project +// Copyright (C) 2023 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,14 +26,6 @@ cc_prebuilt_binary { check_elf_files: false, } cc_prebuilt_binary { - name: "aarch64_linux_gnu_gfxstream_graphics_detector_for_crosvm", - srcs: ["aarch64-linux-gnu/bin/gfxstream_graphics_detector"], - stem: "gfxstream_graphics_detector", - relative_install_path: "aarch64-linux-gnu", - defaults: ["cuttlefish_host"], - check_elf_files: false, -} -cc_prebuilt_binary { name: "aarch64_linux_gnu_libdrm.so.2_for_crosvm", srcs: ["aarch64-linux-gnu/bin/libdrm.so.2"], stem: "libdrm.so.2", @@ -97,6 +89,18 @@ cc_prebuilt_binary { defaults: ["cuttlefish_host"], check_elf_files: false, } +prebuilt_usr_share_host { + name: "x86_64_efi-virtio.rom_resource_for_qemu", + src: "qemu/x86_64-linux-gnu/usr/share/qemu/efi-virtio.rom", + filename: "efi-virtio.rom", + sub_dir: "qemu", +} +prebuilt_usr_share_host { + name: "x86_64_en-us_resource_for_qemu", + src: "qemu/x86_64-linux-gnu/usr/share/qemu/keymaps/en-us", + filename: "en-us", + sub_dir: "qemu/keymaps", +} // Note: This is commented out to avoid a conflict with the binary built // from external/crosvm. This should be uncommented out when backporting to // older branches with just use the prebuilt and which do not build from @@ -110,10 +114,9 @@ cc_prebuilt_binary { // check_elf_files: false, // } cc_prebuilt_binary { - name: "x86_64_linux_gnu_gfxstream_graphics_detector_for_crosvm", - srcs: ["x86_64-linux-gnu/bin/gfxstream_graphics_detector"], - stem: "gfxstream_graphics_detector", - relative_install_path: "x86_64-linux-gnu", + name: "x86_64_linux_gnu_libc++.so.1_binary_for_qemu", + srcs: ["qemu/x86_64-linux-gnu/bin/libc++.so.1"], + stem: "libc++.so.1", defaults: ["cuttlefish_host"], check_elf_files: false, } @@ -150,6 +153,13 @@ cc_prebuilt_binary { check_elf_files: false, } cc_prebuilt_binary { + name: "x86_64_linux_gnu_libgfxstream_backend.so.0_binary_for_qemu", + srcs: ["qemu/x86_64-linux-gnu/bin/libgfxstream_backend.so.0"], + stem: "libgfxstream_backend.so.0", + defaults: ["cuttlefish_host"], + check_elf_files: false, +} +cc_prebuilt_binary { name: "x86_64_linux_gnu_libgfxstream_backend.so_for_crosvm", srcs: ["x86_64-linux-gnu/bin/libgfxstream_backend.so"], stem: "libgfxstream_backend.so", @@ -166,6 +176,13 @@ cc_prebuilt_binary { check_elf_files: false, } cc_prebuilt_binary { + name: "x86_64_linux_gnu_librutabaga_gfx_ffi.so.0_binary_for_qemu", + srcs: ["qemu/x86_64-linux-gnu/bin/librutabaga_gfx_ffi.so.0"], + stem: "librutabaga_gfx_ffi.so.0", + defaults: ["cuttlefish_host"], + check_elf_files: false, +} +cc_prebuilt_binary { name: "x86_64_linux_gnu_libvirglrenderer.so.1_for_crosvm", srcs: ["x86_64-linux-gnu/bin/libvirglrenderer.so.1"], stem: "libvirglrenderer.so.1", @@ -182,27 +199,6 @@ cc_prebuilt_binary { check_elf_files: false, } cc_prebuilt_binary { - name: "x86_64_linux_gnu_libc++.so.1_binary_for_qemu", - srcs: ["qemu/x86_64-linux-gnu/bin/libc++.so.1"], - stem: "libc++.so.1", - defaults: ["cuttlefish_host"], - check_elf_files: false, -} -cc_prebuilt_binary { - name: "x86_64_linux_gnu_libgfxstream_backend.so.0_binary_for_qemu", - srcs: ["qemu/x86_64-linux-gnu/bin/libgfxstream_backend.so.0"], - stem: "libgfxstream_backend.so.0", - defaults: ["cuttlefish_host"], - check_elf_files: false, -} -cc_prebuilt_binary { - name: "x86_64_linux_gnu_librutabaga_gfx_ffi.so.0_binary_for_qemu", - srcs: ["qemu/x86_64-linux-gnu/bin/librutabaga_gfx_ffi.so.0"], - stem: "librutabaga_gfx_ffi.so.0", - defaults: ["cuttlefish_host"], - check_elf_files: false, -} -cc_prebuilt_binary { name: "x86_64_linux_gnu_libz.so.1_binary_for_qemu", srcs: ["qemu/x86_64-linux-gnu/bin/libz.so.1"], stem: "libz.so.1", @@ -231,18 +227,6 @@ cc_prebuilt_binary { check_elf_files: false, } prebuilt_usr_share_host { - name: "x86_64_efi-virtio.rom_resource_for_qemu", - src: "qemu/x86_64-linux-gnu/usr/share/qemu/efi-virtio.rom", - filename: "efi-virtio.rom", - sub_dir: "qemu", -} -prebuilt_usr_share_host { - name: "x86_64_en-us_resource_for_qemu", - src: "qemu/x86_64-linux-gnu/usr/share/qemu/keymaps/en-us", - filename: "en-us", - sub_dir: "qemu/keymaps", -} -prebuilt_usr_share_host { name: "x86_64_opensbi-riscv64-generic-fw_dynamic.bin_resource_for_qemu", src: "qemu/x86_64-linux-gnu/usr/share/qemu/opensbi-riscv64-generic-fw_dynamic.bin", filename: "opensbi-riscv64-generic-fw_dynamic.bin", diff --git a/aarch64-linux-gnu/Android.bp b/aarch64-linux-gnu/Android.bp index baaf57b..626a9ab 100644 --- a/aarch64-linux-gnu/Android.bp +++ b/aarch64-linux-gnu/Android.bp @@ -1,6 +1,6 @@ -// Autogenerated via gen_android_bp.sh +// Autogenerated via gen_android_bp.py // -// Copyright (C) 2019 The Android Open Source Project +// Copyright (C) 2023 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -117,18 +117,18 @@ prebuilt_usr_share_host { sub_dir: "cuttlefish/aarch64-linux-gnu/seccomp", } prebuilt_usr_share_host { - name: "serial_device.policy_at_aarch64", - src: "etc/seccomp/serial_device.policy", - filename: "serial_device.policy", - sub_dir: "cuttlefish/aarch64-linux-gnu/seccomp", -} -prebuilt_usr_share_host { name: "serial.policy_at_aarch64", src: "etc/seccomp/serial.policy", filename: "serial.policy", sub_dir: "cuttlefish/aarch64-linux-gnu/seccomp", } prebuilt_usr_share_host { + name: "serial_device.policy_at_aarch64", + src: "etc/seccomp/serial_device.policy", + filename: "serial_device.policy", + sub_dir: "cuttlefish/aarch64-linux-gnu/seccomp", +} +prebuilt_usr_share_host { name: "snd_cras_device.policy_at_aarch64", src: "etc/seccomp/snd_cras_device.policy", filename: "snd_cras_device.policy", @@ -189,14 +189,14 @@ prebuilt_usr_share_host { sub_dir: "cuttlefish/aarch64-linux-gnu/seccomp", } prebuilt_usr_share_host { - name: "xhci_device.policy_at_aarch64", - src: "etc/seccomp/xhci_device.policy", - filename: "xhci_device.policy", - sub_dir: "cuttlefish/aarch64-linux-gnu/seccomp", -} -prebuilt_usr_share_host { name: "xhci.policy_at_aarch64", src: "etc/seccomp/xhci.policy", filename: "xhci.policy", sub_dir: "cuttlefish/aarch64-linux-gnu/seccomp", } +prebuilt_usr_share_host { + name: "xhci_device.policy_at_aarch64", + src: "etc/seccomp/xhci_device.policy", + filename: "xhci_device.policy", + sub_dir: "cuttlefish/aarch64-linux-gnu/seccomp", +} diff --git a/gen_android_bp.py b/gen_android_bp.py new file mode 100644 index 0000000..91aba12 --- /dev/null +++ b/gen_android_bp.py @@ -0,0 +1,322 @@ +# Copyright (C) 2023 The Android Open Source Project +# +# 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. +""" +This script enumerates pre-built resources and updates Android.bp files: + + - $ANDROID_BUILD_TOP/device/google/cuttlefish_vmm/Android.bp + - $ANDROID_BUILD_TOP/device/google/cuttlefish_vmm/$ARCH/Android.bp + - $ANDROID_BUILD_TOP/device/google/cuttlefish/Android.bp + +It is intended to be run manually: + + python3 $ANDROID_BUILD_TOP/device/google/cuttlefish_vmm/gen_android_bp.py + +""" +import datetime +import os +import re +import sys +import textwrap +from dataclasses import dataclass +from enum import auto +from enum import Enum +from pathlib import Path +from typing import Dict +from typing import List +from typing import Iterator +from typing import TypeAlias + + +def tool_name() -> str: + """Returns a short name for this generation tool.""" + return Path(__file__).name + + +class Architecture(Enum): + """Host instruction set architectures.""" + + AARCH64 = auto() + X86_64 = auto() + + def dir(self) -> Path: + "Returns the relative directory path to the specified architecture." + return Path(f"{self.name.lower()}-linux-gnu") + + +# Android.bp variant value type. +Value: TypeAlias = str | Path | bool | list["Value"] + + +def value_to_bp(value: Value) -> str: + """Returns `bp` expression for the specified value""" + if isinstance(value, list): + if len(value) == 1: + return "[%s]" % value_to_bp(value[0]) + return "[\n %s,\n]" % ",\n ".join(value_to_bp(e) for e in value) + elif isinstance(value, bool): + return str(value).lower() + elif isinstance(value, Path): + return value_to_bp(str(value)) + else: + return f'"{value}"' + + +@dataclass +class Module: + """Android bp build rule.""" + + module_type: str + parameters: Dict[str, Value] + + @property + def name(self) -> str: + assert isinstance(self.parameters.get("name"), str) + return self.parameters["name"] + + def __str__(self) -> str: + """Returns a `.bp` string for this modules with its parameters.""" + body = "\n ".join( + f"{k}: {value_to_bp(v)}," for k, v in self.parameters.items() + ) + return f"{self.module_type} {{\n {body}\n}}\n" + + +def update_generated_section(file_path: Path, tag: str, content: str): + """Reads a text file, matches and replaces the content between + a start beacon and an end beacon with the specified one, and + modifies the file in place. + + The generated content is delimited by `// Start of generated` and + `// End of generated`. The specified content is indented the same + way as the start beacon is. + + Args: + file_path: path to the text file to be modified. + tag: marks the beginning aned end of the string generated content. + content: text to replace the content between the start and end beacons with. + """ + # Read the contents of the text file. + with open(file_path, "rt", encoding="utf-8") as f: + file_contents = f.read() + + # Find the start and end beacon positions in the file contents. + start = f"// Start of generated {tag}\n" + end = f"// End of generated {tag}\n" + + match = re.match( + f"^(?P<head>.*)^(?P<indent>[ \t]*){re.escape(start)}.*{re.escape(end)}(?P<tail>.*)$", + file_contents, + re.DOTALL | re.MULTILINE, + ) + if not match: + raise ValueError( + f"Generated content beacons {(start, end)} not matched in file {file_path}" + ) + + with open(file_path, "wt", encoding="utf-8") as f: + f.write(f"{match.group('head')}{match.group('indent')}{start}") + f.write(f"{match.group('indent')}// Generated by {tool_name()}\n") + f.write(textwrap.indent(content, match.group("indent"))) + f.write(f"{match.group('indent')}{end}{match.group('tail')}") + + +def license() -> str: + """Returns a license header at the current date, with generation warning.""" + current_year = datetime.datetime.now().year + return textwrap.dedent( + f"""\ + // Autogenerated via {tool_name()} + // + // Copyright (C) {current_year} The Android Open Source Project + // + // 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. + + """ + ) + + +def comment(text: str) -> str: + """Prefixes each lines with '/// ' and return the commented content.""" + return re.sub("^(?!$)", "// ", text, flags=re.MULTILINE) + + +def gen_android_bp4seccomp(path: Path, arch: Architecture): + """Regenerates the specified '.bp' file for the given architecture.""" + + with open(path, "wt") as out: + subdir = Path("etc/seccomp") + seccomp_dir = arch.dir() / subdir + where_in_etc_on_user_machine = "cuttlefish" / arch.dir() / "seccomp" + out.write(license()) + + for path in sorted(seccomp_dir.iterdir()): + module = Module( + "prebuilt_usr_share_host", + dict( + name=f"{path.name}_at_{arch.name.lower()}", + src=subdir / path.name, + filename=path.name, + sub_dir=where_in_etc_on_user_machine, + ), + ) + out.write(str(module)) + + +def crosvm_binaries(arch: Architecture) -> Iterator[Path]: + """Lists crosvm binary paths.""" + dir = arch.dir() / "bin" + yield dir / "crosvm" + yield dir / "libminijail.so" + yield dir / "libgfxstream_backend.so" + yield from dir.glob("*.so.?") + + +def qemu_binaries(arch: Architecture) -> Iterator[Path]: + """Lists qemu binary paths.""" + dir = Path("qemu/x86_64-linux-gnu/bin") + yield from dir.glob("*.so.?") + yield from dir.glob("qemu-system*") + + +def gen_main_android_bp_modules() -> Iterator[Module]: + """Returns the Modules to write in the main 'Android.bp' file.""" + for arch in Architecture: + for path in crosvm_binaries(arch): + name = re.sub("/bin/|/|-|_bin_", "_", str(path)) + if path.stem != "crosvm": + name = f"{name}_for_crosvm" + + yield Module( + "cc_prebuilt_binary", + dict( + name=name, + srcs=[path], + stem=path.name, + relative_install_path=arch.dir(), + defaults=["cuttlefish_host"], + check_elf_files=False, + ), + ) + + for binary_path in qemu_binaries(Architecture.X86_64): + yield Module( + "cc_prebuilt_binary", + dict( + name=f"x86_64_linux_gnu_{binary_path.name}_binary_for_qemu", + srcs=[binary_path], + stem=binary_path.name, + defaults=["cuttlefish_host"], + check_elf_files=False, + ), + ) + + resource_paths = [ + Path("qemu/efi-virtio.rom"), + Path("qemu/keymaps/en-us"), + Path("qemu/opensbi-riscv64-generic-fw_dynamic.bin"), + ] + + for resource_path in resource_paths: + base_name = resource_path.name + arch = "x86_64" + sub_dir = resource_path.parent + yield Module( + "prebuilt_usr_share_host", + dict( + name=f"{arch}_{base_name}_resource_for_qemu", + src=f"qemu/x86_64-linux-gnu/usr/share/{resource_path}", + filename=base_name, + sub_dir=sub_dir, + ), + ) + + +def gen_main_android_bp_file(android_bp_path: Path, modules: List[Module]): + """Writes the main 'Android.bp' file with the specified modules.""" + + disclamer = f"""\ + // NOTE: Using cc_prebuilt_binary because cc_prebuilt_library will add + // unwanted .so file extensions when installing shared libraries + + """ + crosvm_comment = """\ + // Note: This is commented out to avoid a conflict with the binary built + // from external/crosvm. This should be uncommented out when backporting to + // older branches with just use the prebuilt and which do not build from + // source. + """ + + with open(android_bp_path, "wt") as out: + out.write(license()) + out.write(textwrap.dedent(disclamer)) + + sort_key = lambda m: ( + m.name, + m.parameters["name"].rsplit("_")[-1], + m.parameters["name"], + ) + for module in sorted(modules, key=sort_key): + module_text = str(module) + if module.parameters["name"] == "x86_64_linux_gnu_crosvm": + out.write(textwrap.dedent(crosvm_comment)) + module_text = comment(module_text) + out.write(module_text) + + +def generate_all_cuttlefish_host_package_android_bp(path: Path, modules: list[Module]): + """Updates the list of module in 'device/google/cuttlefish/Android.bp'.""" + + qemu_binaries = [m for m in modules if m.name.endswith("_binary_for_qemu")] + qemu_resources = [m for m in modules if m.name.endswith("_resource_for_qemu")] + + def update_list(list_name: str, modules:list[Module]): + names = sorted(m.parameters["name"] for m in modules) + text = f"{list_name} = {value_to_bp(names)}\n" + update_generated_section(path, list_name, text) + + update_list("qemu_x86_64_linux_gnu_binary", qemu_binaries) + update_list("qemu_x86_64_linux_gnu_resource", qemu_resources) + + +def main(argv): + if len(argv) != 1: + print(f"Usage error: {argv[0]} does not accept any argument.") + return 1 + + # Set the current directory to the script location. + os.chdir(Path(__file__).parent) + + modules = list(gen_main_android_bp_modules()) + gen_main_android_bp_file(Path("Android.bp"), modules) + + generate_all_cuttlefish_host_package_android_bp( + Path("../cuttlefish/build/Android.bp"), modules + ) + + for arch in Architecture: + gen_android_bp4seccomp(arch.dir() / "Android.bp", arch) + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/x86_64-linux-gnu/Android.bp b/x86_64-linux-gnu/Android.bp index 8de52b0..9968d58 100644 --- a/x86_64-linux-gnu/Android.bp +++ b/x86_64-linux-gnu/Android.bp @@ -1,6 +1,6 @@ -// Autogenerated via gen_android_bp.sh +// Autogenerated via gen_android_bp.py // -// Copyright (C) 2019 The Android Open Source Project +// Copyright (C) 2023 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -51,18 +51,18 @@ prebuilt_usr_share_host { sub_dir: "cuttlefish/x86_64-linux-gnu/seccomp", } prebuilt_usr_share_host { - name: "coiommu_device.policy_at_x86_64", - src: "etc/seccomp/coiommu_device.policy", - filename: "coiommu_device.policy", - sub_dir: "cuttlefish/x86_64-linux-gnu/seccomp", -} -prebuilt_usr_share_host { name: "coiommu.policy_at_x86_64", src: "etc/seccomp/coiommu.policy", filename: "coiommu.policy", sub_dir: "cuttlefish/x86_64-linux-gnu/seccomp", } prebuilt_usr_share_host { + name: "coiommu_device.policy_at_x86_64", + src: "etc/seccomp/coiommu_device.policy", + filename: "coiommu_device.policy", + sub_dir: "cuttlefish/x86_64-linux-gnu/seccomp", +} +prebuilt_usr_share_host { name: "common_device.policy_at_x86_64", src: "etc/seccomp/common_device.policy", filename: "common_device.policy", @@ -159,6 +159,12 @@ prebuilt_usr_share_host { sub_dir: "cuttlefish/x86_64-linux-gnu/seccomp", } prebuilt_usr_share_host { + name: "serial.policy_at_x86_64", + src: "etc/seccomp/serial.policy", + filename: "serial.policy", + sub_dir: "cuttlefish/x86_64-linux-gnu/seccomp", +} +prebuilt_usr_share_host { name: "serial_device.policy_at_x86_64", src: "etc/seccomp/serial_device.policy", filename: "serial_device.policy", @@ -177,12 +183,6 @@ prebuilt_usr_share_host { sub_dir: "cuttlefish/x86_64-linux-gnu/seccomp", } prebuilt_usr_share_host { - name: "serial.policy_at_x86_64", - src: "etc/seccomp/serial.policy", - filename: "serial.policy", - sub_dir: "cuttlefish/x86_64-linux-gnu/seccomp", -} -prebuilt_usr_share_host { name: "snd_cras_device.policy_at_x86_64", src: "etc/seccomp/snd_cras_device.policy", filename: "snd_cras_device.policy", @@ -267,14 +267,14 @@ prebuilt_usr_share_host { sub_dir: "cuttlefish/x86_64-linux-gnu/seccomp", } prebuilt_usr_share_host { - name: "xhci_device.policy_at_x86_64", - src: "etc/seccomp/xhci_device.policy", - filename: "xhci_device.policy", - sub_dir: "cuttlefish/x86_64-linux-gnu/seccomp", -} -prebuilt_usr_share_host { name: "xhci.policy_at_x86_64", src: "etc/seccomp/xhci.policy", filename: "xhci.policy", sub_dir: "cuttlefish/x86_64-linux-gnu/seccomp", } +prebuilt_usr_share_host { + name: "xhci_device.policy_at_x86_64", + src: "etc/seccomp/xhci_device.policy", + filename: "xhci_device.policy", + sub_dir: "cuttlefish/x86_64-linux-gnu/seccomp", +} |