M3UAndroid icon indicating copy to clipboard operation
M3UAndroid copied to clipboard

Reproducible Builds

Open IzzySoft opened this issue 1 year ago • 6 comments

I've checked your app if its build is reproducible (see: Reproducible bulds, special client support and more in our repo), but while I was able to successfully generate the APK using ./gradlew assembleRelease, there was a load of differences between the two APKs. Start of the APK diff:

-------------------------------
--- /dev/fd/63  2024-07-10 12:47:51.688719016 +0200
+++ /dev/fd/62  2024-07-10 12:47:51.688719016 +0200
@@ -327,7 +327,7 @@
   res/0c.9.png
   32-bit CRC value (hex):                         95bbccff
   res/0c.png
-  32-bit CRC value (hex):                         f5d1119a
+  32-bit CRC value (hex):                         4dbb75d0
   res/0n.png
   32-bit CRC value (hex):                         c81c99e6
   res/0x.9.png
@@ -393,7 +393,7 @@
   res/2x.xml
   32-bit CRC value (hex):                         4d5f6c8c
   res/3-.png
-  32-bit CRC value (hex):                         a81955ac
+  32-bit CRC value (hex):                         44766c30
   res/33.9.png
   32-bit CRC value (hex):                         c5fedfaf
   res/35.png
@@ -415,7 +415,7 @@
   res/3u.9.png
   32-bit CRC value (hex):                         cff461f2
   res/3z.png
-  32-bit CRC value (hex):                         bd731efa
+  32-bit CRC value (hex):                         bab49c82
   res/3z1.png
   32-bit CRC value (hex):                         55f5805d
   res/42.9.png
@@ -447,7 +447,7 @@
…

Seems like all the differences were caused by assets (here: PNG), while not all of the PNGs had differences. Which might indicate your build process uses some "crunching" mechanism; those are non-deterministic and hence lead to different results on each run.

We'd appreciate if you could help making your build reproducible. We've prepared some hints on reproducible builds for that. If my guess here is right, you should especially look at the section on "Compressing images" – and the following addition to your build.gradle could cure this:

android {
    aaptOptions {
        cruncherEnabled = false
    }
}

Though I see you already have isCrunchPngs = false set; I'm no Android dev so I cannot tell how the two are related (or if the all section is also applied to the 2 sections above).

Looking forward to your reply!

IzzySoft avatar Aug 03 '24 18:08 IzzySoft

@oxyroid you're still around? Any word on the above?

IzzySoft avatar Aug 14 '24 12:08 IzzySoft

I have less time to pay my attention in the repos recently. 🥲

oxyroid avatar Aug 14 '24 13:08 oxyroid

Eh, that happens. And I didn't exactly expect everyone to jump when I open an issue. I was just hoping for some reaction – so thanks for giving it! Now I know you're aware of the problem, but currently have no time to dig in (totally fair). Can you give me any ETA? Is it fine to give you a heads-up here from time to time (maybe once a month or so)?

IzzySoft avatar Aug 14 '24 14:08 IzzySoft

sry I can't.

oxyroid avatar Aug 14 '24 14:08 oxyroid

I'm stuck in a busy job in a busy department at a busy company.

oxyroid avatar Aug 14 '24 14:08 oxyroid

OK, no worries. Hope its OK for you if I send a friendly heads-up from time to time (not more often than once a month)?

IzzySoft avatar Aug 14 '24 20:08 IzzySoft

I assume the busy-bees are still keeping you busy?

IzzySoft avatar Nov 03 '24 23:11 IzzySoft

Ah, a new release! But oh, it got more complicated:

  -rw-r--r--  0.0 unx       56 b-       52 defN 1981-01-01 01:01:02 05cd8676 META-INF/com/android/build/gradle/app-metadata.properties
- -rw-r--r--  0.0 unx     9423 b-     9423 stor 1981-01-01 01:01:02 d6d4af58 assets/dexopt/baseline.prof
+ -rw-r--r--  0.0 unx     9423 b-     9423 stor 1981-01-01 01:01:02 683d7ae5 assets/dexopt/baseline.prof
  -rw-r--r--  0.0 unx     1036 b-     1036 stor 1981-01-01 01:01:02 a8d037c8 assets/dexopt/baseline.profm
- -rw-r--r--  0.0 unx  9783488 b-  4431016 defN 1981-01-01 01:01:02 486ab654 classes.dex
+ -rw-r--r--  0.0 unx  9783488 b-  4431017 defN 1981-01-01 01:01:02 691b20f3 classes.dex
  -rw-r--r--  0.0 unx  4702512 b-  1885053 defN 1981-01-01 01:01:02 59eda247 classes2.dex
  -rw-r--r--  0.0 unx    10096 b-    10096 stor 1981-01-01 01:01:02 9734baa0 lib/arm64-v8a/libandroidx.graphics.path.so
  -rw-r--r--  0.0 unx  4025264 b-  4025264 stor 1981-01-01 01:01:02 65a4761f lib/arm64-v8a/libavcodec.so
@@ -319,7 +319,6 @@
  -rw----     0.0 fat      658 b-      658 stor 1981-01-01 01:01:02 50ee6e75 res/5v1.png
  -rw----     0.0 fat      228 b-      228 stor 1981-01-01 01:01:02 8210f539 res/5w.png
  -rw----     0.0 fat      553 b-      553 stor 1981-01-01 01:01:02 73ee1c5d res/5y.png
- -rw----     0.0 fat   158240 b-    70753 defN 1981-01-01 01:01:02 96e21ded res/5z.ttf
  -rw----     0.0 fat     1128 b-      395 defN 1981-01-01 01:01:02 0553f94a res/5z.xml
  -rw----     0.0 fat     1633 b-     1633 stor 1981-01-01 01:01:02 7ed7d2b3 res/6-.png
  -rw----     0.0 fat      796 b-      358 defN 1981-01-01 01:01:02 bc60ca5c res/61.xml
@@ -1278,7 +1277,7 @@
  -rw----     0.0 fat      648 b-      648 stor 1981-01-01 01:01:02 e3a292db res/W51.png
  -rw----     0.0 fat      700 b-      276 defN 1981-01-01 01:01:02 cbd12084 res/W8.xml
  -rw----     0.0 fat      792 b-      792 stor 1981-01-01 01:01:02 cd6c6bda res/W9.png
- -rw----     0.0 fat     1736 b-      368 defN 1981-01-01 01:01:02 01846845 res/W9.xml
+ -rw----     0.0 fat     1736 b-      368 defN 1981-01-01 01:01:02 6840d983 res/W9.xml
  -rw----     0.0 fat      396 b-      396 stor 1981-01-01 01:01:02 f3a2968a res/WA.png
  -rw----     0.0 fat      388 b-      388 stor 1981-01-01 01:01:02 c753e16d res/WA1.png
  -rw----     0.0 fat       67 b-       67 stor 1981-01-01 01:01:02 88b2a3b0 res/WB.png
@@ -2686,5 +2685,5 @@
  -rw----     0.0 fat      249 b-      249 stor 1981-01-01 01:01:02 72a34e93 res/zv.png
  -rw----     0.0 fat      435 b-      435 stor 1981-01-01 01:01:02 cc705e7f res/zz.png
  -rw----     0.0 fat       67 b-       67 stor 1981-01-01 01:01:02 88b2a3b0 res/zz1.png
- -rw----     0.0 fat  2086148 b-  2086148 stor 1981-01-01 01:01:02 8b014e1f resources.arsc
+ -rw----     0.0 fat  2086088 b-  2086088 stor 1981-01-01 01:01:02 d383df68 resources.arsc

As there's no vcsInfo included with the build, I cannot tell for sure – but either we've built from different commits (I've build from the one the tag points to), or we used different build instructions. I've basically oriented at your workflow and the target APK, so this is the recipe I've used:

        build:
          - sed -r '/signingConfigs.getByName/d' -i androidApp/build.gradle.kts
          - sed -r 's/isUniversalApk = true/isUniversalApk = false/ ; s/include\("x86", "x86_64", "arm64-v8a", "armeabi-v7a"\)/include("arm64-v8a")/' -i androidApp/build.gradle.kts
          - chmod +x gradlew
          - ./gradlew assembleStableChannelRichCodecRelease
          - mv androidApp/build/outputs/apk/stableChannelRichCodec/release/*_arm64-v8a.apk /outputs/unsigned.apk

Line 1 disables signing, line 2 makes sure only the needed APK is produced (to not unnecessarily waste resources).

The diff of classes.dex is rather small:

 |: invoke-virtual {v10, v11}, Landroid/widget/ImageView;.setImageDrawable:(Landroid/graphics/drawable/Drawable;)V
 |: invoke-virtual {v10, v5}, Landroid/view/View;.setOnClickListener:(Landroid/view/View$OnClickListener;)V
-|: const v11, #float 1.82105e+38 // #7f090010
+|: const v11, #float 1.82105e+38 // #7f09000f
 |: invoke-static {v1, v11}, Lx3/o;.a:(Landroid/content/Context;I)Landroid/graphics/Typeface;

But I've no clue where that TTF in your APK came from if it's not in mine… In case it matters: I built with OpenJDK-17 on Debian bookworm.

Any hints?

IzzySoft avatar Jan 01 '25 21:01 IzzySoft

Maybe I should consider to generate these config files in CI/CD. I generate them on my local computer is a bit unreliable. :(

oxyroid avatar Jan 02 '25 08:01 oxyroid

Glad to see you already have an idea :hugs: We can give it another try anytime, all I'd need is an APK built from a clean tree, so I can build from the same commit to compare.

IzzySoft avatar Jan 02 '25 10:01 IzzySoft

Not sure what your idea was… I've just tried v1.15.0, and the diff got bigger again:

  -rw-r--r--  0.0 unx      120 b-      117 defN 1981-01-01 01:01:02 59466db9 META-INF/version-control-info.textproto
- -rw-r--r--  0.0 unx    13715 b-    13715 stor 1981-01-01 01:01:02 ad648647 assets/dexopt/baseline.prof
- -rw-r--r--  0.0 unx      662 b-      662 stor 1981-01-01 01:01:02 843ae5be assets/dexopt/baseline.profm
- -rw-r--r--  0.0 unx  2751296 b-  1347909 defN 1981-01-01 01:01:02 4b955835 classes.dex
- -rw-r--r--  0.0 unx  8648148 b-  3804334 defN 1981-01-01 01:01:02 4572db08 classes2.dex
- -rw-r--r--  0.0 unx  3187320 b-  1233162 defN 1981-01-01 01:01:02 1547c4cf classes3.dex
+ -rw-r--r--  0.0 unx     9743 b-     9743 stor 1981-01-01 01:01:02 315e6139 assets/dexopt/baseline.prof
+ -rw-r--r--  0.0 unx     1467 b-     1467 stor 1981-01-01 01:01:02 cc36edc5 assets/dexopt/baseline.profm
+ -rw-r--r--  0.0 unx  9569740 b-  4335282 defN 1981-01-01 01:01:02 6b56a9f9 classes.dex
+ -rw-r--r--  0.0 unx  4720048 b-  1882105 defN 1981-01-01 01:01:02 b27537ed classes2.dex
  -rw-r--r--  0.0 unx    10096 b-    10096 stor 1981-01-01 01:01:02 9734baa0 lib/arm64-v8a/libandroidx.graphics.path.so
  -rw-r--r--  0.0 unx  4025264 b-  4025264 stor 1981-01-01 01:01:02 65a4761f lib/arm64-v8a/libavcodec.so
  -rw-r--r--  0.0 unx   593224 b-   593224 stor 1981-01-01 01:01:02 5f5584f5 lib/arm64-v8a/libavutil.so
@@ -50,15 +49,15 @@
  -rw----     2.0 fat     1140 b-      577 defN 1981-01-01 01:01:02 818edc9a META-INF/ktor-utils.kotlin_module
  -rw----     2.0 fat       88 b-       67 defN 1981-01-01 01:01:02 fe471c6c META-INF/ktor-websocket-serialization.kotlin_module
  -rw----     2.0 fat      355 b-      195 defN 1981-01-01 01:01:02 49a47298 META-INF/ktor-websockets.kotlin_module
- -rw----     2.0 fat        5 b-        7 defN 1981-01-01 01:01:02 c2313d69 META-INF/services/S6.a
+ -rw----     2.0 fat        5 b-        7 defN 1981-01-01 01:01:02 ff5114d9 META-INF/services/R6.a
  -rw----     2.0 fat       77 b-       61 defN 1981-01-01 01:01:02 855d9f6e META-INF/services/io.ktor.serialization.kotlinx.KotlinxSerializationExtensionProvider
  -rw----     2.0 fat       40 b-       37 defN 1981-01-01 01:01:02 b667f565 META-INF/services/io.ktor.server.config.ConfigLoader
  -rw----     2.0 fat       91 b-       74 defN 1981-01-01 01:01:02 75f1aa42 META-INF/services/kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoader
  -rw----     2.0 fat      236 b-       99 defN 1981-01-01 01:01:02 218b615c META-INF/services/kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition
  -rw----     2.0 fat       57 b-       55 defN 1981-01-01 01:01:02 43ef89c5 META-INF/services/reactor.blockhound.integration.BlockHoundIntegration
- -rw----     2.0 fat        5 b-        7 defN 1981-01-01 01:01:02 b1d0ce7d META-INF/services/t6.a
- -rw----     2.0 fat        5 b-        7 defN 1981-01-01 01:01:02 00e2b9ed META-INF/services/u8.A
- -rw----     2.0 fat        5 b-        7 defN 1981-01-01 01:01:02 2bcfea2e META-INF/services/v8.a
+ -rw----     2.0 fat        5 b-        7 defN 1981-01-01 01:01:02 03f0126d META-INF/services/s6.a
+ -rw----     2.0 fat        5 b-        7 defN 1981-01-01 01:01:02 7a22ea8d META-INF/services/s8.z
+ -rw----     2.0 fat        5 b-        7 defN 1981-01-01 01:01:02 510fb94e META-INF/services/t8.a
  -rw----     2.0 fat       88 b-       70 defN 1981-01-01 01:01:02 2a940232 META-INF/ui_release.kotlin_module
  -rw----     2.0 fat       52 b-       41 defN 1981-01-01 01:01:02 caf6e848 custom.config.conf
  -rw----     2.0 fat       42 b-       35 defN 1981-01-01 01:01:02 45c23b63 custom.config.yaml
@@ -80,7 +79,7 @@
  -rw----     2.0 fat   127010 b-    38582 defN 1981-01-01 01:01:02 af9d74ef org/fusesource/jansi/internal/native/Windows/x86_64/jansi.dll
  -rw----     2.0 fat       14 b-       16 defN 1981-01-01 01:01:02 98cc3806 org/fusesource/jansi/jansi.properties
  -rw----     2.0 fat      935 b-      221 defN 1981-01-01 01:01:02 e6b54850 org/fusesource/jansi/jansi.txt
- -rw----     0.0 fat    20316 b-     4430 defN 1981-01-01 01:01:02 a8c37ebe AndroidManifest.xml
+ -rw----     0.0 fat    20344 b-     4443 defN 1981-01-01 01:01:02 8793d117 AndroidManifest.xml
  -rw----     0.0 fat      744 b-      345 defN 1981-01-01 01:01:02 0f30c0af res/-1.xml

I've built the arm64 variant only, disabling the others (I can only compare 1 file against 1 file, so why build them all?). As a result, now even the versionName differs:

       ATTR: http://schemas.android.com/apk/res/android:versionCode=144
-      ATTR: http://schemas.android.com/apk/res/android:versionName='1.15.0'
+      ATTR: http://schemas.android.com/apk/res/android:versionName='1.15.0_arm64-v8a.apk'
       ATTR: http://schemas.android.com/apk/res/android:compileSdkVersion=35

The DEX files I don't even need to diff: a look at their file sizes tells enough.

Do you see any chance that we get that aligned? Any chance I can build an arm64 APK that matches yours – without building all the others along, wasting resources on them?

IzzySoft avatar Mar 31 '25 00:03 IzzySoft

@oxyroid any word?

IzzySoft avatar Apr 27 '25 13:04 IzzySoft

Later I will improve the building automation and keep the builds reproducible

oxyroid avatar Apr 27 '25 13:04 oxyroid

Any ETA, so I don't ping you unnecessarily every now and then?

IzzySoft avatar Apr 27 '25 16:04 IzzySoft