Skip to content

p4a rebase, use ndk28 and qt6.10#10485

Open
accumulator wants to merge 24 commits intospesmilo:masterfrom
accumulator:ndk28_qt610_rebase_p4a
Open

p4a rebase, use ndk28 and qt6.10#10485
accumulator wants to merge 24 commits intospesmilo:masterfrom
accumulator:ndk28_qt610_rebase_p4a

Conversation

@accumulator
Copy link
Copy Markdown
Member

@accumulator accumulator commented Feb 19, 2026

This updates P4A to a much more recent branch point (~2025-10), right before upstream moves to python3.14.

  • NDK upgraded to 28c. This is more recent than the Qt6.10 supported NDK27c, but this seems to work without issues, and allows us to drop the 16kb alignment patches.
  • Qt upgraded to 6.10.1
  • p4a minapi increased to 26 (Android 8.0)
  • pyqt6sip upgraded to 13.10.3
  • pyqt_builder upgraded to 1.19.1
  • pyqt6 upgraded to 6.10.1
  • sip upgraded to 6.15.1
  • openssl (implicitly) upgraded to 3.3.1

patches dropped:

  • 16 kb alignment patches for qt6, cffi, sqlite, pyqt6, qt6-bootstrap
  • recipes: bump openssl to 3.0.x (e91310fbf88857b2fbd9f9a5f591300ae5da90b5)
  • python: update to 3.11.5 (a01269f7799587ad74ee40e0b642d917b8db7d4e)
  • patches for reproducibility (8e3bad863d52ae537066d222d9cfe177b868ec9d, e04b87585714114a626a34b558066144a6c91217, 39cc65c1812a9937b0b0e4afda18fb40ab0fa1b0)
  • Update cffi recipe for Python 3.10 (41fee3e938d13b6701b205da8c17d0d444188e63)
  • recipes: add patches for python3 recipes, for reproducible .pyc generation (0ab0d872e6c6b88ddc05b9c4ba6fcd3aa7921242)

patches added:

  • compat-windowinsets.patch to avoid crashing on requesting window insets on Android 8 (375a05de21b538d704174b1efeb3fc85d151f94e)

other changes:

  • squashed all of Qt5 history to a single commit
  • squashed all of Qt6.4 history to a single commit
  • qt6 compile option -no-feature-getentropy, this feature requires API28 and has a fallback reading /dev/urandom. (Note: we don't use any cryptographic primitives from Qt, so this should not be potentially problematic)

changes in QML GUI:

  • changed all pyqtProperty accessors that also have a setter to pass QVariant instead of the actual type, to work around this PyQt issue.
  • changed QML typed properties declarations that use custom types as var instead.
  • to restore Android8 compatibility, direct imports of QtMultimedia are removed. (QtMultimedia is currently not needed on android, but is used for camera/scanning on desktop)
  • styling updates due to new Material 3 theme

@accumulator
Copy link
Copy Markdown
Member Author

accumulator commented Feb 19, 2026

Note: we need to check if the build is still reproducible!
Note2: styling is probably inconsistent in many places
Note3: this should only be merged after the next release, as currently android 7 and 8 are not working due to biometric java classes crash, and this branch will NOT work anymore on android 7. The next release therefore should indicate current minapi (23) to get electrum working on current android7 devices before moving to a new minapi (26), otherwise android7 will get stuck with a non-working version without the option to downgrade.

@accumulator accumulator force-pushed the ndk28_qt610_rebase_p4a branch 7 times, most recently from bb0914b to 3ed4382 Compare February 23, 2026 22:35
@accumulator accumulator added this to the 4.8.0 milestone Feb 25, 2026
@SomberNight
Copy link
Copy Markdown
Member

hey, sorry for lack of feedback. It is most certainly not due to lack of interest! :)

Did you close this just to make it clear we should not include it in 4.7.1 (which I agree with - and now 4.7.x is branched off, and a huge change like this I would not want to cherry-pick to 4.7.x), or is it for some other reason?
Is it ready for testing/review?

@accumulator accumulator reopened this Mar 3, 2026
@accumulator
Copy link
Copy Markdown
Member Author

oops, I don't recall closing this.. reopening

@accumulator
Copy link
Copy Markdown
Member Author

Is it ready for testing/review?

Yes

@f321x
Copy link
Copy Markdown
Member

f321x commented Mar 4, 2026

When running this as a debug apk on my Pixel 9 (Android 16) i noticed two issues:

This Unexpected nullptr parameter warning shows up when stopping the app:

03-04 10:08:04.941 19730 19764 I python  :  11.68 | I | plugin.Plugins | jnius detach
03-04 10:08:04.942 19730 19764 I python  :  11.69 | I | plugin.Plugins | stopped
03-04 10:08:04.945 19730 19763 I python  :  11.69 | I | daemon.Daemon | removing lockfile
03-04 10:08:04.946 19730 19763 I python  :  11.69 | I | daemon.Daemon | stopped
03-04 10:08:05.022 19730 19753 I python  :  11.77 | W | gui.qml.qeapp | QObject::disconnect: Unexpected nullptr parameter

The app crashes most of the time when starting it (like 4 out of 5 times), when cancelling the following Biometric authentication it crashes almost certainly. However when i manage to open it it runs reliably and doesn't crash anymore. Seems to be some kind of race during startup? I noticed the following log lines during these crashes:

03-04 10:08:46.762 19813 19846 I python  :   2.92 | D | gui.qml.qenetwork | fee histogram updated
03-04 10:08:47.238 19813 19813 I python  :   3.40 | D | gui.qml.qebiometrics | biometric auth cancelled by user
03-04 10:08:47.238 19813 19835 I python  :   3.40 | W | gui.qml.qeapp | Biometric auth failed: CANCELLED
03-04 10:08:47.287 19813 19867 I python  :   3.45 | W | gui.qml.qeapp | Failed to acquire deadlock protector for 'QAndroidPlatformOpenGLWindow::eglSurface()' while already locked by 'QtAndroidAccessibility::runInObjectContext()'.
03-04 10:08:47.289 19813 19867 I python  :   3.45 | W | gui.qml.qeapp | Failed to acquire deadlock protector for QAndroidPlatformOpenGLWindow::eglSurface().
03-04 10:09:09.983 19895 19917 I python  :   1.08 | I | gui.qml.ElectrumGui | Entering main loop
03-04 10:09:09.997 19895 19917 I python  :   1.09 | W | gui.qml.qeapp | wallet requires password
03-04 10:09:10.001 19895 19917 I python  :   1.10 | D | gui.qml.qebiometrics | _start_activity: DECRYPT, len(data)=133
03-04 10:09:10.015 19895 19917 I python  :   1.11 | W | gui.qml.qeapp | daemon loading false
03-04 10:09:10.070 19895 19942 I python  :   1.17 | W | gui.qml.qeapp | Failed to acquire deadlock protector for 'QAndroidPlatformOpenGLWindow::eglSurface()' while already locked by 'QtAndroidAccessibility::runInObjectContext()'.
03-04 10:09:10.077 19895 19942 I python  :   1.17 | W | gui.qml.qeapp | Failed to acquire deadlock protector for QAndroidPlatformOpenGLWindow::eglSurface().
03-04 10:09:10.086 19895 19928 I python  :   1.18 | I | lnworker.LNGossip | starting taskgroup.
03-04 10:09:10.087 19895 19928 I python  :   1.18 | I | lnworker.LNPeerManager.[LNGossip] | starting taskgroup.
03-04 10:09:10.470 19895 19928 I python  :   1.56 | I | interface.[5.9.83.108:50002] | connection established. version: ['ElectrumX 1.18.0', '1.6'], handshake duration: 138.00 ms

This is the Android crash report:

type: crash
osVersion: google/tokay/tokay:16/BP4A.260205.002/2026021201:user/release-keys
flags: dev options enabled
package: org.electrum.electrum:45407013, targetSdk 35
process: org.electrum.electrum
installer: com.android.packageinstaller

signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------

backtrace:
      #00 pc 000000000007d9c0  /apex/com.android.runtime/lib64/bionic/libc.so (abort+160) (BuildId: b2e2593ea9af5cb426017f2c32a8fcf5)
      #01 pc 0000000000304aa0  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libQt6Core_arm64-v8a.so (BuildId: 8931ee3d5926136691ad4138d5a045c25d029803)
      #02 pc 000000000031acb4  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libQt6Core_arm64-v8a.so (BuildId: 8931ee3d5926136691ad4138d5a045c25d029803)
      #03 pc 000000000031b550  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libQt6Core_arm64-v8a.so (QMessageLogger::fatal(char const*, ...) const+152) (BuildId: 8931ee3d5926136691ad4138d5a045c25d029803)
      #04 pc 000000000009a848  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libplugins_platforms_qtforandroid_arm64-v8a.so (BuildId: 273879cc841d14aae157ecda0dfc0530629054c7)
      #05 pc 000000000009a318  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libplugins_platforms_qtforandroid_arm64-v8a.so (BuildId: 273879cc841d14aae157ecda0dfc0530629054c7)
      #06 pc 0000000000581788  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libQt6Gui_arm64-v8a.so (QOpenGLContext::makeCurrent(QSurface*)+144) (BuildId: a56b29ee58a4afe709da073c19350f00467b1f4f)
      #07 pc 000000000058dfd8  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libQt6Gui_arm64-v8a.so (BuildId: a56b29ee58a4afe709da073c19350f00467b1f4f)
      #08 pc 000000000058e264  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libQt6Gui_arm64-v8a.so (BuildId: a56b29ee58a4afe709da073c19350f00467b1f4f)
      #09 pc 000000000049fdb8  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libQt6Gui_arm64-v8a.so (QRhi::create(QRhi::Implementation, QRhiInitParams*, QFlags<QRhi::Flag>, QRhiNativeHandles*, QRhiAdapter*)+152) (BuildId: a56b29ee58a4afe709da073c19350f00467b1f4f)
      #10 pc 00000000004f1014  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libQt6Quick_arm64-v8a.so (QSGRhiSupport::createRhi(QQuickWindow*, QSurface*, bool)+1036) (BuildId: 06be7c46a481e005d36bba0d2ee08484b99c24d7)
      #11 pc 00000000005f2238  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libQt6Quick_arm64-v8a.so (BuildId: 06be7c46a481e005d36bba0d2ee08484b99c24d7)
      #12 pc 00000000005f2448  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libQt6Quick_arm64-v8a.so (BuildId: 06be7c46a481e005d36bba0d2ee08484b99c24d7)
      #13 pc 000000000048ce24  /data/app/~~Ugakqqk7pSuNKMd_DGYNLA==/org.electrum.electrum-xUuIdVbQ5QFI0x95-tbQig==/lib/arm64/libQt6Core_arm64-v8a.so (BuildId: 8931ee3d5926136691ad4138d5a045c25d029803)
      #14 pc 0000000000091584  /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*) (.__uniq.67847048707805468364044055584648682506)+180) (BuildId: b2e2593ea9af5cb426017f2c32a8fcf5)
      #15 pc 00000000000813d4  /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+68) (BuildId: b2e2593ea9af5cb426017f2c32a8fcf5)

@accumulator
Copy link
Copy Markdown
Member Author

accumulator commented Mar 4, 2026

When running this as a debug apk on my Pixel 9 (Android 16) i noticed two issues:

This Unexpected nullptr parameter warning shows up when stopping the app:

03-04 10:08:04.941 19730 19764 I python  :  11.68 | I | plugin.Plugins | jnius detach
03-04 10:08:04.942 19730 19764 I python  :  11.69 | I | plugin.Plugins | stopped
03-04 10:08:04.945 19730 19763 I python  :  11.69 | I | daemon.Daemon | removing lockfile
03-04 10:08:04.946 19730 19763 I python  :  11.69 | I | daemon.Daemon | stopped
03-04 10:08:05.022 19730 19753 I python  :  11.77 | W | gui.qml.qeapp | QObject::disconnect: Unexpected nullptr parameter

Yes I see the same.

The app crashes most of the time when starting it (like 4 out of 5 times), when cancelling the following Biometric authentication it crashes almost certainly. However when i manage to open it it runs reliably and doesn't crash anymore. Seems to be some kind of race during startup?

I haven't seen this at all. I'm also using debug apk on Pixel 9. I assume you fully cleaned the buildozer build tree first?

I noticed the following log lines during these crashes:

03-04 10:08:46.762 19813 19846 I python  :   2.92 | D | gui.qml.qenetwork | fee histogram updated
03-04 10:08:47.238 19813 19813 I python  :   3.40 | D | gui.qml.qebiometrics | biometric auth cancelled by user
03-04 10:08:47.238 19813 19835 I python  :   3.40 | W | gui.qml.qeapp | Biometric auth failed: CANCELLED
03-04 10:08:47.287 19813 19867 I python  :   3.45 | W | gui.qml.qeapp | Failed to acquire deadlock protector for 'QAndroidPlatformOpenGLWindow::eglSurface()' while already locked by 'QtAndroidAccessibility::runInObjectContext()'.
03-04 10:08:47.289 19813 19867 I python  :   3.45 | W | gui.qml.qeapp | Failed to acquire deadlock protector for QAndroidPlatformOpenGLWindow::eglSurface().
03-04 10:09:09.983 19895 19917 I python  :   1.08 | I | gui.qml.ElectrumGui | Entering main loop
03-04 10:09:09.997 19895 19917 I python  :   1.09 | W | gui.qml.qeapp | wallet requires password
03-04 10:09:10.001 19895 19917 I python  :   1.10 | D | gui.qml.qebiometrics | _start_activity: DECRYPT, len(data)=133
03-04 10:09:10.015 19895 19917 I python  :   1.11 | W | gui.qml.qeapp | daemon loading false
03-04 10:09:10.070 19895 19942 I python  :   1.17 | W | gui.qml.qeapp | Failed to acquire deadlock protector for 'QAndroidPlatformOpenGLWindow::eglSurface()' while already locked by 'QtAndroidAccessibility::runInObjectContext()'.
03-04 10:09:10.077 19895 19942 I python  :   1.17 | W | gui.qml.qeapp | Failed to acquire deadlock protector for QAndroidPlatformOpenGLWindow::eglSurface().
03-04 10:09:10.086 19895 19928 I python  :   1.18 | I | lnworker.LNGossip | starting taskgroup.
03-04 10:09:10.087 19895 19928 I python  :   1.18 | I | lnworker.LNPeerManager.[LNGossip] | starting taskgroup.
03-04 10:09:10.470 19895 19928 I python  :   1.56 | I | interface.[5.9.83.108:50002] | connection established. version: ['ElectrumX 1.18.0', '1.6'], handshake duration: 138.00 ms

This is my log. It has some warnings and errors, but never crashes and seems to run fine:

03-04 12:00:11.388 20865 20887 I python  :   1.09 | I | gui.qml.ElectrumGui | Entering main loop
03-04 12:00:11.399 20865 20887 I python  :   1.10 | W | gui.qml.qeapp | wallet requires password
03-04 12:00:11.403 20865 20887 I python  :   1.11 | D | gui.qml.qebiometrics | _start_activity: DECRYPT, len(data)=133
03-04 12:00:11.416 20865 20887 I python  :   1.12 | W | gui.qml.qeapp | daemon loading false
03-04 12:00:11.974 20865 20909 I python  :   1.68 | W | gui.qml.qeapp | makeCurrent(): no EGLSurface, likely Surface destroyed by Android.
03-04 12:00:11.974 20865 20909 I python  :   1.68 | W | gui.qml.qeapp | QRhiGles2: Failed to make context current. Expect bad things to happen.
03-04 12:00:11.974 20865 20909 I python  :   1.68 | W | gui.qml.qeapp | Failed to start frame
03-04 12:00:12.713 20865 20897 I python  :   2.42 | D | exchange_rate.CoinGecko | received fx quotes
03-04 12:00:12.714 20865 20897 I python  :   2.42 | D | gui.qml.qefx | new quotes
03-04 12:00:12.807 20865 20897 I python  :   2.51 | I | interface.[skbxmit.coinjoined.com:50002] | connection established. version: ['ElectrumX 1.19.0', '1.6'], handshake duration: 192.64 ms
03-04 12:00:12.877 20865 20897 I python  :   2.58 | I | interface.[skbxmit.coinjoined.com:50002] | set blockchain with height 939251
03-04 12:00:12.881 20865 20897 I python  :   2.59 | I | interface.[skbxmit.coinjoined.com:50002] | new chain tip. height=939252
03-04 12:00:12.881 20865 20897 I python  :   2.59 | D | gui.qml.qenetwork | new height: 939252
03-04 12:00:12.884 20865 20897 I python  :   2.59 | D | gui.qml.qenetwork | network_status updated: Connected to 1 node.
03-04 12:00:12.885 20865 20897 I python  :   2.59 | D | gui.qml.qenetwork | chain tips # changed: 1
03-04 12:00:12.927 20865 20897 I python  :   2.63 | I | network | fee_estimates {}
03-04 12:00:14.341 20865 20865 I python  :   4.05 | D | gui.qml.qebiometrics | biometric auth cancelled by user
03-04 12:00:14.344 20865 20887 I python  :   4.05 | W | gui.qml.qeapp | Biometric auth failed: CANCELLED
03-04 12:00:14.430 20865 20909 I python  :   4.14 | W | gui.qml.qeapp | QEGLPlatformContext: eglSwapBuffers failed: 300d
03-04 12:00:14.460 20865 20909 E Surface : [733f4e6 SurfaceView[org.electrum.electrum/org.kivy.android.PythonActivity]#4(BLAST Consumer)4](id:518100000004) clearBuffersForDisconnectLocked: 1 buffers were freed while being dequeued!
03-04 12:00:14.592  1391  6537 D CoreBackPreview: Window{eae2219 u0 org.electrum.electrum/org.kivy.android.PythonActivity}: Setting back callback OnBackInvokedCallbackInfo{mCallback=android.window.IOnBackInvokedCallback$Stub$Proxy@27d23d6, mPriority=0, mIsAnimationCallback=true, mOverrideBehavior=0}
03-04 12:00:14.640 20865 20865 D VRI[PythonActivity]: WindowInsets changed: ime:[0,0,0,796] 

@f321x
Copy link
Copy Markdown
Member

f321x commented Mar 6, 2026

weird.

I assume you fully cleaned the buildozer build tree first?

yes, i started in a clean repo with fresh container.

Also i am using GrapheneOS, but had all optional exploit protections disabled, so this shouldn't be the reason.

@accumulator accumulator force-pushed the ndk28_qt610_rebase_p4a branch 4 times, most recently from 7c24c22 to 3ebe8e5 Compare March 9, 2026 12:17
@f321x
Copy link
Copy Markdown
Member

f321x commented Mar 9, 2026

The recent changes fixed the crash for me, 3ebe8e5 now works fine.

p4a rebased on spesmilo/electrum_202602, 375a05de21b538d704174b1efeb3fc85d151f94e
…erties

- on the python side, for pyqtProperty's with a setter, the pyqtProperty should be declared as QVariant type
- on the qml side, properties should be declared 'var', not the custom type.
@accumulator accumulator force-pushed the ndk28_qt610_rebase_p4a branch from 3ebe8e5 to 660f2ea Compare March 9, 2026 16:11
Copy link
Copy Markdown
Member

@SomberNight SomberNight left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of my other comments are too important, but this one is a blocker.
We must hash pin everything we pull in.

( self-note: reviewed 660f2ea )

Comment on lines +9 to +10
assert PyjniusRecipe._version == "1.7.0"
assert PyjniusRecipe.depends == [('genericndkbuild', 'sdl2', 'sdl3', 'qt6'), 'six', 'python3'], PyjniusRecipe.depends
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something fishy is going on.

New pyjnius requires Cython 3.1.x [ref], but ISTM we only install Cython 0.29 [ref].


Ok, so I believe it is due to the recipe.hostpython_prerequisites introduced in kivy/python-for-android@8110faf.

Uhum... so this is due to this hostpython_prerequisites, installing

https://github.com/spesmilo/python-for-android/blob/ee6886ec3048670b182afb18237e0ae69fde1254/pythonforandroid/recipes/pyjnius/__init__.py#L14
https://github.com/spesmilo/python-for-android/blob/ee6886ec3048670b182afb18237e0ae69fde1254/pythonforandroid/recipes/android/__init__.py#L16
https://github.com/spesmilo/python-for-android/blob/ee6886ec3048670b182afb18237e0ae69fde1254/pythonforandroid/recipes/pyqt6/__init__.py#L18
Looks like all kinds of unpinned packages are getting installed at build-time willy-nilly.

Uhh this install_hostpython_prerequisites is a real can of worms. (esp with force_upgrade=True!)
So it is calling pip with internet and downloading packages without hash-pins from PyPI. Often without even version-pins. We can't have this... everything must be pinned.

Perhaps we should make sure that install_hostpython_prerequisites always gets called with a packages arg that contains hashes. We could patch the pip_options internal var to add --require-hashes, as a final sanity check.

Also, this recipe.hostpython_prerequisites should probably be something we assert/check in our contrib/android/p4a_recipes, similar to depends and python_depends. We really don't want any of these silently changing.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, hostpython package handling considerably changed in p4a upstream. Pinning will take some work.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added support for hash pinning the hostpython_prerequisites.

Nice. Thanks a lot!

The hostpython_prerequisites are not compiled but pulled binary from pypi. packaging is now not compiled but pulled in as binary instead. If we want to compile it instead this could take some work to accomplish

Ok, I think it's acceptable to pull in some pure-python .wheels from PyPI for a small number of popular packages. As long as everything is hash-pinned.

In general we should make sure everything is hash-pinned and instead of logging warnings or silently ignoring issues, we should add belt-and-suspender sanity-check hard-fails, make sure we don't just accidentally pull in the unpinned current latest of version of something.

@accumulator
Copy link
Copy Markdown
Member Author

accumulator commented Mar 18, 2026

I've added support for hash pinning the hostpython_prerequisites. The hostpython_prerequisites are not compiled but pulled binary from pypi. I've changed sip and pyqt_builder from prereq to dep, so that we compile it ourselves. packaging is now not compiled but pulled in as binary instead. If we want to compile it instead this could take some work to accomplish (It is now pulled in as transitive dependency for the build[virtualenv] prerequisite for PyProjectRecipe recipies). The entire dependency tree for PyProjectRecipe prereqs is hash pinned in the hostpython3 recipe.

Yes, hostpython package handling considerably changed in p4a upstream.

.. and it still sucks

Comment on lines +10 to +14
class SetuptoolsRecipePinned(SetuptoolsRecipe):
sha512sum = "5a3572466a68c6f650111448ce3343f64c62044650bb8635edbff97e2bc7b216b8bbe3b4e3bccf34e6887f3bedc911b27ca5f9a515201cae49cf44fbacf03345"
hostpython_prerequisites = [
HashPinnedDependency(package='setuptools==80.9.0',
hashes=[]),
]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is the hash of the host setuptools not pinned?

also, shouldn't PythonRecipe.install_hostpython_prerequisites raise an exception in this case?
I would have expected pip install --require-hashes to error out (?)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not trigger because apparently it isn't used as a compiled dependency..

Comment on lines +27 to +42
# pin deptree build[virtualenv]==1.4.0
HashPinnedDependency(package="packaging==26.0",
hashes=['sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529']),
HashPinnedDependency(package="pyproject_hooks==1.2.0",
hashes=['sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913']),
HashPinnedDependency(package="virtualenv==21.2.0",
hashes=['sha256:1bd755b504931164a5a496d217c014d098426cddc79363ad66ac78125f9d908f']),
HashPinnedDependency(package="distlib==0.4.0",
hashes=['sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16']),
HashPinnedDependency(package="filelock==3.25.2",
hashes=['sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70']),
HashPinnedDependency(package="platformdirs==4.9.4",
hashes=['sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868']),
HashPinnedDependency(package="python_discovery==1.1.3",
hashes=['sha256:90e795f0121bc84572e737c9aa9966311b9fde44ffb88a5953b3ec9b31c6945e']),
]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packaging [...] is now pulled in as transitive dependency for the build[virtualenv] prerequisite for PyProjectRecipe recipies. The entire dependency tree for PyProjectRecipe prereqs is hash pinned in the hostpython3 recipe.

is virtualenv actually needed? can't we just use stdlib venv?
I see that upstream declared it there but what specifically is needed that venv is missing?
that would rid us of all these transitive deps

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have a look

Comment on lines +9 to +10
assert PyjniusRecipe._version == "1.7.0"
assert PyjniusRecipe.depends == [('genericndkbuild', 'sdl2', 'sdl3', 'qt6'), 'six', 'python3'], PyjniusRecipe.depends
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added support for hash pinning the hostpython_prerequisites.

Nice. Thanks a lot!

The hostpython_prerequisites are not compiled but pulled binary from pypi. packaging is now not compiled but pulled in as binary instead. If we want to compile it instead this could take some work to accomplish

Ok, I think it's acceptable to pull in some pure-python .wheels from PyPI for a small number of popular packages. As long as everything is hash-pinned.

In general we should make sure everything is hash-pinned and instead of logging warnings or silently ignoring issues, we should add belt-and-suspender sanity-check hard-fails, make sure we don't just accidentally pull in the unpinned current latest of version of something.

…d[virtualenv]',

remove setuptools as its use is now pinned via hostpython_prerequisites where applicable,
update depends asserts in pyqt6sip, sip, pyqt_builder
@accumulator accumulator force-pushed the ndk28_qt610_rebase_p4a branch from 5a952dd to ca5e374 Compare March 23, 2026 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants