niess / python-appimage

AppImage distributions of Python
https://python-appimage.readthedocs.io/en/latest/
GNU General Public License v3.0
170 stars 24 forks source link

[Question] Adding wxPython #58

Closed mantielero closed 4 months ago

mantielero commented 1 year ago

I am trying to pack a piece of software using python2.7. I am struggling to get the dependencies properly.

I download python2.7:

wget https://github.com/niess/python-appimage/releases/download/python2.7/python2.7.18-cp27-cp27m-manylinux1_x86_64.AppImage
chmod +x python2.7.18-cp27-cp27m-manylinux1_x86_64.AppImage
./python2.7.18-cp27-cp27m-manylinux1_x86_64.AppImage  --appimage-extract

Then I install the dependencies:

usr/bin/pip2.7 install future zeroconf==0.19.1 numpy==1.16.5 matplotlib==2.0.2 lxml==4.6.2 pyro sslpsk pyserial

But I struggle to get wxPython given than only v4.x is available, while I need v3.0. I found it in Ubuntu. So I downloaded:

apt-get download python-wxgtk3.0
dpkg-deb -xv python-wxgtk3.0_3.0.2.0+dfsg-8build1_amd64.deb ./

Is there a way to get the extracted data from the .deb package integrated with the extracted data from python-appimage?

niess commented 1 year ago

Hello @mantielero,

sorry, I missed this post.

I understand that you need a wxPython version that is not available as a binary wheel on PyPI. But you found the corresponding binary in a .deb file. Is this correct?

If so, you could try to simply copy the wxPython package from the deb file to the AppImage site-packages directory, hoping that the two builds are binary compatible (?) You would also need to package any external libraries that are used by wxPython (you can check this e.g. with ldd or objdump -p).

Note, that the previous attempt is likely not to work straight out of the box :( Thus, it might actually be easier to rebuild wxPython from source and to bundle it in the AppImage.

jeanslack commented 1 year ago

Hello @niess

Thank you for developing this very useful project! I saw this issue a few days.

I pip installed an ubuntu 18.04 specific wxPython wheel into python-appimage, which works in some Linux distributions but in others needs other libraries. I'm wondering how to include the following missing libraries required by wxPython inside a python-appimage:

strings squashfs-root/opt/python3.9/lib/python3.9/site-packages/wx/libwx_gtk3u_core-3.1.so.5 | grep "\.so."
libgtk-3.so.0
libgdk-3.so.0
libpangocairo-1.0.so.0
libpango-1.0.so.0
libcairo.so.2
libgdk_pixbuf-2.0.so.0
libgio-2.0.so.0
libgobject-2.0.so.0
libglib-2.0.so.0
libX11.so.6
libXxf86vm.so.1
libSM.so.6
libnotify.so.4
libXtst.so.6
libpangoft2-1.0.so.0
libfontconfig.so.1
libSDL2-2.0.so.0
libpng16.so.16
libjpeg.so.8
libtiff.so.5
libwx_baseu-3.1.so.5
libm.so.6
libstdc++.so.6
libgcc_s.so.1
libpthread.so.0
libc.so.6
libwx_gtk3u_core-3.1.so.5

Although not all of these libraries should be included inside appimage assuming that all target systems (Linux distributions) ship them by default.

I am also aware that getting a wxPython wheel compiled to run on only a few compatible Linux systems is a tough task, since there is no official wxPython manylinux wheel yet.

niess commented 1 year ago

Hello @jeanslack ,

in principle, extra system like libraries would be bundled under AppDir/usr/lib, where AppDir is the (extracted) AppImage root directory. Now, it actually depends on the pip installed binaries. I am assuming that your wxPython package ships with shared libraries (A.so), properly loaded by Python, but depending on (missing) system like libraries (B.so). Then, A.so would not be aware that B.so would be under AppDir/usr/lib.

A quick and dirty solution would be to modify the LD_LIBRARY_PATH at runtime by editing the AppImage entry point (AppDir/AppRun). For example you could add $APPDIR/usr/lib to it (assuming that B.so goes there), as

export LD_LIBRARY_PATH=$APPDIR/usr/lib:$LD_LIBRARY_PATH

(in AppDir/AppRun, right before calling Python.)

You could try this first as a quick hack. The inconvenience with this solution is that you are spamming the LD_LIBRARY_PATH env variable, which could have side effects. But, if your AppImage is not intended to be further re-used, then this could be very OK for your use case.

As for which B.so should be bundled or not, your link looks good to me. Clearly libc.so should not. It would not work actually. I would assume that libstdc++.so.6 should be excluded as well.

Concerning the first issue, i.e. locating B.so, I am discussing a more sophisticated solution below, which is used by python-appimage. First, you need to check the RPATH of A.so. For example, using objdump as

objdump -p A.so

(Look for the RUNPATH entry, in the output of objdump. It might be absent, which means that RPATH is empty)

The RPATH tells where to look for dependencies, i.e. B.so (like PATH for executable, etc.). There is a special keyword $ORIGIN which refers to the parent directory of A.so (see e.g. objdump -p AppDir/usr/lib/libcrypt.so.2). If the RPATH is empty (or not consistent with the AppImage layout), then you would need to edit it. This can be done with patchelf. Note that if you installed python-appimage, then you already have patchelf as well (see e.g. python-appimage which patchelf, or python-appimage install patchelf).

The RPATH can be edited as

patchelf --set-rpath '$ORIGIN/relative/path/to/where/B/is/located' A.so

(Note that you need to use relative paths in order that the application is relocatable. Otherwise, the re-built AppImage would not work.)

It might be that simply copying B.so aside of A.so works. You could try this first. I actually do not remember if $ORIGIN is by default in the search path for dependencies.

As a final word, indeed, making this work will likely be a tough task in this particular case :( Even if you properly set all RPATHs (a mandatory requirement, somehow), you might be stuck with conflictual dependencies issues at some point. But, if you are interested in these technicalities, this could be an instructive exercise :)

jeanslack commented 1 year ago

Your explanation was very helpful and instructive. I'm already trying to do some testing using your directions and will see what's more convenient at this point.

Thank you very much!