-
-
Notifications
You must be signed in to change notification settings - Fork 64
Reproducible build #400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Yes, I'll try to complete the actions setup right away. I remember getting multiple OutOfMemoryError building the APK in the GitHub server, causing me to fall back to my local machine for building the APK files. |
Ah, thanks! That explains my confusion. I was able to build the app with our setup here (if you have a Linux machine or VM at hand, you can establish that environment in probably less than 5 minutes using our rbuilder_setup scripts, which we already successfully tested on Debian systems (Debian bookworm/bullseye and Ubuntu jammy/noble) and have a PR ready for testing on RPM based ones (RHEL, Fedora, Rocky & Co) – I gladly share my build recipe with you for that). |
I do have a local Linux server and your provided repo would be a great start for it, thanks for that!! |
What distribution is the Linux server running? And, I'd be very very glad & thankful for feedback shared about the setup (and operation then). We're still working on making the latter easier (my next steps will be improving the rbhelper package which the installer offers to set up as well, and then to update/create proper documentation). Feedback "from outside" would be very valuable for that! |
Here's my build recipe for Inure: ---
repository: https://github.com/Hamza417/Inure.git
updates: releases
versions:
- tag: build103.1.1
apks:
- apk_pattern: app-github-release\.apk
apk_url: https://github.com/Hamza417/Inure/releases/download/build103.1.1/app-github-release.apk
build:
- chmod +x gradlew
- ./gradlew assembleGithubRelease
- mv app/build/outputs/apk/github/release/*unsigned.apk /outputs/unsigned.apk
build_cpus:
build_home_dir: /home/runner
build_repo_dir: /home/runner/work/Inure/Inure
build_timeout:
build_user: build
provisioning:
android_home: /opt/sdk
build_tools:
cmake:
cmdline_tools:
version: '12.0'
url: https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
sha256: 2d2d50857e4eb553af5a6dc3ad507a17adf43d115264b1afc116f95c92e5e258
extra_packages: []
image: ubuntu:noble
jdk: openjdk-17-jdk-headless
ndk:
platform:
platform_tools:
tools:
verify_gradle_wrapper: true (empty values using defaults; I'm keeping those declarations in to have them easily available in case they are needed, e.g. with a later release. And I've set |
I have updated the actions file, and the build should now be generated in a Linux environment from now on. Also, yes I did set up and ran your scripts in my Ubuntu server (noble) and found the process of setting it up a breeze, and it helped me a lot into finding the source of the issue. I haven't formed any opinion about it, but yeah, using trydiffoscope was troublesome because the server kept timing out on my request and I had to set up the diffoscope locally and compare the APKs. Other than that, it was good. Thanks for helping me out on this one :) I did a thorough study on this and managed to make the Inure fully reproducible, or at least that's what my result says. Could you please check the diffoscope report and let me know if it's identical now? I had compared two signed APKs, so the signature mismatched (expected) but classes and resources are identical on two separate builds. |
Wonderful!
🤩 Thanks for that lovely feedback! Much appreciated. Glad to see a goal achieved 🥳
So it's not only me… It worked fine a while ago, but lately seems to permanently time out.
You've seen the note about the diffoscope image for Podman and how to operate that? Maybe we should make that more obvious, if you missed it.
It looks like it is. To be absolutely sure, could you provide me an APK and name the corresponding commit? You can attach the APK here after renaming it to Btw: the builder should show you whether the file was RB. Well, time to get the documentation up to sniff I guess, but we cannot do everything at the same time unfortunately… |
It's built on this commit: f2b7d66 |
Funny. Looks like now signing is enforced even if the keystore does not exist (I didn't place any):
which is strange, as this line should take care the corresponding block is not even called when the file does not exist. Guess it should be set to Adding - -rw-r--r-- 0.0 unx 7264 b- 7264 stor 1981-01-01 01:01:02 2747909b lib/arm64-v8a/libinure_su.so
- -rw-r--r-- 0.0 unx 1388080 b- 1388080 stor 1981-01-01 01:01:02 7c7ae7e2 lib/arm64-v8a/libinure_terminal_emulator.so
+ -rw-r--r-- 0.0 unx 7192 b- 7192 stor 1981-01-01 01:01:02 f5b5a084 lib/arm64-v8a/libinure_su.so
+ -rw-r--r-- 0.0 unx 1387720 b- 1387720 stor 1981-01-01 01:01:02 0931087b lib/arm64-v8a/libinure_terminal_emulator.so
-rw-r--r-- 0.0 unx 387256 b- 387256 stor 1981-01-01 01:01:02 c14c01f1 lib/arm64-v8a/librenderscript-toolkit.so
- -rw-r--r-- 0.0 unx 5692 b- 5692 stor 1981-01-01 01:01:02 a6b77094 lib/armeabi-v7a/libinure_su.so
- -rw-r--r-- 0.0 unx 810664 b- 810664 stor 1981-01-01 01:01:02 6176f3ed lib/armeabi-v7a/libinure_terminal_emulator.so
+ -rw-r--r-- 0.0 unx 5620 b- 5620 stor 1981-01-01 01:01:02 d18ddcf6 lib/armeabi-v7a/libinure_su.so
+ -rw-r--r-- 0.0 unx 810304 b- 810304 stor 1981-01-01 01:01:02 3e1d62c8 lib/armeabi-v7a/libinure_terminal_emulator.so
-rw-r--r-- 0.0 unx 251596 b- 251596 stor 1981-01-01 01:01:02 cbd89bb1 lib/armeabi-v7a/librenderscript-toolkit.so
- -rw-r--r-- 0.0 unx 5784 b- 5784 stor 1981-01-01 01:01:02 42e41388 lib/x86/libinure_su.so
- -rw-r--r-- 0.0 unx 1049384 b- 1049384 stor 1981-01-01 01:01:02 4c457021 lib/x86/libinure_terminal_emulator.so
+ -rw-r--r-- 0.0 unx 5712 b- 5712 stor 1981-01-01 01:01:02 6256a591 lib/x86/libinure_su.so
+ -rw-r--r-- 0.0 unx 1049024 b- 1049024 stor 1981-01-01 01:01:02 9f7d23fd lib/x86/libinure_terminal_emulator.so
-rw-r--r-- 0.0 unx 321232 b- 321232 stor 1981-01-01 01:01:02 4e1d41d2 lib/x86/librenderscript-toolkit.so
- -rw-r--r-- 0.0 unx 6920 b- 6920 stor 1981-01-01 01:01:02 c0a01cc3 lib/x86_64/libinure_su.so
- -rw-r--r-- 0.0 unx 1243896 b- 1243896 stor 1981-01-01 01:01:02 553134ad lib/x86_64/libinure_terminal_emulator.so
+ -rw-r--r-- 0.0 unx 6848 b- 6848 stor 1981-01-01 01:01:02 57aeea86 lib/x86_64/libinure_su.so
+ -rw-r--r-- 0.0 unx 1243576 b- 1243576 stor 1981-01-01 01:01:02 7619ae3a lib/x86_64/libinure_terminal_emulator.so
-rw-r--r-- 0.0 unx 354768 b- 354768 stor 1981-01-01 01:01:02 9f8e8758 lib/x86_64/librenderscript-toolkit.so Which cmake version are you using? Without specifying any, here it uses |
I did use the same recipe, and It's built using the same CMake version
What's interesting is if .so files are what's breaking the RB, then why is |
BuildIDs differ. Because: Different build path. I could match that by setting PS: I see you found the same already. I'll revert my change after verifying. I just want to make sure it's not something else in addition. |
It's interesting that actions used Here's the build recipe I used, I changed the path to ---
repository: https://github.com/Hamza417/Inure.git
updates: releases
versions:
- tag: build103.1.1
apks:
- apk_pattern: app-github-release\.apk
apk_url: https://github.com/Hamza417/Inure/releases/download/build103.1.1/app-github-release.apk
build:
- chmod +x gradlew
- ./gradlew assembleGithubRelease
- mv app/build/outputs/apk/github/release/*unsigned.apk /outputs/unsigned.apk
build_cpus:
build_home_dir: /home/runner
build_repo_dir: /home/runner/work/Inure/Inure
build_timeout:
build_user: build
provisioning:
android_home: /usr/local/lib/android/sdk
build_tools:
cmake:
cmdline_tools:
version: '12.0'
url: https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip
sha256: 2d2d50857e4eb553af5a6dc3ad507a17adf43d115264b1afc116f95c92e5e258
extra_packages: []
image: ubuntu:noble
jdk: openjdk-21-jdk-headless
ndk:
platform:
platform_tools:
tools:
verify_gradle_wrapper: true |
|
I have updated the actions workflow to use I think it's safe to close #399 now as well. |
OK, so we stay with |
Yes, next release should be RB, can you do what is necessary if Inure needs to be marked reproducible on F-Droid? |
@Hamza417 note that this will cover @IzzySoft's repo only for F-Droid... since users already have your app, to switch, they'll need to uninstall and reainstall the newer RB versions. There's no "upgrade" path you'd want that? /LE: first of all they'd need to find out they have to do this, while we announce these in https://f-droid.org/news/ (RSS too) and https://floss.social/@fdroidorg our reach is still rather limited. There are ideas about integrating this is Client, but no concrete proposals |
It'd be an inconvenience for them for sure, unless the signature is changed on F-Droid, why'd the users need to uninstall before installing? I am a bit lost here, so could you explain this please, and what is the best course of action here?
I can also notify the users through my ends like notifying about this in the group and through the app's GitHub repo. |
right now, in F-Droid, the APK is signed by F-Droid. with reproducible builds (if confirmed verified), we'll host your own signed APK (eg. https://github.com/Hamza417/Inure/releases/tag/build103.1.1 -> app-github-release.apk ) per the graph in https://f-droid.org/docs/Reproducible_Builds/ branches YES - YES Android security protection does not allow updating a package with a different signature. |
Summing up:
|
Understandable! It'd be best to keep the signature consistent throughout the repositories. I'll mention this in changelogs and notify everyone about this beforehand. |
Sounds good to me. @licaon-kter what do you think? How much "preparation time" on your end so @Hamza417 doesn't send out the notification "too early"? Or maybe just mention it "for the next release", once LK confirmed F-Droid has their RB recipe ready? |
"for the next release" sounds good enough 👍 |
@Hamza417 missed to reply to your comment, apologies! Asking @licaon-kter / @linsui to correct me should that have been fixed already, but at F-Droid.org it will be difficult to remove screenshots later. You can replace them there easily with new variants using the exact same names, but should you later reduce their number, some of the "old once" will stick there. At IzzyOnDroid, screenshots will be optimized at import (resized if too large, and also compressed). Still, the resulting screenshot files sum up to over 1 MB – which will be downloaded to each client looking at the app details. Considering bandwidth (especially for devices on "low-end plans", but also in general considering the environment), this still might pose an issue. To not get me wrong: I don't try to "regulate" here, I'm just "voicing concerns". Decision remains yours. I just feel the need to advise, so you can make an informed decision 😉 |
Yep, it's harder to change the path. We need to move things around. Not difficule but verbose and ugly. And I prefer to have less requirement for reproducible build. It's better if we can make it reproducible with any folder layout.
It needs to be removed manually. |
There is a folder name in .cxx is different. According to the hash_key.txt file in it:
If I understand it correctly, if we put the cFlags in gradle this hash is affected so we should put it in the cmake file instead. |
- Added `-ffile-prefix-map` to remove absolute paths from debug info. - Enabled `--hash-style=gnu` for improved ELF symbol lookup performance. - Disabled `--build-id` to ensure fully reproducible builds.
You can add them with |
Yes, you can get the APK from here: https://github.com/Hamza417/Inure/actions/runs/14134722583
EDIT: rebooting the server fixed it, I am building an APK now in rblog. |
- Added `-ffile-prefix-map` to remove absolute paths from debug info. - Enabled `--hash-style=gnu` for improved ELF symbol lookup performance. - Disabled `--build-id` to ensure fully reproducible builds.
I thought it should be add_compile_options("-ffile-prefix-map=${CMAKE_SOURCE_DIR}= -ffile-prefix-map=$ENV{ANDROID_HOME}=")
add_link_options("LINKER:--hash-style=gnu,--build-id=none") Not sure if it works without the quotes. |
It works but it's not enough... We need to replace the root path of this repo because some paths are not in CMAKE_SOURCE_DIR. I guess we need to use https://cmake.org/cmake/help/latest/command/cmake_path.html#get-parent-path. |
Thanks for clarification, @linsui – added that to our notes with a link to your comment. Please update me if it turns out that needs to be adjusted, so I can then replace it with the final variant. (And following the discussion, I'm not sure where it's harder to change the path: in the YAML, or with
@Hamza417 I'll leave that to you and linsui then. At IoD, currently all screenshots have been pulled – but they will be cleaned automatically when you remove them on your end. Only exception where that currently fails on our end is if you only change the file extension (e.g. |
I hope we can make the build path configurable soon.
This is new to me... Generally it's enough to add flags in gradle. Still, I thought it's better to make it reproducible even in a different build environment. :) |
- Added `-ffile-prefix-map` to remove absolute paths from debug info. - Enabled `--hash-style=gnu` for improved ELF symbol lookup performance. - Disabled `--build-id` to ensure fully reproducible builds.
- Dynamically determine the project root using `cmake_path(GET ... PARENT_PATH)`. - Added `-ffile-prefix-map` to remove absolute paths from debug info. - Enabled `--hash-style=gnu` for improved ELF symbol lookup performance. - Disabled `--build-id` to ensure fully reproducible builds.
@linsui yeah, and life's a bitch sometimes, adding unexpected things to reality unfortunately. How was that old Chinese curse: "May you live in interesting times?" Well, I sometimes wish for boring ones now… So yeah, wherever the course goes. Wish you luck there. If that path ends at a wall, a configurable path (as rbtlog supports it) would be the way to go. Though I agree, "reproducible even in a different build environment" would be good – hope the price isn't too high there… |
- Added `-ffile-prefix-map` and `-fdebug-prefix-map` flags. - Added linker flags to strip debug symbols from the final release build.
You can check the report: report.zip w.apk is windows one and l.ap is what I had built in GitHub actions (Ubuntu) The permission.txt is something happened first time, probably by how line separators works in different build environments? That's something I can deal with a little bit more investigation. You can get the new APK file from here: https://github.com/Hamza417/Inure/actions/runs/14139120293 Please check it now 🤞🏻 |
It works. :) Thanks! Yep, strip helps a lot. |
Confirmed here as well, without any changes to the recipe on our end: {
"upstream_signed_apk_sha256": "bbfed552e71f1eb8268b1bdd544371328891680fc4112c499b5191ab9a30a0ac",
"built_unsigned_apk_sha256": "fc967bf2afd87b455e44ef14adafdf6fd5243d938af2ce33cdfb0d9f389aba80",
"signature_copied_apk_sha256": "bbfed552e71f1eb8268b1bdd544371328891680fc4112c499b5191ab9a30a0ac"
} |
PS: could someone please sum up what changes were needed in the end, so we can document that properly? Would be good if we can suggest a "one fits all" solution (as we've shown, we all pull the same rope here 😉). |
Besides the known tricks in https://f-droid.org/docs/Reproducible_Builds/, strip can remove lots of unreproducible bits. |
OK, so making my question a little more precise: Different build pathsIf there are differences in embedded paths, this is what one should start with. Having used the defaults of our recipes, one most likely used build_home_dir: /home/runner
build_repo_dir: /home/runner/work/<repoName>/<repoName>
build_user: runner
provisioning:
android_home: /usr/local/lib/android/sdk For other variables used in GH images, see e.g. here. Also check the linsui points out that the embedded externalNativeBuild {
cmake {
cFlags "-ffile-prefix-map=${rootDir}= -ffile-prefix-map=${System.getenv("ANDROID_HOME")}= -Wl,--hash-style=gnu,--build-id=none"
cppFlags "-ffile-prefix-map=${rootDir}= -ffile-prefix-map=${System.getenv("ANDROID_HOME")}= -Wl,--hash-style=gnu,--build-id=none"
}
} Build IDs...This is from the documentation I'm currently writing on analyzing/fixing RBs with our builder setup. The last block with "linsui points out" is what I've added from here. Is that sufficient for this part, or what extra steps were taken? If we want to include that approach, it should have all steps. For our builders, the first variant suffices – but it would be nice to have the second variant to fit yours as well, don't you agree? 😉 |
I prefer to remove those bits depending on the build environment, which is mainly embeded absolute path. And the build-id is also affected by the build path which is a hash of them. The absolute path can be removed by |
I know – in ours as well 😉 E.g. build-id comes in the next section, as you can see. And yes, hash style is mentioned as well. (And yes, I know that different build paths can lead to different build IDs, too.) Above quote was just a little piece of the documentation I'm currently preparing 😉 So In above text, I've just added before the "Build IDs" header:
And this is why both are mentioned: if you want to confirm an APK from a project where the maintainer(s) left, there is nobody to fix the "upstream APK". That leaves only things you can do locally on your builder then. Our builders are intended "for general use", not specific to our repo or yours, so we need both options there 😉 PS: My question here was mostly to confirm that this adjustment was "the complete one" – or what other "learnings" I might have missed. Thanks for enlighting me as well, linsui 🙇♂ |
Nice to know :) I'll publish a patch release soon after fixing some minor issues. |
Just wondering: you've created a Github action to build the release APK, but you're obviously not using it for release builds (at least your latest APK was built on a Windows machine). Which unfortunately makes Reproducible Builds impossible, as the build paths are embedded into the libraries – and on Linux, we cannot match Windows paths:
If you'd use your Github action instead, it would be possible to establish reproducible builds – at least at IzzyOnDroid (see e.g. Reproducible Builds, special client support and more at IzzyOnDroid for some background on this).
So no pressure, but just asking: would that be something you'd consider? One big win of having your app confirmed as RB is that this clearly shows your APKs have been built from exactly the source code they claim to, with nothing added or taken away, and thus pushes up the trust level a level or two. No guarantee we succeed there – but given an example APK built with your Github action, we could take a look and see.
Thanks in advance for considering!
The text was updated successfully, but these errors were encountered: