Corregge i simboli nativi AAB in formato .so.sym per Play Console.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-05 19:45:29 +02:00
co-authored by Cursor
parent 5daada81b0
commit b8694a6b7b
+48 -10
View File
@@ -1,3 +1,4 @@
import java.io.File
import java.util.Properties
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
@@ -23,8 +24,8 @@ android {
applicationId = "com.matchlivetv.match_live_tv"
minSdk = 24
targetSdk = 36
versionCode = 30
versionName = "2.0.9-native"
versionCode = 31
versionName = "2.0.10-native"
val apiBaseUrl = project.findProperty("API_BASE_URL") as String?
?: "https://www.matchlivetv.it"
@@ -122,11 +123,21 @@ dependencies {
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
}
// Play Console: le .so prebuilt (AndroidX) sono già stripped → AGP non aggiunge
// BUNDLE-METADATA/com.android.tools.build.debugsymbols. Incorporiamo un zip ABI/.so
// nell'intermediary bundle prima della firma.
// Play Console: le .so prebuilt (AndroidX) sono già stripped → AGP salta l'estrazione
// (niente BUNDLE-METADATA/com.android.tools.build.debugsymbols). Generiamo i .so.sym
// come fa AGP (llvm-objcopy --strip-debug) e li iniettiamo nell'intermediary AAB.
fun findLlvmObjcopy(): File {
val ndkRoot = File(android.sdkDirectory, "ndk")
val ndkDirs = ndkRoot.listFiles()?.filter { it.isDirectory }?.sortedByDescending { it.name }.orEmpty()
for (ndk in ndkDirs) {
val candidate = ndk.resolve("toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objcopy")
if (candidate.isFile) return candidate
}
error("llvm-objcopy non trovato sotto ${ndkRoot.absolutePath}")
}
val injectNativeDebugSymbolsInReleaseBundle by tasks.registering {
description = "Embed native-debug-symbols.zip into the release AAB intermediary"
description = "Embed native-debug-symbols.zip (.so.sym) into the release AAB intermediary"
val mergeNative = tasks.named("mergeReleaseNativeLibs")
val packageBundle = tasks.named("packageReleaseBundle")
dependsOn(mergeNative, packageBundle)
@@ -157,15 +168,40 @@ val injectNativeDebugSymbolsInReleaseBundle by tasks.registering {
require(libsDir.isDirectory) { "Native libs missing: $libsDir" }
require(aabFile.isFile) { "Intermediary AAB missing: $aabFile" }
val objcopy = findLlvmObjcopy()
val workDir = layout.buildDirectory.dir("tmp/native-debug-symbols-inject").get().asFile
workDir.deleteRecursively()
workDir.mkdirs()
val symbolsRoot = workDir.resolve("symbols")
symbolsRoot.mkdirs()
var count = 0
libsDir.walkTopDown().filter { it.isFile && it.extension == "so" }.forEach { so ->
val rel = so.relativeTo(libsDir).invariantSeparatorsPath
val outRel = "$rel.sym"
val outFile = symbolsRoot.resolve(outRel)
outFile.parentFile.mkdirs()
// Allineato ad AGP SYMBOL_TABLE: llvm-objcopy --strip-debug → *.so.sym
val proc = ProcessBuilder(
objcopy.absolutePath,
"--strip-debug",
so.absolutePath,
outFile.absolutePath,
).redirectErrorStream(true).start()
val out = proc.inputStream.bufferedReader().readText()
check(proc.waitFor() == 0) {
"objcopy failed for $rel: $out"
}
count++
}
check(count > 0) { "Nessuna .so da cui generare simboli in $libsDir" }
val symbolsZip = workDir.resolve("native-debug-symbols.zip")
ZipOutputStream(symbolsZip.outputStream().buffered()).use { zos ->
libsDir.walkTopDown().filter { it.isFile && it.extension == "so" }.forEach { so ->
val rel = so.relativeTo(libsDir).invariantSeparatorsPath
symbolsRoot.walkTopDown().filter { it.isFile }.forEach { f ->
val rel = f.relativeTo(symbolsRoot).invariantSeparatorsPath
zos.putNextEntry(ZipEntry(rel))
so.inputStream().use { it.copyTo(zos) }
f.inputStream().use { it.copyTo(zos) }
zos.closeEntry()
}
}
@@ -192,7 +228,9 @@ val injectNativeDebugSymbolsInReleaseBundle by tasks.registering {
}
}
outAab.copyTo(aabFile, overwrite = true)
logger.lifecycle("Injected $metaPath (${symbolsZip.length()} bytes) into ${aabFile.name}")
logger.lifecycle(
"Injected $metaPath ($count .so.sym, ${symbolsZip.length()} bytes) into ${aabFile.name} via ${objcopy.name}",
)
}
}