# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. @depends(toolchains_base_dir, "--help") @imports(_from="os.path", _import="isdir") @imports(_from="mozboot.android", _import="NDK_VERSION") def default_android_ndk_root(toolchains_base_dir, _): for ndk in ("android-ndk-%s" % NDK_VERSION, "android-ndk"): path = os.path.join(toolchains_base_dir, ndk) if isdir(path): return path option( "--with-android-ndk", nargs=1, default=default_android_ndk_root, help="location where the Android NDK can be found{|}", ) option("--with-android-toolchain", nargs=1, help="location of the Android toolchain") option( "--with-android-lldb-server", nargs=1, help="location of the Android LLDB server" ) option( "--with-android-googlevr-sdk", nargs=1, help="location of the Android GoogleVR SDK" ) @depends(target) def min_android_version(target): if target.cpu in ["aarch64", "x86_64"]: # 64-bit support was added in API 21. return "21" return "16" option( "--with-android-version", nargs=1, help="android platform version{|}", default=min_android_version, ) @depends("--with-android-version", min_android_version) @imports(_from="__builtin__", _import="ValueError") def android_version(value, min_version): if not value: # Someone has passed --without-android-version. die("--with-android-version cannot be disabled.") try: version = int(value[0]) except ValueError: die("--with-android-version expects an integer value") if version < int(min_version): die( "--with-android-version must be at least %s (got %s)", min_version, value[0] ) return version @depends("--with-android-ndk") @imports(_from="os.path", _import="isdir") def ndk(value): if value: if not isdir(value[0]): die( "The path you specified with --with-android-ndk (%s) is not " "a directory" % value[0] ) return value[0] die( "You must specify --with-android-ndk=/path/to/ndk when targeting Android, " "or try |mach bootstrap|." ) set_config("ANDROID_NDK", ndk) @depends(ndk) @checking("for android ndk version") @imports(_from="__builtin__", _import="open") @imports(_from="mozboot.android", _import="NDK_VERSION") @imports(_from="mozboot.android", _import="get_ndk_version") @imports(_from="mozboot.android", _import="GetNdkVersionError") def ndk_version(ndk): if not ndk: # Building 'js/src' for non-Android. return try: major, minor, human = get_ndk_version(ndk) except GetNdkVersionError as e: die(str(e)) if NDK_VERSION != human: die( "The only supported version of the NDK is %s (have %s)\n" "Please run |mach bootstrap| " "to install the correct NDK." % (NDK_VERSION, human) ) return namespace( major=major, minor=minor, ) set_config("ANDROID_NDK_MAJOR_VERSION", ndk_version.major) set_config("ANDROID_NDK_MINOR_VERSION", ndk_version.minor) @imports(_from="os.path", _import="isdir") @imports(_from="mozbuild.shellutil", _import="quote") def host_dir(host, base_dir): dir_format = "%s/%s-%s" host_kernel = "windows" if host.kernel == "WINNT" else host.kernel.lower() dir = dir_format % (base_dir, host_kernel, host.cpu) log.debug("Trying %s" % quote(dir)) if not isdir(dir) and host.cpu == "x86_64": dir = dir_format % (base_dir, host_kernel, "x86") log.debug("Trying %s" % quote(dir)) if not isdir(dir) and host.kernel == "Darwin" and host.cpu == "aarch64": dir = dir_format % (base_dir, host_kernel, "x86_64") log.debug("Trying %s" % quote(dir)) if isdir(dir): return dir @depends(host, ndk, "--with-android-toolchain") @checking("for the Android toolchain directory", lambda x: x or "not found") def android_toolchain(host, ndk, toolchain): if not ndk: return if toolchain: return toolchain[0] toolchain = host_dir(host, os.path.join(ndk, "toolchains", "llvm", "prebuilt")) if toolchain: return toolchain die("You have to specify --with-android-toolchain=" "/path/to/ndk/toolchain.") @depends(target, android_toolchain) @checking("for android sysroot directory") @imports(_from="os.path", _import="isdir") def android_sysroot(target, android_toolchain): if target.os != "Android": return search_dirs = [ os.path.join(android_toolchain, "sysroot"), ] for sysroot_dir in search_dirs: if isdir(sysroot_dir): return sysroot_dir die( "Android sysroot directory not found in %s." % str([sysroot_dir for sysroot_dir in search_dirs]) ) @depends(target, host, ndk, "--with-android-lldb-server") @checking("for the Android LLDB server", lambda x: x or "not found") @imports(_from="os", _import="listdir") @imports(_from="os.path", _import="isdir") @imports(_from="os.path", _import="isfile") @imports(_from="mozbuild.shellutil", _import="quote") def android_lldb_server(target, host, ndk, lldb): if not ndk: return if lldb: return lldb[0] else: clang_format = "toolchains/llvm/prebuilt/%s-%s/lib64/clang" llvm_lib = "lib/linux" host_kernel = "windows" if host.kernel == "WINNT" else host.kernel.lower() clang_path = os.path.join(ndk, clang_format % (host_kernel, host.cpu)) if not isdir(clang_path) and host.kernel == "Darwin" and host.cpu == "aarch64": clang_path = os.path.join(ndk, clang_format % (host_kernel, "x86_64")) log.debug("Listing subdirectories of %s" % quote(clang_path)) clang_subdirs = [ x for x in listdir(clang_path) if isdir(os.path.join(clang_path, x)) ] log.debug("Got %r" % clang_subdirs) if len(clang_subdirs) != 1: die( "Could not resolve lldb-server in %s. Please specify --with-android-lldb-server=/path/to/android/lldb-server" % quote(clang_path) ) log.debug("Found version %s" % quote(clang_subdirs[0])) if target.cpu == "x86": target_cpu = "i386" else: target_cpu = target.cpu full_path = os.path.join( clang_path, clang_subdirs[0], llvm_lib, target_cpu, "lldb-server" ) log.debug("Trying %s" % quote(full_path)) if isfile(full_path): return full_path die("Please specify --with-android-lldb-server=/path/to/android/lldb-server") set_config("ANDROID_LLDB_SERVER", android_lldb_server) option( env="STLPORT_LIBS", nargs=1, help="Options linker should pass for standard C++ library", ) @depends("STLPORT_LIBS", ndk) @imports(_from="os.path", _import="isfile") def stlport_libs(value, ndk): if value and len(value): return value.split() if not ndk: return return ["-static-libstdc++"] set_config("STLPORT_LIBS", stlport_libs) @depends(android_sysroot, android_toolchain) def extra_toolchain_flags(android_sysroot, toolchain_dir): if not android_sysroot: return [] flags = [ "--sysroot={}".format(android_sysroot), "--gcc-toolchain={}".format(toolchain_dir), ] return flags add_old_configure_assignment("extra_android_flags", extra_toolchain_flags) @depends(extra_toolchain_flags) def bindgen_cflags_android(toolchain_flags): return toolchain_flags @depends("--with-android-googlevr-sdk", target) @checking("for GoogleVR SDK", lambda x: x.result) @imports(_from="os.path", _import="exists") @imports(_from="os.path", _import="abspath") def googlevr_sdk(value, target): if not value: return namespace(result="Not specified") path = abspath(value[0]) if not exists(path): die("Could not find GoogleVR SDK %s", path) include = "%s/libraries/headers/" % path if "arm" == target.cpu: arch = "armeabi-v7a" elif "aarch64" == target.cpu: arch = "arm64-v8a" elif "x86" == target.cpu: arch = "x86" else: die("Unsupported GoogleVR cpu architecture %s" % target.cpu) libs = "{0}/libraries/jni/{1}/".format(path, arch) if not exists(libs): die( "Could not find GoogleVR NDK at %s. Did you try running " "'./gradlew :extractNdk' in %s?", libs, path, ) return namespace( result=path, include=include, libs=libs, enabled=True, ) set_define("MOZ_ANDROID_GOOGLE_VR", googlevr_sdk.enabled) set_config("MOZ_ANDROID_GOOGLE_VR", googlevr_sdk.enabled) set_config("MOZ_ANDROID_GOOGLE_VR_INCLUDE", googlevr_sdk.include) set_config("MOZ_ANDROID_GOOGLE_VR_LIBS", googlevr_sdk.libs)