3

I am writing a Python app that works with graphics and depends on PySDL2 library. PySDL2 depends on compiled SDL2 binary library that can be downloaded from SDL site. I wrote a bootstrap script to automate the process, but it works only for Windows, because there is no binary download for Linux.

The question is how to make that binary SDL2 download for Linux?

It is not clear if it is possible to create .so file that will work on every Linux at all, if it is because it is impossible to create .so file that will work on every CPU, and that's mostly because it is not clear if any work was already done in this direction (I am sure people tried to research this problem) and if it is, then why the format of portable .so file (cross-platform against different distributions and CPUs) was not adopted.

UPDATE: I don't mind installing dependencies (packages) with updates and security fixes provided by Linux community, but this should be done in user space, and I need the ability to automate it with portable scripts.

anatoly techtonik
  • 17,421
  • 8
  • 111
  • 131

2 Answers2

4

Don't do this.

The most reliable way would be to make a complete static built library stack.

But this will totally bloat your application and if there ever is any security issue in these libraries, you will need to update this yourself and all your users will need to re-download.

By using the distribution provided SDL libraries, your application will benefit from SDL bugfixes and updates done by the Linux community.

Consider providing packages for the most common distributions (i.e. Debian, Ubuntu, Redhat, Fedora) that then have proper dependencies on the distribution-provided SDL library.

When you look at how Skype, Google etc. distribute their binaries, it's always in a distribution-specific package, that can then work with the system libraries. For example Skype:

Depends: libasound2 (>= 1.0.16), libc6 (>= 2.3.6-6~), libc6 (>= 2.7),
  libgcc1 (>= 1:4.1.1), libqt4-dbus (>= 4:4.5.3), libqt4-network (>= 4:4.8.0),
  libqt4-xml (>= 4:4.5.3), libqtcore4 (>= 4:4.7.0~beta1), libqtgui4 (>= 4:4.8.0),
  libqtwebkit4 (>= 2.1.0~2011week13), libstdc++6 (>= 4.6), libx11-6, libxext6,
  libxss1, libxv1, libssl1.0.0

As you can see, skype does not bring all its libraries included. When installing Skype, the user may have to rely on his package manager to resolve these dependencies.

Furthermore, Linux users are very reluctant to download or install binaries at all. If you really want people to use your "app", you better make it open source and have someone include it with the major Linux distributions. Linux isn't Windows. One of the reasons there are few viruses on Linux is because most people don't download untrusted software.

Has QUIT--Anony-Mousse
  • 70,714
  • 12
  • 123
  • 184
  • Alright. How can I do this in user space? When I download .dll, I don't need root rights to run the binary and with packages that Linux community builds the user needs to be root to run it. I also don't know how to tell user command that it needs to be run for his platform, which kills all the fun and ruins experience. In the end user should download and run my program - not spend 10 minutes trying to fetch all dependencies.. so I'd like to automate this step. – anatoly techtonik Jan 13 '14 at 20:39
  • And yes - my app is open source - it is here - https://bitbucket.org/techtonik/discovery/src/tip/graphics/pysdl2/?at=default =) – anatoly techtonik Jan 13 '14 at 20:41
  • To sum up, the solution **is not portable**. Is there a way to make good? – anatoly techtonik Jan 13 '14 at 20:48
  • And I really doubt that my app will be included in Linux distribution, because it is [way too complicated](http://askubuntu.com/questions/395584/how-to-build-a-newer-version-of-a-package-than-is-available-for-my-stable-releas) even to install a newer version of existing package. – anatoly techtonik Jan 13 '14 at 21:04
  • I frequently build new packages myself. Most are trivial to build, and your question indicates that you are trying a way too complicated approach. Lots of packages can automatically be packaged by debhelper, then the `debian/rules` file consists of a single rule, `%: dh $@`, aka: "let debhelper handle everything". – Has QUIT--Anony-Mousse Jan 14 '14 at 08:50
  • my development station is not Debian/Ubuntu, and users of my silly Python app are also not a hardcore Linux users, so I'd like to make their experience as easy as possible to help them see that Linux platform can also be user friendly, that why I need **portable** .so. I understand your security concerns, that's why my bootstrap script includes protection from MITM and remote site compromises. – anatoly techtonik Jan 14 '14 at 10:04
  • Well, the notion of "user friendly" for Linux users means: "already comes with my distribution, and doesn't require me to run untrusted `.exe` files from some obscure place on the net"... you may need to wait until pySDL2 is available, then uses will likely not need to trust any `.so` from you anymore. – Has QUIT--Anony-Mousse Jan 14 '14 at 11:16
  • 1. This `.exe` that you are speaking about is actually a `.dll` and it comes from official SDL2 site - this is mentioned in my question. Now that trust is not a question, between "use right now" and "wait until PySDL2 is available" the latter is not "user friendly". Acceptable answer (for me) is "Linux doesn't support this, because...", but not "You should not do this.." – anatoly techtonik Jan 14 '14 at 11:43
  • 2. I still want to mention that your advice and warnings in generic case are useful, and can be applied for my use case too if you could expand on `The most reliable way would be to make a complete static built library stack` and why the stack will be totally bloated. SDL2 is a graphic library and I don't want it to include all graphics drivers as a result. – anatoly techtonik Jan 14 '14 at 11:47
3

Regarding CPU architectures, Linux does not have support for Fat Binaries (more than architecture per binary, something which is available in OS X for example). There was a proposal called Fat ELF by Ryan Gordon which sadly didn't go anywhere.

In the particular case of SDL2, the library links by default to very few libraries:

ldd /usr/local/lib/libSDL2.so

    linux-vdso.so.1 =>  (0x00007fffd1f0b000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f414c44e000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f414c24a000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f414c02c000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f414be24000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f414ba5c000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f414cac4000)

The rest of the binaries SDL depends on are loaded dynamically (using dlopen), and SDL is quite adaptable to different versions of certain binaries. So, in short, if you compile in a system with certain versions of libc, libpthread, etc and manage to find a different system with compatible binaries, you have a good chance that the SDL binary will at least run. In practice, you are better off depending on the system provided binary, or accept that you'll be supporting a limited set of distros with your custom made SDL2.

Note that this limitation also applies if you link SDL statically! And if you think you can keep on adding statically linked binaries until you've made a static ball of several hundred megs that runs anywhere (like I did!), there's other limitations that prevent you from doing that, ranging from licensing issues to segfaults due to linking libpthread statically.

Community
  • 1
  • 1
gabomdq
  • 1,660
  • 13
  • 9
  • That's sad, but I guess no worse than in .dll case on Windows. I think system libraries on that OS are backward compatible, and this should be the case for Linux too, no? At least I can try to build this .so file and if it fails to start, say - "sorry dude, try to find out how to compile SDL2 + PySDL for ur sys". Are there any additional hints how to increase portability percentage? Does static linking help? – anatoly techtonik Jan 13 '14 at 20:58
  • I think the two main alternatives you have are either creating a package (a .deb package for Debian/Ubuntu, RPM for Fedora, etc), and listing SDL2 as a dependency (along with Python 2 or 3, and whatever else the end user needs to have installed). Or you could make an install script that downloads, compiles and installs SDL2, even better if you use the standard Pythonic way of doing so (which is what PySDL2 does: https://pypi.python.org/pypi/PySDL2/0.8.0) – gabomdq Jan 13 '14 at 21:30
  • If you do the package way, the OS takes care of root rights for you. If you make a Python distutils script, you can install without root permissions (using a virtualenv for example), but I think in general users know they have to install with sudo. – gabomdq Jan 13 '14 at 23:49