makepanda: update Android cross-compile for clang and NDK r16

Tested on Windows.
This commit is contained in:
rdb 2018-02-06 19:22:09 +01:00
parent 8a7b47d501
commit 2dba9357bb
2 changed files with 134 additions and 88 deletions

View File

@ -821,9 +821,6 @@ if (COMPILER=="GCC"):
SmartPkgEnable("FREETYPE", "freetype2", ("freetype"), ("freetype2", "freetype2/freetype/freetype.h"))
SmartPkgEnable("HARFBUZZ", "harfbuzz", ("harfbuzz"), ("harfbuzz", "harfbuzz/hb-ft.h"))
SmartPkgEnable("GL", "gl", ("GL"), ("GL/gl.h"), framework = "OpenGL")
SmartPkgEnable("GLES", "glesv1_cm", ("GLESv1_CM"), ("GLES/gl.h"), framework = "OpenGLES")
SmartPkgEnable("GLES2", "glesv2", ("GLESv2"), ("GLES2/gl2.h")) #framework = "OpenGLES"?
SmartPkgEnable("EGL", "egl", ("EGL"), ("EGL/egl.h"))
SmartPkgEnable("NVIDIACG", "", ("Cg"), "Cg/cg.h", framework = "Cg")
SmartPkgEnable("ODE", "", ("ode"), "ode/ode.h", tool = "ode-config")
SmartPkgEnable("OPENAL", "openal", ("openal"), "AL/al.h", framework = "OpenAL")
@ -837,6 +834,12 @@ if (COMPILER=="GCC"):
SmartPkgEnable("JPEG", "", ("jpeg"), "jpeglib.h")
SmartPkgEnable("PNG", "libpng", ("png"), "png.h", tool = "libpng-config")
# On Android, these are system libraries.
if GetHost() != "android":
SmartPkgEnable("GLES", "glesv1_cm", (), ("GLES/gl.h"), framework = "OpenGLES")
SmartPkgEnable("GLES2", "glesv2", (), ("GLES2/gl2.h")) #framework = "OpenGLES"?
SmartPkgEnable("EGL", "egl", (), ("EGL/egl.h"))
if not PkgSkip("FFMPEG"):
if GetTarget() == "darwin":
LibName("FFMPEG", "-Wl,-read_only_relocs,suppress")
@ -1251,7 +1254,13 @@ def CompileCxx(obj,src,opts):
cmd += " -arch %s" % arch
if "SYSROOT" in SDK:
cmd += ' --sysroot=%s -no-canonical-prefixes' % (SDK["SYSROOT"])
if GetTarget() != "android":
cmd += ' --sysroot=%s' % (SDK["SYSROOT"])
else:
ndk_dir = SDK["ANDROID_NDK"].replace('\\', '/')
cmd += ' -isystem %s/sysroot/usr/include' % (ndk_dir)
cmd += ' -isystem %s/sysroot/usr/include/%s' % (ndk_dir, SDK["ANDROID_TRIPLE"])
cmd += ' -no-canonical-prefixes'
# Android-specific flags.
arch = GetTargetArch()
@ -1261,33 +1270,38 @@ def CompileCxx(obj,src,opts):
# just copied from the default Android Makefiles.
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"])
if "ANDROID_GCC_TOOLCHAIN" in SDK:
cmd += ' -gcc-toolchain ' + SDK["ANDROID_GCC_TOOLCHAIN"].replace('\\', '/')
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__'
cmd += ' -fstack-protector -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16'
cmd += ' -target armv7-none-linux-androideabi'
cmd += ' -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16'
cmd += ' -fno-integrated-as'
elif arch == 'arm':
cmd += ' -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__'
cmd += ' -fstack-protector -march=armv5te -mtune=xscale -msoft-float'
cmd += ' -target armv5te-none-linux-androideabi'
cmd += ' -march=armv5te -mtune=xscale -msoft-float'
cmd += ' -fno-integrated-as'
elif arch == 'aarch64':
cmd += ' -target aarch64-none-linux-android'
elif arch == 'mips':
cmd += ' -finline-functions -fmessage-length=0'
cmd += ' -fno-inline-functions-called-once -fgcse-after-reload'
cmd += ' -frerun-cse-after-loop -frename-registers'
cmd += ' -target mipsel-none-linux-android'
cmd += ' -mips32'
elif arch == 'mips64':
cmd += ' -target mips64el-none-linux-android'
cmd += ' -fintegrated-as'
elif arch == 'x86':
cmd += ' -target i686-none-linux-android'
cmd += ' -mstackrealign'
elif arch == 'x86_64':
cmd += ' -target x86_64-none-linux-android'
cmd += " -Wa,--noexecstack"
# Now add specific release/debug flags.
if optlevel >= 3:
cmd += " -fomit-frame-pointer"
if arch.startswith('arm'):
cmd += ' -finline-limit=64 -mthumb'
elif arch == 'mips':
cmd += ' -funswitch-loops -finline-limit=300'
else:
cmd += ' -fno-omit-frame-pointer'
if arch.startswith('arm'):
# Do we want thumb or arm instructions?
if arch.startswith('arm'):
if optlevel >= 3:
cmd += ' -mthumb'
else:
cmd += ' -marm'
# Enable SIMD instructions if requested
@ -1745,9 +1759,26 @@ def CompileLink(dll, obj, opts):
cmd += " -arch %s" % arch
elif GetTarget() == 'android':
arch = GetTargetArch()
if "ANDROID_GCC_TOOLCHAIN" in SDK:
cmd += ' -gcc-toolchain ' + SDK["ANDROID_GCC_TOOLCHAIN"].replace('\\', '/')
cmd += " -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now"
if GetTargetArch() == 'armv7a':
if arch == 'armv7a':
cmd += ' -target armv7-none-linux-androideabi'
cmd += " -march=armv7-a -Wl,--fix-cortex-a8"
elif arch == 'arm':
cmd += ' -target armv5te-none-linux-androideabi'
elif arch == 'aarch64':
cmd += ' -target aarch64-none-linux-android'
elif arch == 'mips':
cmd += ' -target mipsel-none-linux-android'
cmd += ' -mips32'
elif arch == 'mips64':
cmd += ' -target mips64el-none-linux-android'
elif arch == 'x86':
cmd += ' -target i686-none-linux-android'
elif arch == 'x86_64':
cmd += ' -target x86_64-none-linux-android'
cmd += ' -lc -lm'
else:
cmd += " -pthread"

View File

@ -37,7 +37,8 @@ TARGET_ARCH = None
HAS_TARGET_ARCH = False
TOOLCHAIN_PREFIX = ""
ANDROID_ABI = None
ANDROID_API = 14
ANDROID_TRIPLE = None
ANDROID_API = None
SYS_LIB_DIRS = []
SYS_INC_DIRS = []
DEBUG_DEPENDENCIES = False
@ -359,40 +360,48 @@ def SetTarget(target, arch=None):
if host == 'android':
arch = host_arch
else:
arch = 'arm'
arch = 'armv7a'
# Did we specify an API level?
global ANDROID_API
target, _, api = target.partition('-')
if api:
global ANDROID_API
ANDROID_API = int(api)
elif arch in ('mips64', 'aarch64', 'x86_64'):
# 64-bit platforms were introduced in Android 21.
ANDROID_API = 21
else:
# Default to the lowest API level supported by NDK r16.
ANDROID_API = 14
# Determine the prefix for our gcc tools, eg. arm-linux-androideabi-gcc
global ANDROID_ABI
global ANDROID_ABI, ANDROID_TRIPLE
if arch == 'armv7a':
ANDROID_ABI = 'armeabi-v7a'
TOOLCHAIN_PREFIX = 'arm-linux-androideabi-'
ANDROID_TRIPLE = 'arm-linux-androideabi'
elif arch == 'arm':
ANDROID_ABI = 'armeabi'
TOOLCHAIN_PREFIX = 'arm-linux-androideabi-'
ANDROID_TRIPLE = 'arm-linux-androideabi'
elif arch == 'aarch64':
ANDROID_ABI = 'arm64-v8a'
TOOLCHAIN_PREFIX = 'aarch64-linux-android-'
ANDROID_TRIPLE = 'aarch64-linux-android'
elif arch == 'mips':
ANDROID_ABI = 'mips'
TOOLCHAIN_PREFIX = 'mipsel-linux-android-'
ANDROID_TRIPLE = 'mipsel-linux-android'
elif arch == 'mips64':
ANDROID_ABI = 'mips64'
TOOLCHAIN_PREFIX = 'mips64el-linux-android-'
ANDROID_TRIPLE = 'mips64el-linux-android'
elif arch == 'x86':
ANDROID_ABI = 'x86'
TOOLCHAIN_PREFIX = 'i686-linux-android-'
ANDROID_TRIPLE = 'i686-linux-android'
elif arch == 'x86_64':
ANDROID_ABI = 'x86_64'
TOOLCHAIN_PREFIX = 'x86_64-linux-android-'
ANDROID_TRIPLE = 'x86_64-linux-android'
else:
exit('Android architecture must be arm, armv7a, aarch64, mips, mips64, x86 or x86_64')
TOOLCHAIN_PREFIX = ANDROID_TRIPLE + '-'
elif target == 'linux':
if arch is not None:
TOOLCHAIN_PREFIX = '%s-linux-gnu-' % arch
@ -2359,6 +2368,8 @@ def SdkLocateAndroid():
"""This actually locates the Android NDK, not the Android SDK.
NDK_ROOT must be set to its root directory."""
global TOOLCHAIN_PREFIX
if GetTarget() != 'android':
return
@ -2368,6 +2379,7 @@ def SdkLocateAndroid():
abi = ANDROID_ABI
SDK["ANDROID_ABI"] = abi
SDK["ANDROID_TRIPLE"] = ANDROID_TRIPLE
if GetHost() == 'android':
return
@ -2383,36 +2395,58 @@ def SdkLocateAndroid():
SDK["ANDROID_NDK"] = ndk_root
# Determine the toolchain location.
gcc_ver = '4.8'
prebuilt_dir = os.path.join(ndk_root, 'toolchains', 'llvm', 'prebuilt')
if not os.path.isdir(prebuilt_dir):
exit('Not found: %s' % (prebuilt_dir))
host_tag = GetHost() + '-x86'
if host_64:
host_tag += '_64'
elif host_tag == 'windows-x86':
host_tag = 'windows'
prebuilt_dir = os.path.join(prebuilt_dir, host_tag)
if host_tag == 'windows-x86_64' and not os.path.isdir(prebuilt_dir):
# Try the 32-bits toolchain instead.
host_tag = 'windows'
prebuilt_dir = os.path.join(prebuilt_dir, host_tag)
SDK["ANDROID_TOOLCHAIN"] = prebuilt_dir
# And locate the GCC toolchain, which is needed for some tools (eg. as/ld)
arch = GetTargetArch()
if arch == 'armv7a' or arch == 'arm':
arch = 'arm'
toolchain = 'arm-linux-androideabi-' + 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)
for opt in (TOOLCHAIN_PREFIX + '4.9', arch + '-4.9', TOOLCHAIN_PREFIX + '4.8', arch + '-4.8'):
if os.path.isdir(os.path.join(ndk_root, 'toolchains', opt)):
SDK["ANDROID_GCC_TOOLCHAIN"] = os.path.join(ndk_root, 'toolchains', opt, 'prebuilt', host_tag)
break
# The prebuilt binaries have no toolchain prefix.
TOOLCHAIN_PREFIX = ''
# Determine the sysroot directory.
SDK["SYSROOT"] = os.path.join(ndk_root, 'platforms', 'android-%s' % (api), 'arch-%s' % (arch))
if arch == 'armv7a':
arch_dir = 'arch-arm'
elif arch == 'aarch64':
arch_dir = 'arch-arm64'
else:
arch_dir = 'arch-' + arch
SDK["SYSROOT"] = os.path.join(ndk_root, 'platforms', 'android-%s' % (api), arch_dir).replace('\\', '/')
#IncDirectory("ALWAYS", os.path.join(SDK["SYSROOT"], 'usr', 'include'))
stdlibc = os.path.join(ndk_root, 'sources', 'cxx-stl', 'gnu-libstdc++', gcc_ver)
SDK["ANDROID_STL"] = stdlibc
# Starting with NDK r16, libc++ is the recommended STL to use.
stdlibc = os.path.join(ndk_root, 'sources', 'cxx-stl', 'llvm-libc++')
IncDirectory("ALWAYS", os.path.join(stdlibc, 'include').replace('\\', '/'))
LibDirectory("ALWAYS", os.path.join(stdlibc, 'libs', abi).replace('\\', '/'))
#IncDirectory("ALWAYS", os.path.join(stdlibc, 'include'))
#IncDirectory("ALWAYS", os.path.join(stdlibc, 'libs', abi, 'include'))
stl_lib = os.path.join(stdlibc, 'libs', abi, 'libc++_shared.so')
LibName("ALWAYS", stl_lib.replace('\\', '/'))
CopyFile(os.path.join(GetOutputDir(), 'lib', 'libc++_shared.so'), stl_lib)
stl_lib = os.path.join(stdlibc, 'libs', abi, 'libgnustl_shared.so')
LibName("ALWAYS", stl_lib)
CopyFile(os.path.join(GetOutputDir(), 'libs', abi, 'libgnustl_shared.so'), stl_lib)
# The Android support library polyfills C++ features not available in the
# STL that ships with Android.
support = os.path.join(ndk_root, 'sources', 'android', 'support', 'include')
IncDirectory("ALWAYS", support.replace('\\', '/'))
LibName("ALWAYS", "-landroid_support")
########################################################################
##
@ -2675,6 +2709,10 @@ def SetupBuildEnvironment(compiler):
os.environ["LC_ALL"] = "en_US.UTF-8"
os.environ["LANGUAGE"] = "en"
# In the case of Android, we have to put the toolchain on the PATH in order to use it.
if GetTarget() == 'android' and GetHost() != 'android':
AddToPathEnv("PATH", os.path.join(SDK["ANDROID_TOOLCHAIN"], "bin"))
if compiler == "MSVC":
# Add the visual studio tools to PATH et al.
SetupVisualStudioEnviron()
@ -2709,11 +2747,15 @@ def SetupBuildEnvironment(compiler):
continue
line = line[12:].strip()
for libdir in line.split(':'):
libdir = os.path.normpath(libdir)
libdirs = line.split(':')
while libdirs:
libdir = os.path.normpath(libdirs.pop(0))
if os.path.isdir(libdir):
if libdir not in SYS_LIB_DIRS:
SYS_LIB_DIRS.append(libdir)
elif len(libdir) == 1:
# Oops, is this a drive letter? Prepend it to the next.
libdirs[0] = libdir + ':' + libdirs[0]
elif GetVerbose():
print("Ignoring non-existent library directory %s" % (libdir))
@ -2771,33 +2813,6 @@ def SetupBuildEnvironment(compiler):
for dir in SYS_INC_DIRS:
print(" " + dir)
# In the case of Android, we have to put the toolchain on the PATH in order to use it.
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):
exit('Not found: %s' % (prebuilt_dir))
host_tag = GetHost() + '-x86'
if host_64:
host_tag += '_64'
elif host_tag == 'windows-x86':
host_tag = 'windows'
prebuilt_dir = os.path.join(prebuilt_dir, host_tag)
if host_64 and not os.path.isdir(prebuilt_dir):
# Try the 32-bits toolchain instead.
prebuilt_dir = os.path.join(prebuilt_dir, host_tag)
if not os.path.isdir(prebuilt_dir):
if host_64:
exit('Not found: %s or %s' % (prebuilt_dir, host_tag))
else:
exit('Not found: %s' % (prebuilt_dir))
# Then, add it to the PATH.
AddToPathEnv("PATH", os.path.join(prebuilt_dir, 'bin'))
# If we're cross-compiling, no point in putting our output dirs on the path.
if CrossCompiling():
return