diff --git a/dtool/src/dtoolbase/dtool_platform.h b/dtool/src/dtoolbase/dtool_platform.h index 4cb25abc3a..9037632738 100644 --- a/dtool/src/dtoolbase/dtool_platform.h +++ b/dtool/src/dtoolbase/dtool_platform.h @@ -51,6 +51,8 @@ #elif defined(__ANDROID__) #if defined(__ARM_ARCH_7A__) #define DTOOL_PLATFORM "android_armv7a" +#elif defined(__aarch64__) +#define DTOOL_PLATFORM "android_aarch64" #elif defined(__arm__) #define DTOOL_PLATFORM "android_arm" #elif defined(__mips__) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 5e7d59443a..ef02a1eb04 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -864,7 +864,7 @@ if (COMPILER=="GCC"): if not PkgSkip("PYTHON"): python_lib = SDK["PYTHONVERSION"] - if not RTDIST: + if not RTDIST and GetTarget() != 'android': # We don't link anything in the SDK with libpython. python_lib = "" SmartPkgEnable("PYTHON", "", python_lib, (SDK["PYTHONVERSION"], SDK["PYTHONVERSION"] + "/Python.h")) @@ -1259,8 +1259,11 @@ def CompileCxx(obj,src,opts): if GetTarget() == "android": # Most of the specific optimization flags here were # just copied from the default Android Makefiles. - cmd += ' -I%s/include' % (SDK["ANDROID_STL"]) - cmd += ' -I%s/libs/%s/include' % (SDK["ANDROID_STL"], SDK["ANDROID_ABI"]) + if "ANDROID_API" in SDK: + cmd += ' -D__ANDROID_API__=' + str(SDK["ANDROID_API"]) + if "ANDROID_STL" in SDK: + cmd += ' -I%s/include' % (SDK["ANDROID_STL"]) + cmd += ' -I%s/libs/%s/include' % (SDK["ANDROID_STL"], SDK["ANDROID_ABI"]) cmd += ' -ffunction-sections -funwind-tables' if arch == 'armv7a': cmd += ' -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__' @@ -1310,7 +1313,7 @@ def CompileCxx(obj,src,opts): if optlevel >= 4 or GetTarget() == "android": cmd += " -fno-rtti" - if ('SSE2' in opts or not PkgSkip("SSE2")) and not arch.startswith("arm"): + if ('SSE2' in opts or not PkgSkip("SSE2")) and not arch.startswith("arm") and arch != 'aarch64': cmd += " -msse2" # Needed by both Python, Panda, Eigen, all of which break aliasing rules. @@ -1437,12 +1440,19 @@ def CompileIgate(woutd,wsrc,opts): cmd += ' -D_MSC_VER=1600 -D"__declspec(param)=" -D__cdecl -D_near -D_far -D__near -D__far -D__stdcall' if (COMPILER=="GCC"): cmd += ' -D__attribute__\(x\)=' - if GetTargetArch() in ("x86_64", "amd64"): + target_arch = GetTargetArch() + if target_arch in ("x86_64", "amd64"): cmd += ' -D_LP64' + elif target_arch == 'aarch64': + cmd += ' -D_LP64 -D__LP64__ -D__aarch64__' else: cmd += ' -D__i386__' - if GetTarget() == 'darwin': + + target = GetTarget() + if target == 'darwin': cmd += ' -D__APPLE__' + elif target == 'android': + cmd += ' -D__ANDROID__' optlevel = GetOptimizeOption(opts) if (optlevel==1): cmd += ' -D_DEBUG' @@ -1744,8 +1754,8 @@ def CompileLink(dll, obj, opts): if LDFLAGS != "": cmd += " " + LDFLAGS - # Don't link libraries with Python. - if "PYTHON" in opts and GetOrigExt(dll) != ".exe" and not RTDIST: + # Don't link libraries with Python, except on Android. + if "PYTHON" in opts and GetOrigExt(dll) != ".exe" and not RTDIST and GetTarget() != 'android': opts = opts[:] opts.remove("PYTHON") diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index b1666aee39..6ea7ec2626 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -37,6 +37,7 @@ TARGET_ARCH = None HAS_TARGET_ARCH = False TOOLCHAIN_PREFIX = "" ANDROID_ABI = None +ANDROID_API = 14 SYS_LIB_DIRS = [] SYS_INC_DIRS = [] DEBUG_DEPENDENCIES = False @@ -290,7 +291,13 @@ def GetHost(): elif sys.platform == 'darwin': return 'darwin' elif sys.platform.startswith('linux'): - return 'linux' + try: + # Python seems to offer no built-in way to check this. + osname = subprocess.check_output(["uname", "-o"]) + if osname.strip().lower() == b'android': + return 'android' + except: + return 'linux' elif sys.platform.startswith('freebsd'): return 'freebsd' else: @@ -344,9 +351,19 @@ def SetTarget(target, arch=None): if arch not in choices: exit('Mac OS X architecture must be one of %s' % (', '.join(choices))) - elif target == 'android': + elif target == 'android' or target.startswith('android-'): if arch is None: - arch = 'arm' + # If compiling on Android, default to same architecture. Otherwise, arm. + if host == 'android': + arch = host_arch + else: + arch = 'arm' + + # Did we specify an API level? + target, _, api = target.partition('-') + if api: + global ANDROID_API + ANDROID_API = int(api) # Determine the prefix for our gcc tools, eg. arm-linux-androideabi-gcc global ANDROID_ABI @@ -356,14 +373,23 @@ def SetTarget(target, arch=None): elif arch == 'arm': ANDROID_ABI = 'armeabi' TOOLCHAIN_PREFIX = 'arm-linux-androideabi-' - elif arch == 'x86': - ANDROID_ABI = 'x86' - TOOLCHAIN_PREFIX = 'i686-linux-android-' + elif arch == 'aarch64': + ANDROID_ABI = 'arm64-v8a' + TOOLCHAIN_PREFIX = 'aarch64-linux-android-' elif arch == 'mips': ANDROID_ABI = 'mips' TOOLCHAIN_PREFIX = 'mipsel-linux-android-' + elif arch == 'mips64': + ANDROID_ABI = 'mips64' + TOOLCHAIN_PREFIX = 'mips64el-linux-android-' + elif arch == 'x86': + ANDROID_ABI = 'x86' + TOOLCHAIN_PREFIX = 'i686-linux-android-' + elif arch == 'x86_64': + ANDROID_ABI = 'x86_64' + TOOLCHAIN_PREFIX = 'x86_64-linux-android-' else: - exit('Android architecture must be arm, armv7a, x86 or mips') + exit('Android architecture must be arm, armv7a, aarch64, mips, mips64, x86 or x86_64') elif target == 'linux': if arch is not None: @@ -413,13 +439,13 @@ def CrossCompiling(): return GetTarget() != GetHost() def GetCC(): - if TARGET == 'darwin' or TARGET == 'freebsd': + if TARGET in ('darwin', 'freebsd', 'android'): return os.environ.get('CC', TOOLCHAIN_PREFIX + 'clang') else: return os.environ.get('CC', TOOLCHAIN_PREFIX + 'gcc') def GetCXX(): - if TARGET == 'darwin' or TARGET == 'freebsd': + if TARGET in ('darwin', 'freebsd', 'android'): return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'clang++') else: return os.environ.get('CXX', TOOLCHAIN_PREFIX + 'g++') @@ -2339,6 +2365,16 @@ def SdkLocateAndroid(): if GetTarget() != 'android': return + # Allow ANDROID_API/ANDROID_ABI to be used in makepanda.py. + api = ANDROID_API + SDK["ANDROID_API"] = api + + abi = ANDROID_ABI + SDK["ANDROID_ABI"] = abi + + if GetHost() == 'android': + return + # Determine the NDK installation directory. if 'NDK_ROOT' not in os.environ: exit('NDK_ROOT must be set when compiling for Android!') @@ -2355,18 +2391,20 @@ def SdkLocateAndroid(): if arch == 'armv7a' or arch == 'arm': arch = 'arm' toolchain = 'arm-linux-androideabi-' + gcc_ver - elif arch == 'x86': - toolchain = 'x86-' + gcc_ver + elif arch == 'aarch64': + toolchain = 'aarch64-linux-android-' + gcc_ver elif arch == 'mips': toolchain = 'mipsel-linux-android-' + gcc_ver + elif arch == 'mips64': + toolchain = 'mips64el-linux-android-' + gcc_ver + elif arch == 'x86': + toolchain = 'x86-' + gcc_ver + elif arch == 'x86_64': + toolchain = 'x86_64-' + gcc_ver SDK["ANDROID_TOOLCHAIN"] = os.path.join(ndk_root, 'toolchains', toolchain) - # Allow ANDROID_ABI to be used in makepanda.py. - abi = ANDROID_ABI - SDK["ANDROID_ABI"] = abi - # Determine the sysroot directory. - SDK["SYSROOT"] = os.path.join(ndk_root, 'platforms', 'android-9', 'arch-%s' % (arch)) + SDK["SYSROOT"] = os.path.join(ndk_root, 'platforms', 'android-%s' % (api), 'arch-%s' % (arch)) #IncDirectory("ALWAYS", os.path.join(SDK["SYSROOT"], 'usr', 'include')) stdlibc = os.path.join(ndk_root, 'sources', 'cxx-stl', 'gnu-libstdc++', gcc_ver) @@ -2626,7 +2664,12 @@ def SetupBuildEnvironment(compiler): print("Using compiler: %s" % compiler) print("Host OS: %s" % GetHost()) print("Host arch: %s" % GetHostArch()) + + target = GetTarget() + if target != 'android': print("Target OS: %s" % GetTarget()) + else: + print("Target OS: %s (API level %d)" % (GetTarget(), ANDROID_API)) print("Target arch: %s" % GetTargetArch()) # Set to English so we can safely parse the result of gcc commands. @@ -2732,7 +2775,7 @@ def SetupBuildEnvironment(compiler): print(" " + dir) # In the case of Android, we have to put the toolchain on the PATH in order to use it. - if GetTarget() == 'android': + if GetTarget() == 'android' and GetHost() != 'android': # Locate the directory where the toolchain binaries reside. prebuilt_dir = os.path.join(SDK['ANDROID_TOOLCHAIN'], 'prebuilt') if not os.path.isdir(prebuilt_dir):