xref: /aosp_15_r20/development/tools/ndk/ndkabidump/__init__.py (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1*90c8c64dSAndroid Build Coastguard Worker#
2*90c8c64dSAndroid Build Coastguard Worker# Copyright (C) 2021 The Android Open Source Project
3*90c8c64dSAndroid Build Coastguard Worker#
4*90c8c64dSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*90c8c64dSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*90c8c64dSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*90c8c64dSAndroid Build Coastguard Worker#
8*90c8c64dSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*90c8c64dSAndroid Build Coastguard Worker#
10*90c8c64dSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*90c8c64dSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
12*90c8c64dSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*90c8c64dSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*90c8c64dSAndroid Build Coastguard Worker# limitations under the License.
15*90c8c64dSAndroid Build Coastguard Worker#
16*90c8c64dSAndroid Build Coastguard Worker"""Tool for updating the prebuilt NDK ABI dumps."""
17*90c8c64dSAndroid Build Coastguard Workerimport argparse
18*90c8c64dSAndroid Build Coastguard Workerimport logging
19*90c8c64dSAndroid Build Coastguard Workerfrom pathlib import Path
20*90c8c64dSAndroid Build Coastguard Workerimport shutil
21*90c8c64dSAndroid Build Coastguard Workerimport sys
22*90c8c64dSAndroid Build Coastguard Worker
23*90c8c64dSAndroid Build Coastguard Workerfrom .soong import Soong
24*90c8c64dSAndroid Build Coastguard Worker
25*90c8c64dSAndroid Build Coastguard Worker
26*90c8c64dSAndroid Build Coastguard Workerdef logger() -> logging.Logger:
27*90c8c64dSAndroid Build Coastguard Worker    """Returns the module level logger."""
28*90c8c64dSAndroid Build Coastguard Worker    return logging.getLogger(__name__)
29*90c8c64dSAndroid Build Coastguard Worker
30*90c8c64dSAndroid Build Coastguard Worker
31*90c8c64dSAndroid Build Coastguard Workerclass Updater:
32*90c8c64dSAndroid Build Coastguard Worker    """Tool for updating prebuilt NDK ABI dumps."""
33*90c8c64dSAndroid Build Coastguard Worker
34*90c8c64dSAndroid Build Coastguard Worker    def __init__(self, src_dir: Path, build_dir: Path) -> None:
35*90c8c64dSAndroid Build Coastguard Worker        self.src_dir = src_dir
36*90c8c64dSAndroid Build Coastguard Worker        self.build_dir = build_dir
37*90c8c64dSAndroid Build Coastguard Worker
38*90c8c64dSAndroid Build Coastguard Worker    def build_abi_dumps(self) -> None:
39*90c8c64dSAndroid Build Coastguard Worker        """Builds the updated NDK ABI dumps."""
40*90c8c64dSAndroid Build Coastguard Worker        soong = Soong(self.src_dir, self.build_dir)
41*90c8c64dSAndroid Build Coastguard Worker        logger().info(f"Building ABI dumps to {self.build_dir}")
42*90c8c64dSAndroid Build Coastguard Worker        soong.build(
43*90c8c64dSAndroid Build Coastguard Worker            ["dump-ndk-abi"],
44*90c8c64dSAndroid Build Coastguard Worker            env={
45*90c8c64dSAndroid Build Coastguard Worker                "TARGET_PRODUCT": "ndk",
46*90c8c64dSAndroid Build Coastguard Worker                "TARGET_RELEASE": "trunk_staging",
47*90c8c64dSAndroid Build Coastguard Worker                # TODO: remove ALLOW_MISSING_DEPENDENCIES=true when all the
48*90c8c64dSAndroid Build Coastguard Worker                # riscv64 dependencies exist (currently blocked by
49*90c8c64dSAndroid Build Coastguard Worker                # http://b/273792258).
50*90c8c64dSAndroid Build Coastguard Worker                "ALLOW_MISSING_DEPENDENCIES": "true",
51*90c8c64dSAndroid Build Coastguard Worker                # TODO: remove BUILD_BROKEN_DISABLE_BAZEL=1 when bazel supports
52*90c8c64dSAndroid Build Coastguard Worker                # riscv64 (http://b/262192655).
53*90c8c64dSAndroid Build Coastguard Worker                "BUILD_BROKEN_DISABLE_BAZEL": "1",
54*90c8c64dSAndroid Build Coastguard Worker            },
55*90c8c64dSAndroid Build Coastguard Worker        )
56*90c8c64dSAndroid Build Coastguard Worker
57*90c8c64dSAndroid Build Coastguard Worker    def copy_updated_abi_dumps(self) -> None:
58*90c8c64dSAndroid Build Coastguard Worker        """Copies the NDK ABI dumps from the build directory to prebuilts."""
59*90c8c64dSAndroid Build Coastguard Worker        prebuilts_project = self.src_dir / "prebuilts/abi-dumps"
60*90c8c64dSAndroid Build Coastguard Worker        prebuilts_dir = prebuilts_project / "ndk"
61*90c8c64dSAndroid Build Coastguard Worker        abi_out = self.build_dir / "soong/abi-dumps/ndk"
62*90c8c64dSAndroid Build Coastguard Worker        for version_dir in abi_out.iterdir():
63*90c8c64dSAndroid Build Coastguard Worker            try:
64*90c8c64dSAndroid Build Coastguard Worker                int(version_dir.name)
65*90c8c64dSAndroid Build Coastguard Worker            except ValueError:
66*90c8c64dSAndroid Build Coastguard Worker                logger().info("Skipping %s because it is a preview API level", version_dir)
67*90c8c64dSAndroid Build Coastguard Worker                continue
68*90c8c64dSAndroid Build Coastguard Worker
69*90c8c64dSAndroid Build Coastguard Worker            for dump in version_dir.glob("**/abi.stg"):
70*90c8c64dSAndroid Build Coastguard Worker                install_path = prebuilts_dir / dump.relative_to(abi_out)
71*90c8c64dSAndroid Build Coastguard Worker                install_dir = install_path.parent
72*90c8c64dSAndroid Build Coastguard Worker                if not install_dir.exists():
73*90c8c64dSAndroid Build Coastguard Worker                    install_dir.mkdir(parents=True)
74*90c8c64dSAndroid Build Coastguard Worker                logger().info(f"Copying ABI dump {dump} to {install_path}")
75*90c8c64dSAndroid Build Coastguard Worker                shutil.copy2(dump, install_path)
76*90c8c64dSAndroid Build Coastguard Worker
77*90c8c64dSAndroid Build Coastguard Worker    def run(self) -> None:
78*90c8c64dSAndroid Build Coastguard Worker        """Runs the updater.
79*90c8c64dSAndroid Build Coastguard Worker
80*90c8c64dSAndroid Build Coastguard Worker        Cleans the out directory, builds the ABI dumps, and copies the results
81*90c8c64dSAndroid Build Coastguard Worker        to the prebuilts directory.
82*90c8c64dSAndroid Build Coastguard Worker        """
83*90c8c64dSAndroid Build Coastguard Worker        self.build_abi_dumps()
84*90c8c64dSAndroid Build Coastguard Worker        self.copy_updated_abi_dumps()
85*90c8c64dSAndroid Build Coastguard Worker
86*90c8c64dSAndroid Build Coastguard Worker
87*90c8c64dSAndroid Build Coastguard WorkerHELP = """\
88*90c8c64dSAndroid Build Coastguard WorkerBuilds and updates the NDK ABI prebuilts.
89*90c8c64dSAndroid Build Coastguard Worker
90*90c8c64dSAndroid Build Coastguard WorkerWhenever a change is made that alters the NDK ABI (or an API level is
91*90c8c64dSAndroid Build Coastguard Workerfinalized, or a new preview codename is introduced to the build), the prebuilts
92*90c8c64dSAndroid Build Coastguard Workerin prebuilts/abi-dumps/ndk need to be updated to match. For any finalized APIs,
93*90c8c64dSAndroid Build Coastguard Workerthe breaking change typically needs to be reverted.
94*90c8c64dSAndroid Build Coastguard Worker
95*90c8c64dSAndroid Build Coastguard WorkerNote that typically this tool should be executed via
96*90c8c64dSAndroid Build Coastguard Workerdevelopment/tools/ndk/update_ndk_abi.sh. That script will ensure that this tool
97*90c8c64dSAndroid Build Coastguard Workeris up-to-date and run with the correct arguments.
98*90c8c64dSAndroid Build Coastguard Worker"""
99*90c8c64dSAndroid Build Coastguard Worker
100*90c8c64dSAndroid Build Coastguard Worker
101*90c8c64dSAndroid Build Coastguard Workerclass App:
102*90c8c64dSAndroid Build Coastguard Worker    """Command line application from updating NDK ABI prebuilts."""
103*90c8c64dSAndroid Build Coastguard Worker
104*90c8c64dSAndroid Build Coastguard Worker    @staticmethod
105*90c8c64dSAndroid Build Coastguard Worker    def parse_args() -> argparse.Namespace:
106*90c8c64dSAndroid Build Coastguard Worker        """Parses and returns command line arguments."""
107*90c8c64dSAndroid Build Coastguard Worker
108*90c8c64dSAndroid Build Coastguard Worker        parser = argparse.ArgumentParser(
109*90c8c64dSAndroid Build Coastguard Worker            formatter_class=argparse.RawDescriptionHelpFormatter, description=HELP
110*90c8c64dSAndroid Build Coastguard Worker        )
111*90c8c64dSAndroid Build Coastguard Worker
112*90c8c64dSAndroid Build Coastguard Worker        def resolved_path(path: str) -> Path:
113*90c8c64dSAndroid Build Coastguard Worker            """Converts a string into a fully resolved Path."""
114*90c8c64dSAndroid Build Coastguard Worker            return Path(path).resolve()
115*90c8c64dSAndroid Build Coastguard Worker
116*90c8c64dSAndroid Build Coastguard Worker        parser.add_argument(
117*90c8c64dSAndroid Build Coastguard Worker            "--src-dir",
118*90c8c64dSAndroid Build Coastguard Worker            type=resolved_path,
119*90c8c64dSAndroid Build Coastguard Worker            required=True,
120*90c8c64dSAndroid Build Coastguard Worker            help="Path to the top of the Android source tree.",
121*90c8c64dSAndroid Build Coastguard Worker        )
122*90c8c64dSAndroid Build Coastguard Worker
123*90c8c64dSAndroid Build Coastguard Worker        parser.add_argument(
124*90c8c64dSAndroid Build Coastguard Worker            "out_dir",
125*90c8c64dSAndroid Build Coastguard Worker            type=resolved_path,
126*90c8c64dSAndroid Build Coastguard Worker            metavar="OUT_DIR",
127*90c8c64dSAndroid Build Coastguard Worker            help="Output directory to use for building ABI dumps.",
128*90c8c64dSAndroid Build Coastguard Worker        )
129*90c8c64dSAndroid Build Coastguard Worker
130*90c8c64dSAndroid Build Coastguard Worker        parser.add_argument(
131*90c8c64dSAndroid Build Coastguard Worker            "-v",
132*90c8c64dSAndroid Build Coastguard Worker            "--verbose",
133*90c8c64dSAndroid Build Coastguard Worker            action="count",
134*90c8c64dSAndroid Build Coastguard Worker            default=0,
135*90c8c64dSAndroid Build Coastguard Worker            help="Increase logging verbosity.",
136*90c8c64dSAndroid Build Coastguard Worker        )
137*90c8c64dSAndroid Build Coastguard Worker
138*90c8c64dSAndroid Build Coastguard Worker        return parser.parse_args()
139*90c8c64dSAndroid Build Coastguard Worker
140*90c8c64dSAndroid Build Coastguard Worker    def run(self) -> None:
141*90c8c64dSAndroid Build Coastguard Worker        """Builds the new NDK ABI dumps and copies them to prebuilts."""
142*90c8c64dSAndroid Build Coastguard Worker        args = self.parse_args()
143*90c8c64dSAndroid Build Coastguard Worker        log_level = logging.DEBUG if args.verbose else logging.INFO
144*90c8c64dSAndroid Build Coastguard Worker        logging.basicConfig(level=log_level)
145*90c8c64dSAndroid Build Coastguard Worker        test_path = args.src_dir / "build/soong/soong_ui.bash"
146*90c8c64dSAndroid Build Coastguard Worker        if not test_path.exists():
147*90c8c64dSAndroid Build Coastguard Worker            sys.exit(
148*90c8c64dSAndroid Build Coastguard Worker                f"Source directory {args.src_dir} does not appear to be an "
149*90c8c64dSAndroid Build Coastguard Worker                f"Android source tree: {test_path} does not exist."
150*90c8c64dSAndroid Build Coastguard Worker            )
151*90c8c64dSAndroid Build Coastguard Worker
152*90c8c64dSAndroid Build Coastguard Worker        Updater(args.src_dir, args.out_dir).run()
153