blob: c577da80959245616fbc37887f086969b82b75cb [file] [log] [blame]
#
# Copyright (C) 2017 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.
#
"""Constants and helper functions for NDK ABIs."""
from typing import List, NewType, Optional
from .platforms import FIRST_LP64_API_LEVEL, MIN_API_LEVEL
Arch = NewType("Arch", str)
Abi = NewType("Abi", str)
Toolchain = NewType("Toolchain", str)
LP32_ABIS = (
Abi("armeabi-v7a"),
Abi("x86"),
)
LP64_ABIS = (
Abi("arm64-v8a"),
Abi("x86_64"),
)
ALL_ABIS = sorted(LP32_ABIS + LP64_ABIS)
ALL_ARCHITECTURES = (
Arch("arm"),
Arch("arm64"),
Arch("x86"),
Arch("x86_64"),
)
ALL_TOOLCHAINS = (
Toolchain("arm-linux-androideabi"),
Toolchain("aarch64-linux-android"),
Toolchain("x86"),
Toolchain("x86_64"),
)
ALL_TRIPLES = (
"arm-linux-androideabi",
"aarch64-linux-android",
"i686-linux-android",
"x86_64-linux-android",
)
def arch_to_toolchain(arch: Arch) -> Toolchain:
"""Returns the NDK toolchain name for the given architecture."""
return dict(zip(ALL_ARCHITECTURES, ALL_TOOLCHAINS))[arch]
def arch_to_triple(arch: Arch) -> str:
"""Returns the triple for the given architecture."""
return dict(zip(ALL_ARCHITECTURES, ALL_TRIPLES))[arch]
def toolchain_to_arch(toolchain: Toolchain) -> Arch:
"""Returns the architecture for the given toolchain."""
return dict(zip(ALL_TOOLCHAINS, ALL_ARCHITECTURES))[toolchain]
def arch_to_abis(arch: Arch) -> List[Abi]:
"""Returns the ABIs for the given architecture."""
return {
Arch("arm"): [Abi("armeabi-v7a")],
Arch("arm64"): [Abi("arm64-v8a")],
Arch("x86"): [Abi("x86")],
Arch("x86_64"): [Abi("x86_64")],
}[arch]
def abi_to_arch(abi: Abi) -> Arch:
"""Returns the architecture for the given ABI."""
return {
Abi("armeabi-v7a"): Arch("arm"),
Abi("arm64-v8a"): Arch("arm64"),
Abi("x86"): Arch("x86"),
Abi("x86_64"): Arch("x86_64"),
}[abi]
def clang_target(arch: Arch, api: Optional[int] = None) -> str:
"""Returns the Clang target to be used for the given arch/API combo.
Args:
arch: Architecture to compile for. 'arm' will target ARMv7.
api: API level to compile for. Defaults to the lowest supported API
level for the architecture if None.
"""
if api is None:
# Currently there is only one ABI per arch.
abis = arch_to_abis(arch)
assert len(abis) == 1
abi = abis[0]
api = min_api_for_abi(abi)
triple = arch_to_triple(arch)
if arch == "arm":
triple = "armv7a-linux-androideabi"
return f"{triple}{api}"
def min_api_for_abi(abi: Abi) -> int:
"""Returns the minimum supported build API for the given ABI.
>>> min_api_for_abi('arm64-v8a')
21
>>> min_api_for_abi('armeabi-v7a')
19
>>> min_api_for_abi('foobar')
Traceback (most recent call last):
...
ValueError: Invalid ABI: foobar
"""
if abi in LP64_ABIS:
return FIRST_LP64_API_LEVEL
if abi in LP32_ABIS:
return MIN_API_LEVEL
raise ValueError("Invalid ABI: {}".format(abi))