makepanda: support cross-compiling for Android again

This commit is contained in:
rdb 2019-01-19 23:15:21 +01:00
parent 7968022c23
commit c0b973b789
3 changed files with 75 additions and 14 deletions

View File

@ -867,6 +867,11 @@ def MakeInstallerAndroid(version, **kwargs):
line = line.strip() line = line.strip()
if not line: if not line:
continue continue
if ' ' in line:
line = line.split(' ', 1)[0]
# Change .so.1.2 suffix to .so, as needed for loading in .apk
if '.so.' in line: if '.so.' in line:
dep = line.rpartition('.so.')[0] + '.so' dep = line.rpartition('.so.')[0] + '.so'
oscmd("patchelf --replace-needed %s %s %s" % (line, dep, target), True) oscmd("patchelf --replace-needed %s %s %s" % (line, dep, target), True)
@ -960,7 +965,7 @@ def MakeInstallerAndroid(version, **kwargs):
aapt_cmd += " -F %s" % (apk_unaligned) aapt_cmd += " -F %s" % (apk_unaligned)
aapt_cmd += " -M apkroot/AndroidManifest.xml" aapt_cmd += " -M apkroot/AndroidManifest.xml"
aapt_cmd += " -A apkroot/assets -S apkroot/res" aapt_cmd += " -A apkroot/assets -S apkroot/res"
aapt_cmd += " -I $PREFIX/share/aapt/android.jar" aapt_cmd += " -I %s" % (SDK["ANDROID_JAR"])
oscmd(aapt_cmd) oscmd(aapt_cmd)
# And add all the libraries to it. # And add all the libraries to it.
@ -974,7 +979,13 @@ def MakeInstallerAndroid(version, **kwargs):
oscmd("zipalign -v -p 4 %s %s" % (apk_unaligned, apk_unsigned)) oscmd("zipalign -v -p 4 %s %s" % (apk_unaligned, apk_unsigned))
# Finally, sign it using a debug key. This is generated if it doesn't exist. # Finally, sign it using a debug key. This is generated if it doesn't exist.
oscmd("apksigner debug.ks %s panda3d.apk" % (apk_unsigned)) if GetHost() == 'android':
# Termux version of apksigner automatically generates a debug key.
oscmd("apksigner debug.ks %s panda3d.apk" % (apk_unsigned))
else:
if not os.path.isfile('debug.ks'):
oscmd("keytool -genkey -noprompt -dname 'CN=Panda3D,O=Panda3D,C=US' -keystore debug.ks -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 1000")
oscmd("apksigner sign --ks debug.ks --ks-pass pass:android --min-sdk-version %s --out panda3d.apk %s" % (SDK["ANDROID_API"], apk_unsigned))
# Clean up. # Clean up.
oscmd("rm -rf apkroot") oscmd("rm -rf apkroot")

View File

@ -2043,7 +2043,10 @@ def CompileRsrc(target, src, opts):
def CompileJava(target, src, opts): def CompileJava(target, src, opts):
"""Compiles a .java file into a .class file.""" """Compiles a .java file into a .class file."""
cmd = "ecj " if GetHost() == 'android':
cmd = "ecj "
else:
cmd = "javac -bootclasspath " + BracketNameWithQuotes(SDK["ANDROID_JAR"]) + " "
optlevel = GetOptimizeOption(opts) optlevel = GetOptimizeOption(opts)
if optlevel >= 4: if optlevel >= 4:

View File

@ -2463,22 +2463,40 @@ def SdkLocateAndroid():
SDK["ANDROID_TRIPLE"] = ANDROID_TRIPLE SDK["ANDROID_TRIPLE"] = ANDROID_TRIPLE
if GetHost() == 'android': if GetHost() == 'android':
# Assume we're compiling from termux.
prefix = os.environ.get("PREFIX", "/data/data/com.termux/files/usr")
SDK["ANDROID_JAR"] = prefix + "/share/aapt/android.jar"
return return
# Determine the NDK installation directory. sdk_root = os.environ.get('ANDROID_HOME')
if 'NDK_ROOT' not in os.environ: if not sdk_root or not os.path.isdir(sdk_root):
exit('NDK_ROOT must be set when compiling for Android!') sdk_root = os.environ.get('ANDROID_SDK_ROOT')
if not sdk_root:
exit('ANDROID_SDK_ROOT must be set when compiling for Android!')
elif not os.path.isdir(sdk_root):
exit('Cannot find %s. Please install Android SDK and set ANDROID_SDK_ROOT or ANDROID_HOME.' % (sdk_root))
ndk_root = os.environ["NDK_ROOT"] # Determine the NDK installation directory.
if not os.path.isdir(ndk_root): if os.environ.get('NDK_ROOT') or os.environ.get('ANDROID_NDK_ROOT'):
exit("Cannot find %s. Please install Android NDK and set NDK_ROOT." % (ndk_root)) # We have an explicit setting from an environment variable.
ndk_root = os.environ.get('ANDROID_NDK_ROOT')
if not ndk_root or not os.path.isdir(ndk_root):
ndk_root = os.environ.get('NDK_ROOT')
if not ndk_root or not os.path.isdir(ndk_root):
exit("Cannot find %s. Please install Android NDK and set ANDROID_NDK_ROOT." % (ndk_root))
else:
# Often, it's installed in the ndk-bundle subdirectory of the SDK.
ndk_root = os.path.join(sdk_root, 'ndk-bundle')
if not os.path.isdir(os.path.join(ndk_root, 'toolchains')):
exit('Cannot find the Android NDK. Install it via the SDK manager or set the ANDROID_NDK_ROOT variable if you have installed it in a different location.')
SDK["ANDROID_NDK"] = ndk_root SDK["ANDROID_NDK"] = ndk_root
# Determine the toolchain location. # Determine the toolchain location.
prebuilt_dir = os.path.join(ndk_root, 'toolchains', 'llvm', 'prebuilt') prebuilt_dir = os.path.join(ndk_root, 'toolchains', 'llvm', 'prebuilt')
if not os.path.isdir(prebuilt_dir): if not os.path.isdir(prebuilt_dir):
exit('Not found: %s' % (prebuilt_dir)) exit('Not found: %s (is the Android NDK installed?)' % (prebuilt_dir))
host_tag = GetHost() + '-x86' host_tag = GetHost() + '-x86'
if host_64: if host_64:
@ -2527,7 +2545,24 @@ def SdkLocateAndroid():
# STL that ships with Android. # STL that ships with Android.
support = os.path.join(ndk_root, 'sources', 'android', 'support', 'include') support = os.path.join(ndk_root, 'sources', 'android', 'support', 'include')
IncDirectory("ALWAYS", support.replace('\\', '/')) IncDirectory("ALWAYS", support.replace('\\', '/'))
LibName("ALWAYS", "-landroid_support") if api < 21:
LibName("ALWAYS", "-landroid_support")
# Determine the location of android.jar.
SDK["ANDROID_JAR"] = os.path.join(sdk_root, 'platforms', 'android-%s' % (api), 'android.jar')
# Which build tools versions do we have? Pick the latest.
versions = []
for version in os.listdir(os.path.join(sdk_root, "build-tools")):
match = re.match('([0-9]+)\\.([0-9]+)\\.([0-9]+)', version)
if match:
version_tuple = int(match.group(1)), int(match.group(2)), int(match.group(3))
versions.append(version_tuple)
versions.sort()
if versions:
version = versions[-1]
SDK["ANDROID_BUILD_TOOLS"] = os.path.join(sdk_root, "build-tools", "{0}.{1}.{2}".format(*version))
######################################################################## ########################################################################
## ##
@ -2793,6 +2828,9 @@ def SetupBuildEnvironment(compiler):
if GetTarget() == 'android' and GetHost() != 'android': if GetTarget() == 'android' and GetHost() != 'android':
AddToPathEnv("PATH", os.path.join(SDK["ANDROID_TOOLCHAIN"], "bin")) AddToPathEnv("PATH", os.path.join(SDK["ANDROID_TOOLCHAIN"], "bin"))
if "ANDROID_BUILD_TOOLS" in SDK:
AddToPathEnv("PATH", SDK["ANDROID_BUILD_TOOLS"])
if compiler == "MSVC": if compiler == "MSVC":
# Add the visual studio tools to PATH et al. # Add the visual studio tools to PATH et al.
SetupVisualStudioEnviron() SetupVisualStudioEnviron()
@ -2845,7 +2883,12 @@ def SetupBuildEnvironment(compiler):
SYS_LIB_DIRS += [SDK.get("SYSROOT", "") + "/usr/lib"] SYS_LIB_DIRS += [SDK.get("SYSROOT", "") + "/usr/lib"]
# Now extract the preprocessor's include directories. # Now extract the preprocessor's include directories.
cmd = GetCXX() + sysroot_flag + " -x c++ -v -E /dev/null" cmd = GetCXX() + " -x c++ -v -E " + os.devnull
if "ANDROID_NDK" in SDK:
cmd += " --sysroot=%s/sysroot" % (SDK["ANDROID_NDK"].replace('\\', '/'))
else:
cmd += sysroot_flag
null = open(os.devnull, 'w') null = open(os.devnull, 'w')
handle = subprocess.Popen(cmd, stdout=null, stderr=subprocess.PIPE, shell=True) handle = subprocess.Popen(cmd, stdout=null, stderr=subprocess.PIPE, shell=True)
scanning = False scanning = False
@ -2858,8 +2901,12 @@ def SetupBuildEnvironment(compiler):
scanning = True scanning = True
continue continue
if not line.startswith(' /'): if sys.platform == "win32":
continue if not line.startswith(' '):
continue
else:
if not line.startswith(' /'):
continue
line = line.strip() line = line.strip()
if line.endswith(" (framework directory)"): if line.endswith(" (framework directory)"):