# -*- 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(target.os) def arm_option_defaults(os): if os == "Android": arch = "armv7-a" thumb = "yes" fpu = "neon" float_abi = "softfp" else: arch = thumb = fpu = float_abi = "toolchain-default" return namespace( arch=arch, thumb=thumb, fpu=fpu, float_abi=float_abi, ) # Note: '{...|}' in the help of all options with a non-constant default to # make the lint happy. The first arm is always going to be used, because a # default is always returned. The lint is fooled by this file being # conditional. If it weren't conditional, the lint wouldn't ask for '{|}' to # be there. option( "--with-arch", nargs=1, default=arm_option_defaults.arch, help="{Use specific CPU features (-march=type). Resets thumb, fpu, " "float-abi, etc. defaults when set|}", ) @depends("--with-arch") def arch_option(value): if value: if value[0] != "toolchain-default": return ["-march={}".format(value[0])] return [] option( "--with-thumb", choices=("yes", "no", "toolchain-default"), default=arm_option_defaults.thumb, nargs="?", help="{Use Thumb instruction set (-mthumb)|}", ) def normalize_arm_option(value): if value: if len(value): if value[0] == "yes": return True elif value[0] == "no": return False else: return value[0] return True return False @depends("--with-thumb") def thumb_option(value): value = normalize_arm_option(value) if value is True: return ["-mthumb"] if value is False: return ["-marm"] return [] option( "--with-thumb-interwork", choices=("yes", "no", "toolchain-default"), default="toolchain-default", nargs="?", help="Use Thumb/ARM instuctions interwork (-mthumb-interwork)", ) @depends("--with-thumb-interwork") def thumb_interwork_option(value): value = normalize_arm_option(value) if value is True: return ["-mthumb-interwork"] if value is False: return ["-mno-thumb-interwork"] return [] option( "--with-fpu", nargs=1, default=arm_option_defaults.fpu, help="{Use specific FPU type (-mfpu=type)|}", ) @depends("--with-fpu") def fpu_option(value): if value: if value[0] != "toolchain-default": return ["-mfpu={}".format(value[0])] return [] option( "--with-float-abi", nargs=1, default=arm_option_defaults.float_abi, help="{Use specific arm float ABI (-mfloat-abi=type)|}", ) @depends("--with-float-abi") def float_abi_option(value): if value: if value[0] != "toolchain-default": return ["-mfloat-abi={}".format(value[0])] return [] option( "--with-soft-float", choices=("yes", "no", "toolchain-default"), default="toolchain-default", nargs="?", help="Use soft float library (-msoft-float)", ) @depends("--with-soft-float") def soft_float_option(value): value = normalize_arm_option(value) if value is True: return ["-msoft-float"] if value is False: return ["-mno-soft-float"] return [] check_and_add_flag( "-mno-unaligned-access", when=depends(target.os)(lambda os: os == "Android") ) # The set of flags that clang understands @depends( arch_option, thumb_option, fpu_option, float_abi_option, soft_float_option, ) def all_clang_arm_flags(arch, thumb, fpu, float_abi, soft_float): return arch + thumb + fpu + float_abi + soft_float # All the flags the compiler understands. When the compiler is clang, this # still includes unsupported flags, but we live it to configure to fail # during a compiler check. These checks aren't available for clang as used # by bindgen, so we keep the separate set of flags for clang for bindgen. @depends(all_clang_arm_flags, thumb_interwork_option) def all_arm_flags(flags, interwork): return flags + interwork add_old_configure_assignment("_ARM_FLAGS", all_arm_flags) add_old_configure_assignment("_THUMB_FLAGS", thumb_option) @depends(configure_cache, c_compiler, all_arm_flags) @checking("ARM version support in compiler", lambda x: x.arm_arch) @imports(_from="textwrap", _import="dedent") def arm_target(configure_cache, compiler, all_arm_flags): # We're going to preprocess the following source to figure out some details # about the arm target options we have enabled. source = dedent( """\ %ARM_ARCH __ARM_ARCH #if __thumb2__ %THUMB2 yes #else %THUMB2 no #endif // Confusingly, the __SOFTFP__ preprocessor variable indicates the // "softfloat" ABI, not the "softfp" ABI. #if __SOFTFP__ %FLOAT_ABI soft #elif __ARM_PCS_VFP %FLOAT_ABI hard #else %FLOAT_ABI softfp #endif // There is more subtlety to it than this preprocessor test, but MOZ_FPU doesn't // need to be too fine-grained. #if __ARM_NEON %FPU neon #elif __ARM_VFPV2__ || __ARM_FP == 12 %FPU vfpv2 #elif __ARM_VFPV3__ %FPU vfpv3 #elif __ARM_VFPV4__ || __ARM_FP == 14 %FPU vfpv4 #elif __ARM_FPV5__ %FPU fp-armv8 #endif """ ) result = try_invoke_compiler( configure_cache, [compiler.compiler] + compiler.flags, compiler.language, source, ["-E"] + all_arm_flags, wrapper=compiler.wrapper, ) # Metadata emitted by preprocessors such as GCC with LANG=ja_JP.utf-8 may # have non-ASCII characters. Treat the output as bytearray. data = {"fpu": None} # fpu may not get a value from the preprocessor. for line in result.splitlines(): if line.startswith("%"): k, _, v = line.partition(" ") k = k.lstrip("%").lower() if k == "arm_arch": data[k] = int(v) else: data[k] = { "yes": True, "no": False, }.get(v, v) log.debug("%s = %s", k, data[k]) return namespace(**data) @depends(arm_target.arm_arch, when=depends(target.os)(lambda os: os == "Android")) def armv7(arch): if arch < 7: die("Android/armv6 and earlier are not supported") set_config("MOZ_THUMB2", True, when=arm_target.thumb2) set_define("MOZ_THUMB2", True, when=arm_target.thumb2) have_arm_simd = c_compiler.try_compile( body='asm("uqadd8 r1, r1, r2");', check_msg="for ARM SIMD support in compiler" ) set_config("HAVE_ARM_SIMD", have_arm_simd) set_define("HAVE_ARM_SIMD", have_arm_simd) have_arm_neon = c_compiler.try_compile( body='asm(".fpu neon\\n vadd.i8 d0, d0, d0");', check_msg="for ARM NEON support in compiler", ) set_config("HAVE_ARM_NEON", have_arm_neon) set_define("HAVE_ARM_NEON", have_arm_neon) # We don't need to build NEON support if we're targetting a non-NEON device. # This matches media/webrtc/trunk/webrtc/build/common.gypi. @depends(arm_target.arm_arch, when=have_arm_neon) def build_arm_neon(arm_arch): return arm_arch >= 7 set_config("BUILD_ARM_NEON", True, when=build_arm_neon) set_define("BUILD_ARM_NEON", True, when=build_arm_neon) set_config("ARM_ARCH", depends(arm_target.arm_arch)(lambda x: str(x))) set_config("MOZ_FPU", arm_target.fpu) @depends(arm_target) def neon_flags(arm_target): # Building with -mfpu=neon requires either the "softfp" or the # "hardfp" ABI. Depending on the compiler's default target, and the # CFLAGS, the default ABI might be neither, in which case it is the # "softfloat" ABI. # The "softfloat" ABI is binary-compatible with the "softfp" ABI, so # we can safely mix code built with both ABIs. So, if we detect # that compiling uses the "softfloat" ABI, force the use of the # "softfp" ABI instead. flags = ["-mfpu=neon"] if arm_target.float_abi == "soft": flags.append("-mfloat-abi=softfp") if arm_target.arm_arch < 7: # clang needs to be forced to at least armv7 for -mfpu=neon to do # something. flags.append("-march=armv7-a") return tuple(flags) set_config("NEON_FLAGS", neon_flags)