| # |
| # Copyright (C) 2016 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. |
| # |
| """Helper functions for NDK build and test paths.""" |
| from __future__ import absolute_import |
| |
| import os |
| from pathlib import Path |
| import sys |
| from typing import Callable, Iterator, Optional |
| |
| import ndk.abis |
| import ndk.config |
| import ndk.hosts |
| |
| |
| ANDROID_DIR = Path(__file__).resolve().parents[2] |
| NDK_DIR = ANDROID_DIR / 'ndk' |
| |
| |
| def android_path(*args: str) -> str: |
| """Returns the absolute path rooted within the top level source tree.""" |
| return str(ANDROID_DIR.joinpath(*args)) |
| |
| |
| def ndk_path(*args: str) -> str: |
| """Returns the absolute path rooted within the NDK source tree.""" |
| return android_path('ndk', *args) |
| |
| |
| def sysroot_path(toolchain: ndk.abis.Toolchain) -> str: |
| """Returns the path to the prebuilt sysroot for the given toolchain.""" |
| arch = ndk.abis.toolchain_to_arch(toolchain) |
| # Only ARM has more than one ABI, and they both have the same minimum |
| # platform level. |
| abi = ndk.abis.arch_to_abis(arch)[0] |
| version = ndk.abis.min_api_for_abi(abi) |
| |
| prebuilt_ndk = 'prebuilts/ndk/current' |
| sysroot_subpath = 'platforms/android-{}/arch-{}'.format(version, arch) |
| return android_path(prebuilt_ndk, sysroot_subpath) |
| |
| |
| def toolchain_path(*args: str) -> str: |
| """Returns a path within the toolchain subdirectory.""" |
| return android_path('toolchain', *args) |
| |
| |
| def _get_dir_from_env(default: str, env_var: str) -> str: |
| """Returns the path to a directory specified by the environment. |
| |
| If the environment variable is not set, the default will be used. The |
| directory is created if it does not exist. |
| |
| Args: |
| default: The path used if the environment variable is not set. |
| env_var: The environment variable that contains the path, if any. |
| |
| Returns: |
| The absolute path to the directory. |
| """ |
| path = os.path.realpath(os.getenv(env_var, default)) |
| if not os.path.isdir(path): |
| os.makedirs(path) |
| return path |
| |
| |
| def get_out_dir() -> str: |
| """Returns the out directory.""" |
| return _get_dir_from_env(android_path('out'), 'OUT_DIR') |
| |
| |
| def get_dist_dir(out_dir: str) -> str: |
| """Returns the distribution directory. |
| |
| The contents of the distribution directory are archived on the build |
| servers. Suitable for build logs and final artifacts. |
| """ |
| return _get_dir_from_env(os.path.join(out_dir, 'dist'), 'DIST_DIR') |
| |
| |
| def path_in_out(dirname: str, out_dir: Optional[str] = None) -> str: |
| """Returns a path within the out directory." |
| |
| Args: |
| dirname: Name of the directory. |
| out_dir: Optional base out directory. Inferred from $OUT_DIR if not |
| supplied. If None and $OUT_DIR is not set, will use ../out |
| relative to the NDK git project. |
| |
| Returns: |
| Absolute path within the out directory. |
| """ |
| if out_dir is None: |
| out_dir = get_out_dir() |
| return os.path.join(out_dir, dirname) |
| |
| |
| def get_install_path(out_dir: Optional[str] = None, |
| host: Optional[ndk.hosts.Host] = None) -> str: |
| """Returns the built NDK install path. |
| |
| Note that the path returned might not actually contain the NDK. The NDK may |
| not actually be present if: |
| |
| * The NDK hasn't been built yet. |
| * The name of the release has changed since the NDK was built. |
| * out_dir is not consistent with the build. |
| |
| Args: |
| out_dir: Optional base out directory. Inferred from $OUT_DIR if not |
| supplied. |
| host: Returns the install path for th given host. |
| |
| Returns: |
| Directory that the built NDK should be installed to. |
| """ |
| if host is None: |
| host = ndk.hosts.get_default_host() |
| release_name = f'android-ndk-{ndk.config.release}' |
| return path_in_out(os.path.join(host.value, release_name), out_dir) |
| |
| |
| def to_posix_path(path: str) -> str: |
| """Replaces backslashes with forward slashes on Windows.""" |
| if sys.platform == 'win32': |
| return path.replace('\\', '/') |
| else: |
| return path |
| |
| |
| def walk(path: Path, |
| top_down: bool = True, |
| on_error: Optional[Callable[[OSError], None]] = None, |
| follow_links: bool = False, |
| directories: bool = True) -> Iterator[Path]: |
| """Recursively iterates through files in a directory. |
| |
| This is a pathlib equivalent of os.walk, which Python inexplicably still |
| does not have in the standard library. |
| |
| Args: |
| path: Directory tree to walk. |
| top_down: If True, walk the tree top-down. If False, walk the tree |
| bottom-up. |
| on_error: An error handling callback for any OSError raised by the |
| walk. |
| follow_links: If True, walk into symbolic links that resolve to |
| directories. |
| directories: If True, the walk will also yield directories. |
| Yields: |
| A Path for each file (and optionally each directory) in the same manner |
| as os.walk. |
| """ |
| for root, dirs, files in os.walk(str(path), |
| topdown=top_down, |
| onerror=on_error, |
| followlinks=follow_links): |
| root_path = Path(root) |
| if directories: |
| for dir_name in dirs: |
| yield root_path / dir_name |
| for file_name in files: |
| yield root_path / file_name |