makepanda: add code to build an Android package with --installer

This commit is contained in:
rdb 2018-02-09 19:49:02 +01:00
parent e15cea4331
commit bdb74b1e30

View File

@ -7444,6 +7444,117 @@ def MakeInstallerFreeBSD():
WriteFile("+MANIFEST", manifest_txt)
oscmd("pkg create -p pkg-plist -r %s -m . -o . %s" % (os.path.abspath("targetroot"), "--verbose" if GetVerbose() else "--quiet"))
def MakeInstallerAndroid():
oscmd("rm -rf apkroot")
oscmd("mkdir apkroot")
# Also remove the temporary apks.
apk_unaligned = os.path.join(GetOutputDir(), "tmp", "panda3d-unaligned.apk")
apk_unsigned = os.path.join(GetOutputDir(), "tmp", "panda3d-unsigned.apk")
if os.path.exists(apk_unaligned):
os.unlink(apk_unaligned)
if os.path.exists(apk_unsigned):
os.unlink(apk_unsigned)
# Compile the Java classes into a Dalvik executable.
dx_cmd = "dx --dex --output=apkroot/classes.dex "
if GetOptimize() <= 2:
dx_cmd += "--debug "
if GetVerbose():
dx_cmd += "--verbose "
if "ANDROID_API" in SDK:
dx_cmd += "--min-sdk-version=%d " % (SDK["ANDROID_API"])
dx_cmd += os.path.join(GetOutputDir(), "classes")
oscmd(dx_cmd)
# Copy the libraries one by one. In case of library dependencies, strip
# off any suffix (eg. libfile.so.1.0), as Android does not support them.
source_dir = os.path.join(GetOutputDir(), "lib")
target_dir = os.path.join("apkroot", "lib", SDK["ANDROID_ABI"])
oscmd("mkdir -p %s" % (target_dir))
# Determine the library directories we should look in.
libpath = [source_dir]
for dir in os.environ.get("LD_LIBRARY_PATH", "").split(':'):
dir = os.path.expandvars(dir)
dir = os.path.expanduser(dir)
if os.path.isdir(dir):
dir = os.path.realpath(dir)
if not dir.startswith("/system") and not dir.startswith("/vendor"):
libpath.append(dir)
def copy_library(source, base):
# Copy file to destination, stripping version suffix.
target = os.path.join(target_dir, base)
if not target.endswith('.so'):
target = target.rpartition('.so.')[0] + '.so'
if os.path.isfile(target):
# Already processed.
return
oscmd("cp %s %s" % (source, target))
# Walk through the library dependencies.
oscmd("ldd %s | grep .so > %s/tmp/otool-libs.txt" % (target, GetOutputDir()), True)
for line in open(GetOutputDir() + "/tmp/otool-libs.txt", "r"):
line = line.strip()
if not line:
continue
if '.so.' in line:
dep = line.rpartition('.so.')[0] + '.so'
oscmd("patchelf --replace-needed %s %s %s" % (line, dep, target))
else:
dep = line
# Find it on the LD_LIBRARY_PATH.
for dir in libpath:
fulldep = os.path.join(dir, dep)
if os.path.isfile(fulldep):
copy_library(os.path.realpath(fulldep), dep)
break
for base in os.listdir(source_dir):
if not base.startswith('lib'):
continue
if not base.endswith('.so') and '.so.' not in base:
continue
source = os.path.join(source_dir, base)
if os.path.islink(source):
continue
copy_library(source, base)
# Copy the models as well.
oscmd("mkdir apkroot/assets")
oscmd("cp -R %s apkroot/assets/models" % (os.path.join(GetOutputDir(), "models")))
# Make an empty res folder. It's needed for the apk to be installable, apparently.
oscmd("mkdir apkroot/res")
# Now package up the application
oscmd("cp panda/src/android/pview_manifest.xml apkroot/AndroidManifest.xml")
aapt_cmd = "aapt package"
aapt_cmd += " -F %s" % (apk_unaligned)
aapt_cmd += " -M apkroot/AndroidManifest.xml"
aapt_cmd += " -A apkroot/assets -S apkroot/res"
aapt_cmd += " -I $PREFIX/share/aapt/android.jar"
oscmd(aapt_cmd)
# And add all the libraries to it.
oscmd("cd apkroot && aapt add ../%s classes.dex lib/%s/lib*.so" % (apk_unaligned, SDK["ANDROID_ABI"]))
# Now align the .apk, which is necessary for Android to load it.
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.
oscmd("apksigner debug.ks %s panda3d.apk" % (apk_unsigned))
# Clean up.
oscmd("rm -rf apkroot")
os.unlink(apk_unaligned)
os.unlink(apk_unsigned)
try:
if INSTALLER:
ProgressOutput(100.0, "Building installer")
@ -7478,6 +7589,8 @@ try:
MakeInstallerOSX()
elif (target == 'freebsd'):
MakeInstallerFreeBSD()
elif (target == 'android'):
MakeInstallerAndroid()
else:
exit("Do not know how to make an installer for this platform")