import os.path import shutil from typing import Union android_abis = { 'armeabi-v7a': { 'arch': 'armv7a-linux-androideabi', 'ndk_arch': 'arm', 'cflags': '-fpic -mfpu=neon -mfloat-abi=softfp', }, 'arm64-v8a': { 'arch': 'aarch64-linux-android', 'ndk_arch': 'arm64', 'cflags': '-fpic', }, 'x86': { 'arch': 'i686-linux-android', 'ndk_arch': 'x86', 'cflags': '-fPIC -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32', }, 'x86_64': { 'arch': 'x86_64-linux-android', 'ndk_arch': 'x86_64', 'cflags': '-fPIC -m64', }, } class AndroidNdkToolchain: def __init__(self, top_path: str, lib_path: str, tarball_path: str, src_path: str, ndk_path: str, android_abi: str, use_cxx): # build host configuration build_arch = 'linux-x86_64' # select the NDK target abi_info = android_abis[android_abi] host_triplet = abi_info['arch'] arch_path = os.path.join(lib_path, host_triplet) self.tarball_path = tarball_path self.src_path = src_path self.build_path = os.path.join(arch_path, 'build') ndk_arch = abi_info['ndk_arch'] android_api_level = '24' install_prefix = os.path.join(arch_path, 'root') self.host_triplet = host_triplet self.install_prefix = install_prefix llvm_path = os.path.join(ndk_path, 'toolchains', 'llvm', 'prebuilt', build_arch) llvm_triple = host_triplet + android_api_level common_flags = '-Os -g' common_flags += ' ' + abi_info['cflags'] llvm_bin = os.path.join(llvm_path, 'bin') self.cc = os.path.join(llvm_bin, 'clang') self.cxx = os.path.join(llvm_bin, 'clang++') common_flags += ' -target ' + llvm_triple common_flags += ' -fvisibility=hidden -fdata-sections -ffunction-sections' self.ar = os.path.join(llvm_bin, 'llvm-ar') self.arflags = 'rcs' self.ranlib = os.path.join(llvm_bin, 'llvm-ranlib') self.nm = os.path.join(llvm_bin, 'llvm-nm') self.strip = os.path.join(llvm_bin, 'llvm-strip') self.cflags = common_flags self.cxxflags = common_flags self.cppflags = ' -isystem ' + os.path.join(install_prefix, 'include') self.ldflags = ' -L' + os.path.join(install_prefix, 'lib') + \ ' -Wl,--exclude-libs=ALL' + \ ' ' + common_flags self.ldflags = common_flags self.libs = '' self.is_arm = ndk_arch == 'arm' self.is_armv7 = self.is_arm and 'armv7' in self.cflags self.is_aarch64 = ndk_arch == 'arm64' self.is_windows = False self.is_android = True self.is_darwin = False libstdcxx_flags = '' libstdcxx_cxxflags = '' libstdcxx_ldflags = '' libstdcxx_libs = '-static-libstdc++' if self.is_armv7: # On 32 bit ARM, clang generates no ".eh_frame" section; # instead, the LLVM unwinder library is used for unwinding # the stack after a C++ exception was thrown libstdcxx_libs += ' -lunwind' if use_cxx: self.cxxflags += ' ' + libstdcxx_cxxflags self.ldflags += ' ' + libstdcxx_ldflags self.libs += ' ' + libstdcxx_libs self.env = dict(os.environ) # redirect pkg-config to use our root directory instead of the # default one on the build host bin_dir = os.path.join(install_prefix, 'bin') os.makedirs(bin_dir, exist_ok=True) self.pkg_config = shutil.copy(os.path.join(top_path, 'build', 'pkg-config.sh'), os.path.join(bin_dir, 'pkg-config')) self.env['PKG_CONFIG'] = self.pkg_config class MingwToolchain: def __init__(self, top_path: str, toolchain_path, host_triplet, x64: bool, tarball_path, src_path, build_path, install_prefix): self.host_triplet = host_triplet self.tarball_path = tarball_path self.src_path = src_path self.build_path = build_path self.install_prefix = install_prefix toolchain_bin = os.path.join(toolchain_path, 'bin') self.cc = os.path.join(toolchain_bin, host_triplet + '-gcc') self.cxx = os.path.join(toolchain_bin, host_triplet + '-g++') self.ar = os.path.join(toolchain_bin, host_triplet + '-ar') self.arflags = 'rcs' self.ranlib = os.path.join(toolchain_bin, host_triplet + '-ranlib') self.nm = os.path.join(toolchain_bin, host_triplet + '-nm') self.strip = os.path.join(toolchain_bin, host_triplet + '-strip') self.windres = os.path.join(toolchain_bin, host_triplet + '-windres') common_flags = '-O2 -g' if not x64: # enable SSE support which is required for LAME common_flags += ' -march=pentium3' self.cflags = common_flags self.cxxflags = common_flags self.cppflags = '-isystem ' + os.path.join(install_prefix, 'include') + \ ' -DWINVER=0x0600 -D_WIN32_WINNT=0x0600' self.ldflags = '-L' + os.path.join(install_prefix, 'lib') + \ ' -static-libstdc++ -static-libgcc' self.libs = '' # Explicitly disable _FORTIFY_SOURCE because it is broken with # mingw. This prevents some libraries such as libFLAC to # enable it. self.cppflags += ' -D_FORTIFY_SOURCE=0' self.is_arm = host_triplet.startswith('arm') self.is_armv7 = self.is_arm and 'armv7' in self.cflags self.is_aarch64 = host_triplet == 'aarch64' self.is_windows = 'mingw32' in host_triplet self.is_android = False self.is_darwin = False self.env = dict(os.environ) # redirect pkg-config to use our root directory instead of the # default one on the build host import shutil bin_dir = os.path.join(install_prefix, 'bin') os.makedirs(bin_dir, exist_ok=True) self.pkg_config = shutil.copy(os.path.join(top_path, 'build', 'pkg-config.sh'), os.path.join(bin_dir, 'pkg-config')) self.env['PKG_CONFIG'] = self.pkg_config AnyToolchain = Union[AndroidNdkToolchain, MingwToolchain]