From da15679d6ece2a390dd1f34a19517c399bc916a4 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Fri, 14 Feb 2025 18:09:04 +0900 Subject: [PATCH] Also download Android NDK in `update_deps.py` This is a preparation before removing the dependency on Docker from our Android build instructions (#1181). With this commit running the `update_deps.py` also downloads Android NDK for macOS and Linux then extract it under third_party/ndk/. This would enable us to fully control which version of Android NDK should be used to build Android Library ('libmozc.so') in a subsequent commit. At this moment only the observable difference is that the Android NDK will be extracted under third_party/ndk/. There must be no difference in the final artifact yet. --- .gitignore | 1 + src/build_tools/update_deps.py | 85 +++++++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 30098582c..04f62b9ed 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ MODULE.bazel.lock .DS_Store # third_party dirs and cache dir checked out by update_deps.py +/src/third_party/ndk/ /src/third_party/ninja/ /src/third_party/qt/ /src/third_party/qt_host/ diff --git a/src/build_tools/update_deps.py b/src/build_tools/update_deps.py index 1d00b2084..bffce28b3 100644 --- a/src/build_tools/update_deps.py +++ b/src/build_tools/update_deps.py @@ -39,6 +39,7 @@ import hashlib import os import pathlib +import shutil import stat import subprocess import sys @@ -84,6 +85,18 @@ def __hash__(self): sha256='1bad481710aa27f872de6c9f72651f89a6107f0077003d0ebfcc9fd15cba3c75', ) +NDK_LINUX = ArchiveInfo( + url='https://dl.google.com/android/repository/android-ndk-r28-linux.zip', + size=723148067, + sha256='a186b67e8810cb949514925e4f7a2255548fb55f5e9b0824a6430d012c1b695b', +) + +NDK_MAC = ArchiveInfo( + url='https://dl.google.com/android/repository/android-ndk-r28-darwin.zip', + size=950413046, + sha256='19b16241e8e8d4c8e4f3729b8a0a625dd240394e1f1cd072596df891317e22a9', +) + NINJA_MAC = ArchiveInfo( url='https://github.com/ninja-build/ninja/releases/download/v1.11.0/ninja-mac.zip', size=277298, @@ -255,6 +268,38 @@ def extract_ninja(dryrun: bool = False) -> None: ninja.chmod(ninja.stat().st_mode | stat.S_IXUSR) +def extract_ndk(archive: ArchiveInfo, dryrun: bool = False) -> None: + """Extract Android NDK archive. + + Args: + archive: Android NDK archive + dryrun: True if this is a dry-run. + """ + dest = ABS_THIRD_PARTY_DIR.joinpath('ndk').absolute() + src = CACHE_DIR.joinpath(archive.filename) + + if dest.exists(): + if dryrun: + print(f"dryrun: shutil.rmtree(r'{dest}')") + else: + shutil.rmtree(dest) + + if dryrun: + print(f"dryrun: mkdir -p '{dest}')") + else: + dest.mkdir(parents=True, exist_ok=True) + + # Python's zipfile doesn't support symlink. + # We have to fallback to unzip command here. + args = ['unzip', str(src)] + + if dryrun: + print(f'dryrun: exec_command({args}, cwd={dest})') + else: + exec_command(args, cwd=dest, progress=True) + return + + def is_windows() -> bool: """Returns true if the platform is Windows.""" return os.name == 'nt' @@ -265,6 +310,11 @@ def is_mac() -> bool: return os.name == 'posix' and os.uname()[0] == 'Darwin' +def is_linux() -> bool: + """Returns true if the platform is Linux.""" + return os.name == 'posix' and os.uname()[0] == 'Linux' + + def update_submodules(dryrun: bool = False) -> None: """Run 'git submodule update --init --recursive'. @@ -278,17 +328,38 @@ def update_submodules(dryrun: bool = False) -> None: subprocess.run(command, shell=True, check=True) -def exec_command(args: list[str], cwd: os.PathLike[str]) -> None: +def exec_command( + args: list[str], cwd: os.PathLike[str], progress: bool = False +) -> None: """Runs the given command then returns the output. Args: args: The command to be executed. cwd: The working directory to execute the command. + progress: True to show progress. Raises: ChildProcessError: When the given command cannot be executed. """ - process = subprocess.Popen(args, stdout=subprocess.PIPE, shell=False, cwd=cwd) + process = subprocess.Popen( + args, + cwd=cwd, + shell=False, + stdout=subprocess.PIPE, + text=True, + ) + if progress: + with ProgressPrinter() as printer: + for line in process.stdout: + line = line.strip() + printer.print_line(line) + exitcode = process.poll() + if exitcode is None: + continue + if exitcode == 0: + return + raise ChildProcessError(f'Failed to execute {args}. exitcode={exitcode}') + return _, _ = process.communicate() exitcode = process.wait() if exitcode != 0: @@ -314,6 +385,7 @@ def main(): parser.add_argument('--noninja', action='store_true', default=False) parser.add_argument('--noqt', action='store_true', default=False) parser.add_argument('--nowix', action='store_true', default=False) + parser.add_argument('--nondk', action='store_true', default=False) parser.add_argument('--nosubmodules', action='store_true', default=False) parser.add_argument('--cache_only', action='store_true', default=False) @@ -327,6 +399,11 @@ def main(): archives.append(NINJA_MAC) elif is_windows(): archives.append(NINJA_WIN) + if not args.nondk: + if is_linux(): + archives.append(NDK_LINUX) + elif is_mac(): + archives.append(NDK_MAC) for archive in archives: download(archive, args.dryrun) @@ -340,6 +417,10 @@ def main(): if (NINJA_WIN in archives) or (NINJA_MAC in archives): extract_ninja(args.dryrun) + for ndk in [NDK_LINUX, NDK_MAC]: + if ndk in archives: + extract_ndk(ndk, args.dryrun) + if not args.nosubmodules: update_submodules(args.dryrun)