Build a single APK for all ABIs

This commit is contained in:
topjohnwu 2021-05-13 00:21:04 -07:00
parent 66cc9bc545
commit 5e1fba3603
12 changed files with 70 additions and 83 deletions

View File

@ -1,4 +1,3 @@
import com.android.build.gradle.internal.api.ApkVariantOutputImpl
import org.apache.tools.ant.filters.FixCrLfFilter import org.apache.tools.ant.filters.FixCrLfFilter
import java.io.PrintStream import java.io.PrintStream
@ -42,13 +41,6 @@ android {
} }
} }
splits {
abi {
isEnable = true
isUniversalApk = true
}
}
buildFeatures { buildFeatures {
dataBinding = true dataBinding = true
} }
@ -81,40 +73,24 @@ val syncLibs by tasks.registering(Sync::class) {
include("busybox", "magiskboot", "magiskinit", "magisk") include("busybox", "magiskboot", "magiskinit", "magisk")
rename { if (it == "magisk") "libmagisk32.so" else "lib$it.so" } rename { if (it == "magisk") "libmagisk32.so" else "lib$it.so" }
} }
from(rootProject.file("native/out/arm64-v8a")) {
include("magisk")
rename { if (it == "magisk") "libmagisk64.so" else "lib$it.so" }
}
} }
into("x86") { into("x86") {
from(rootProject.file("native/out/x86")) { from(rootProject.file("native/out/x86")) {
include("busybox", "magiskboot", "magiskinit", "magisk") include("busybox", "magiskboot", "magiskinit", "magisk")
rename { if (it == "magisk") "libmagisk32.so" else "lib$it.so" } rename { if (it == "magisk") "libmagisk32.so" else "lib$it.so" }
} }
from(rootProject.file("native/out/x86_64")) {
include("magisk")
rename { if (it == "magisk") "libmagisk64.so" else "lib$it.so" }
}
} }
into("arm64-v8a") { into("arm64-v8a") {
from(rootProject.file("native/out/arm64-v8a")) { from(rootProject.file("native/out/arm64-v8a")) {
include("busybox", "magiskboot", "magiskinit", "magisk") include("busybox", "magiskboot", "magiskinit", "magisk")
rename { if (it == "magisk") "libmagisk64.so" else "lib$it.so" } rename { if (it == "magisk") "libmagisk64.so" else "lib$it.so" }
} }
from(rootProject.file("native/out/armeabi-v7a")) {
include("magisk")
rename { if (it == "magisk") "libmagisk32.so" else "lib$it.so" }
}
} }
into("x86_64") { into("x86_64") {
from(rootProject.file("native/out/x86_64")) { from(rootProject.file("native/out/x86_64")) {
include("busybox", "magiskboot", "magiskinit", "magisk") include("busybox", "magiskboot", "magiskinit", "magisk")
rename { if (it == "magisk") "libmagisk64.so" else "lib$it.so" } rename { if (it == "magisk") "libmagisk64.so" else "lib$it.so" }
} }
from(rootProject.file("native/out/x86")) {
include("magisk")
rename { if (it == "magisk") "libmagisk32.so" else "lib$it.so" }
}
} }
onlyIf { onlyIf {
if (inputs.sourceFiles.files.size != 16) if (inputs.sourceFiles.files.size != 16)
@ -139,10 +115,9 @@ val syncAssets by tasks.registering(Sync::class) {
} }
filesMatching("**/util_functions.sh") { filesMatching("**/util_functions.sh") {
filter { filter {
it.replace( it.replace("#MAGISK_VERSION_STUB",
"#MAGISK_VERSION_STUB",
"MAGISK_VER='${Config.version}'\n" + "MAGISK_VER='${Config.version}'\n" +
"MAGISK_VER_CODE=${Config.versionCode}" "MAGISK_VER_CODE=${Config.versionCode}"
) )
} }
filter<FixCrLfFilter>("eol" to FixCrLfFilter.CrLf.newInstance("lf")) filter<FixCrLfFilter>("eol" to FixCrLfFilter.CrLf.newInstance("lf"))
@ -196,13 +171,6 @@ android.applicationVariants.all {
} }
} }
registerJavaGeneratingTask(genSrcTask.get(), outSrcDir) registerJavaGeneratingTask(genSrcTask.get(), outSrcDir)
outputs.all {
val output = this as ApkVariantOutputImpl
output.filters.forEach {
output.versionNameOverride += "-${it.identifier}"
}
}
} }
dependencies { dependencies {

View File

@ -9,6 +9,7 @@
android:name=".core.App" android:name=".core.App"
android:extractNativeLibs="true" android:extractNativeLibs="true"
android:icon="@drawable/ic_launcher" android:icon="@drawable/ic_launcher"
android:multiArch="true"
tools:ignore="UnusedAttribute,GoogleAppIndexingWarning"> tools:ignore="UnusedAttribute,GoogleAppIndexingWarning">
<!-- Splash --> <!-- Splash -->

View File

@ -7,8 +7,12 @@ import com.topjohnwu.magisk.BuildConfig
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
object Const { object Const {
val CPU_ABI: String = Build.SUPPORTED_ABIS[0] val CPU_ABI: String get() = Build.SUPPORTED_ABIS[0]
val CPU_ABI_32: String = Build.SUPPORTED_32_BIT_ABIS.firstOrNull() ?: CPU_ABI
// Null if 32-bit only or 64-bit only
val CPU_ABI_32 =
if (Build.SUPPORTED_64_BIT_ABIS.isEmpty()) null
else Build.SUPPORTED_32_BIT_ABIS.firstOrNull()
// Paths // Paths
lateinit var MAGISKTMP: String lateinit var MAGISKTMP: String

View File

@ -17,7 +17,6 @@ val isRunningAsStub get() = Info.stub != null
object Info { object Info {
var stub: DynAPK.Data? = null var stub: DynAPK.Data? = null
var stubArch = "lib/${Const.CPU_ABI}"
val EMPTY_REMOTE = UpdateInfo() val EMPTY_REMOTE = UpdateInfo()
var remote = EMPTY_REMOTE var remote = EMPTY_REMOTE

View File

@ -37,6 +37,7 @@ import java.io.*
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.security.SecureRandom import java.security.SecureRandom
import java.util.* import java.util.*
import java.util.zip.ZipEntry
import java.util.zip.ZipFile import java.util.zip.ZipFile
abstract class MagiskInstallImpl protected constructor( abstract class MagiskInstallImpl protected constructor(
@ -93,8 +94,14 @@ abstract class MagiskInstallImpl protected constructor(
// Extract binaries // Extract binaries
if (isRunningAsStub) { if (isRunningAsStub) {
val zf = ZipFile(DynAPK.current(context)) val zf = ZipFile(DynAPK.current(context))
// Also extract magisk32 on non 64-bit only 64-bit devices
val is32lib = Const.CPU_ABI_32?.let {
{ entry: ZipEntry -> entry.name == "lib/$it/libmagisk32.so" }
} ?: { false }
zf.entries().asSequence().filter { zf.entries().asSequence().filter {
!it.isDirectory && it.name.startsWith(Info.stubArch) !it.isDirectory && (it.name.startsWith("lib/${Const.CPU_ABI}/") || is32lib(it))
}.forEach { }.forEach {
val n = it.name.substring(it.name.lastIndexOf('/') + 1) val n = it.name.substring(it.name.lastIndexOf('/') + 1)
val name = n.substring(3, n.length - 3) val name = n.substring(3, n.length - 3)
@ -102,9 +109,17 @@ abstract class MagiskInstallImpl protected constructor(
zf.getInputStream(it).writeTo(dest) zf.getInputStream(it).writeTo(dest)
} }
} else { } else {
val libs = File(context.applicationInfo.nativeLibraryDir).listFiles { _, name -> val info = context.applicationInfo
var libs = File(info.nativeLibraryDir).listFiles { _, name ->
name.startsWith("lib") && name.endsWith(".so") name.startsWith("lib") && name.endsWith(".so")
} ?: emptyArray() } ?: emptyArray()
// Also symlink magisk32 on non 64-bit only 64-bit devices
val lib32 = info.javaClass.getDeclaredField("secondaryNativeLibraryDir").get(info) as String?
if (lib32 != null) {
libs += File(lib32, "libmagisk32.so")
}
for (lib in libs) { for (lib in libs) {
val name = lib.name.substring(3, lib.name.length - 3) val name = lib.name.substring(3, lib.name.length - 3)
Os.symlink(lib.path, "$installDir/$name") Os.symlink(lib.path, "$installDir/$name")

View File

@ -33,11 +33,7 @@ class BusyBoxInit : BaseShellInit() {
if (!shell.isRoot) if (!shell.isRoot)
return true return true
val jar = JarFile(DynAPK.current(context)) val jar = JarFile(DynAPK.current(context))
var bb = jar.getJarEntry("${Info.stubArch}/libbusybox.so") val bb = jar.getJarEntry("lib/${Const.CPU_ABI}/libbusybox.so")
if (bb == null) {
Info.stubArch = "lib/${Const.CPU_ABI_32}"
bb = jar.getJarEntry("${Info.stubArch}/libbusybox.so")
}
localBB = context.deviceProtectedContext.cachedFile("busybox") localBB = context.deviceProtectedContext.cachedFile("busybox")
localBB.delete() localBB.delete()
jar.getInputStream(bb).writeTo(localBB) jar.getInputStream(bb).writeTo(localBB)

View File

@ -347,19 +347,11 @@ def build_apk(args, module):
build_type = build_type.lower() build_type = build_type.lower()
if module == 'app': apk = f'{module}-{build_type}.apk'
for arch in archs + ['universal']: source = op.join(module, 'build', 'outputs', 'apk', build_type, apk)
apk = f'{module}-{arch}-{build_type}.apk' target = op.join(config['outdir'], apk)
source = op.join(module, 'build', 'outputs', 'apk', build_type, apk) mv(source, target)
target = op.join(config['outdir'], apk) header('Output: ' + target)
mv(source, target)
header('Output: ' + target)
else:
apk = f'{module}-{build_type}.apk'
source = op.join(module, 'build', 'outputs', 'apk', build_type, apk)
target = op.join(config['outdir'], apk)
mv(source, target)
header('Output: ' + target)
def build_app(args): def build_app(args):

View File

@ -1,4 +1,4 @@
APP_ABI := armeabi-v7a x86 arm64-v8a x86_64 APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
APP_CFLAGS := -Wall -Oz -fomit-frame-pointer -flto \ APP_CFLAGS := -Wall -Oz -fomit-frame-pointer -flto \
-D__MVSTR=${MAGISK_VERSION} -D__MCODE=${MAGISK_VER_CODE} -D__MVSTR=${MAGISK_VERSION} -D__MCODE=${MAGISK_VER_CODE}
APP_LDFLAGS := -flto APP_LDFLAGS := -flto

View File

@ -147,15 +147,22 @@ echo "RECOVERYMODE=$RECOVERYMODE" >> config
[ ! -z $SHA1 ] && echo "SHA1=$SHA1" >> config [ ! -z $SHA1 ] && echo "SHA1=$SHA1" >> config
# Compress to save precious ramdisk space # Compress to save precious ramdisk space
./magiskboot compress=xz magisk32 magisk32.xz SKIP32="#"
./magiskboot compress=xz magisk64 magisk64.xz SKIP64="#"
$IS64BIT && SKIP64="" || SKIP64="#" if [ -f magisk32 ]; then
./magiskboot compress=xz magisk32 magisk32.xz
unset SKIP32
fi
if [ -f magisk64 ]; then
./magiskboot compress=xz magisk64 magisk64.xz
unset SKIP64
fi
./magiskboot cpio ramdisk.cpio \ ./magiskboot cpio ramdisk.cpio \
"add 0750 init magiskinit" \ "add 0750 init magiskinit" \
"mkdir 0750 overlay.d" \ "mkdir 0750 overlay.d" \
"mkdir 0750 overlay.d/sbin" \ "mkdir 0750 overlay.d/sbin" \
"add 0644 overlay.d/sbin/magisk32.xz magisk32.xz" \ "$SKIP32 add 0644 overlay.d/sbin/magisk32.xz magisk32.xz" \
"$SKIP64 add 0644 overlay.d/sbin/magisk64.xz magisk64.xz" \ "$SKIP64 add 0644 overlay.d/sbin/magisk64.xz magisk64.xz" \
"patch" \ "patch" \
"backup ramdisk.cpio.orig" \ "backup ramdisk.cpio.orig" \

View File

@ -50,16 +50,15 @@ api_level_arch_detect
[ $API -lt 21 ] && abort "! Magisk only support Android 5.0 and above" [ $API -lt 21 ] && abort "! Magisk only support Android 5.0 and above"
ui_print "- Device platform: $ARCH" ui_print "- Device platform: $ABI"
BINDIR=$INSTALLER/lib/$ABILONG BINDIR=$INSTALLER/lib/$ABI
[ -d "$BINDIR" ] || BINDIR=$INSTALLER/lib/$ARCH32
[ -d "$BINDIR" ] || BINDIR=$INSTALLER/lib/armeabi-v7a
cd $BINDIR cd $BINDIR
for file in lib*.so; do mv "$file" "${file:3:${#file}-6}"; done for file in lib*.so; do mv "$file" "${file:3:${#file}-6}"; done
cd / cd /
chmod -R 755 $CHROMEDIR $BINDIR cp -af $INSTALLER/lib/$ABI32/libmagisk32.so $BINDIR/magisk32 2>/dev/null
cp -af $CHROMEDIR/. $BINDIR/chromeos cp -af $CHROMEDIR/. $BINDIR/chromeos
chmod -R 755 $BINDIR
# Check if system root is installed and remove # Check if system root is installed and remove
$BOOTMODE || remove_system_su $BOOTMODE || remove_system_su

View File

@ -55,16 +55,14 @@ ui_print "- Target image: $BOOTIMAGE"
# Detect version and architecture # Detect version and architecture
api_level_arch_detect api_level_arch_detect
ui_print "- Device platform: $ARCH" ui_print "- Device platform: $ABI"
BINDIR=$INSTALLER/lib/$ABILONG BINDIR=$INSTALLER/lib/$ABI
[ -d "$BINDIR" ] || BINDIR=$INSTALLER/lib/$ARCH32
[ -d "$BINDIR" ] || BINDIR=$INSTALLER/lib/armeabi-v7a
cd $BINDIR cd $BINDIR
for file in lib*.so; do mv "$file" "${file:3:${#file}-6}"; done for file in lib*.so; do mv "$file" "${file:3:${#file}-6}"; done
cd / cd /
chmod -R 755 $CHROMEDIR $BINDIR
cp -af $CHROMEDIR/. $BINDIR/chromeos cp -af $CHROMEDIR/. $BINDIR/chromeos
chmod -R 755 $BINDIR
############ ############
# Uninstall # Uninstall

View File

@ -519,17 +519,25 @@ remove_system_su() {
api_level_arch_detect() { api_level_arch_detect() {
API=$(grep_get_prop ro.build.version.sdk) API=$(grep_get_prop ro.build.version.sdk)
ABI=$(grep_get_prop ro.product.cpu.abi | cut -c-3) ABI=$(grep_get_prop ro.product.cpu.abi)
ABI2=$(grep_get_prop ro.product.cpu.abi2 | cut -c-3) if [ "$ABI" = "x86" ]; then
ABILONG=$(grep_get_prop ro.product.cpu.abi) ARCH=x86
ABI32=x86
ARCH=arm IS64BIT=false
ARCH32=arm elif [ "$ABI" = "arm64-v8a" ]; then
IS64BIT=false ARCH=arm64
if [ "$ABI" = "x86" ]; then ARCH=x86; ARCH32=x86; fi; ABI32=armeabi-v7a
if [ "$ABI2" = "x86" ]; then ARCH=x86; ARCH32=x86; fi; IS64BIT=true
if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; ARCH32=arm; IS64BIT=true; fi; elif [ "$ABI" = "x86_64" ]; then
if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; ARCH32=x86; IS64BIT=true; fi; ARCH=x64
ABI32=x86
IS64BIT=true
else
ARCH=arm
ABI=armeabi-v7a
ABI32=armeabi-v7a
IS64BIT=false
fi
} }
check_data() { check_data() {