AppImage / AppImageKit

Package desktop applications as AppImages that run on common Linux-based operating systems, such as RHEL, CentOS, openSUSE, SLED, Ubuntu, Fedora, debian and derivatives. Join #AppImage on irc.libera.chat
http://appimage.org
Other
8.72k stars 559 forks source link

Providing a build toolchain through AppImage ? #298

Open jcelerier opened 7 years ago

jcelerier commented 7 years ago

Hi,

I wonder if it would be meaningful to provide a build toolchain / some kind of "Native Linux GUI SDK" through AppImage ?

For instance, it could be something like :

probonopd commented 7 years ago

I have made a Qt Creator AppImage with Qt but not a full toolchain so far.

Personally I would be highly interested in such a SDK, especially if the binaries made with it could run on old target systems like CentOS 6.

fabianloewe commented 7 years ago

IMO, that's a good idea but with a CentOS 6 docker image or a similar thing and some automating scripts for development and testing on this system.

I will research a bit in that direction once I get some free time.

probonopd commented 7 years ago

A SDK was also asked for here.

jcelerier commented 7 years ago

Nice ! I've been thinking a bit more about it, I think that additional interesting things (or at least that should be kept in mind) would be :

Hopefully, it would not be necessary to have a dependency on docker : just shipping CentOS 6, with the "most common" libraries's /usr stuff would be enough ? Or maybe there would be value in having a QtCreator plug-in able to run the compilation process in a docker instance ? But then we have to handle the X forwarding for development of GUI apps (it's doable, just not trivial : http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/). For my software I was even able to forward the X server of an ARM docker instance through qemu to my host, and, while slow as molasses, it still managed to work.

jcelerier commented 7 years ago

I'm also wondering if there could be an input of the OpenFrameworks (http://openframeworks.cc/) guys, they have managed to make a nice integration between their framework and QtCreator.

cesss commented 7 years ago

I guess it shouldn't be difficult to install a sufficiently old distribution in a virtual machine, and copy the headers and libs from it. By installing such distribution in two virtual machines, one for 32bit and another in 64bit, one could get an SDK for 32bit and another for 64bit.

However, one aspect that I still don't master is the libs that compilers tend to bundle with them, and that seem to be necessary for building executables. That's for me a quite obscure topic I've never really understood yet.

Regarding the libs I'd wish to find in an SDK, for me it's just the common C and C++ libs, as well as X11 and GTK. I use wxWidgets for all my apps, but I compile wxWidgets within my source tree, so I don't need it. Regarding the compiler, I prefer clang, but admit that also having gcc is a plus because sometimes it can be handy.

EDIT: Does anybody know of any cross-compiler from some OS to Linux? (where "some OS" means any OS but Linux). If such thing exists, maybe they already have the sort of SDK we're looking for.

probonopd commented 7 years ago

JHBuild was suggested here, as "it requires only very basic system dependencies".

cesss commented 7 years ago

I tried to understand how could JHBuild help, but didn't get to a conclusion. The goal of JHBuild is to build "source modules", which honestly I never heard of (I'm not a GNOME developer). What I need is a package of headers and libs of relatively old versions of C and C++ libraries, that you could use as "/include" and "/lib" paths for your compiler, so that you could build executables for older distributions even from the latest distro versions. I mean, a sort of cross-compiler environment, from a current Linux distribution to older ones.

jcelerier commented 7 years ago

What I need is a package of headers and libs of relatively old versions of C and C++ libraries, that you could use as "/include" and "/lib" paths for your compiler, so that you could build executables for older distributions even from the latest distro versions.

Why old versions ? The whole point (in my eyes) of AppImage is to enable the developers to use the latest version of libraries, and distribute their software in old distributions that don't have them.

Because anyway, if you depend on an old version, it may not work in more recent distros since there are (AFAIK) not that many libraries keeping forward ABI compatibility, except glibc and X11 stuff.

cesss commented 7 years ago

Why old versions ? The whole point (in my eyes) of AppImage is to enable the developers to use the latest version of libraries, and distribute their software in old distributions that don't have them.

Because anyway, if you depend on an old version, it may not work in more recent distros since there are (AFAIK) not that many libraries keeping forward ABI compatibility, except glibc and X11 stuff.

That rationale would imply that an AppImage needs to bundle all the libs used by the app. My way of doing things is to statically link against all libraries that I need and that aren't installed by default in most distros, or when I need some specific version.

If the purpose of AppImage was to bundle everything, then it wouldn't matter what distro nor what distro version you build the app with: by carefully bundling all shared libs you use and/or statically linking with compiler-specific libs, and making sure that your executable doesn't load any library outside the AppImage, it should work everywhere (well, except for kernel protocol changes when they introduce incompatibilities).

My way of looking at this is that my executables should use the shared system libs that are installed by default in all/most distros. Of course, I expect that all such system-wide libraries keep backwards compatibility with binaries built against older versions of them (by either keeping older versions of such DSOs in the system directories, or by actually implementing backwards compatibility). Otherwise, if you cannot expect that some library be backwards compatible with older executables, such library would be broken by design (IMHO), and I'd personally build it and link statically against it, rather than using the (broken) system-provided DSO.

In conclusion, I believe that building a multi-distro AppImage shouldn't be a matter of building in an old enough distribution, but instead having a sort of SDK (with headers and libs) that would let you build on Ubuntu 16.10 an AppImage that could run in Ubuntu 6.06, for example (yes, maybe a bit extreme example, but just trying to explain that I'm after a sort of cross-compiling environment).

Just as another example, I build all my Windows executables from either Linux or OS X, using mingw64. I've been using the same mingw64 version for years, so my Windows object files are identical no matter if I built them in Ubuntu 16.04 or Ubuntu 10.10. That's the kind of freedom I'm aiming to regarding Linux executables.

jcelerier commented 7 years ago

Of course, I expect that all such system-wide libraries keep backwards compatibility with binaries built against older versions of them

In my experience, this is the case for extremely few libraries, apart glibc. Now that I think of it, this also poses the challenge of package management, if someone wants to use less common libraries...

but instead having a sort of SDK (with headers and libs) that would let you build on Ubuntu 16.10 an AppImage that could run in Ubuntu 6.06, for example

Yes, and I think that the CentOS 6 "root system" could be used at this effect. (Maybe Ubuntu 6.06 is a bit older, I'm not sure). Put its /usr in a subfolder and set it as the compiler's build root.

jcelerier commented 7 years ago

A problem I'm currently thinking of : if I'm not mistaken, every time an AppImage is launched, it ends up being mounted on a different folder. But this means that if I am building a software with a toolchain inside the AppImage, every time the SDK is launched, the toolchain will be in a different folder, which means that for the Makefiles for instance, CC and CXX will change every time the SDK is launched, which certainly means that Make will rebuild the whole code (if it even works).

probonopd commented 7 years ago

Why old versions ? The whole point (in my eyes) of AppImage is to enable the developers to use the latest version of libraries, and distribute their software in old distributions that don't have them.

As pointed out by @cesss I think we should clearly distinguish between core system-level libraries that we expect to be managed by the base system. Here we have to assume the worst, i.e., old versions. Then there are specific libraries that fall into the app domain. Here we can ship the latest and greatest along with the app, since the libraries will only be used by this app and not shared with the system.

As a very rough guideline, look at what macOS bundles ship inside an .app bundle (e.g., Qt because it cannot be assumed to be part of the base system but not libc because it can).

probonopd commented 7 years ago

A problem I'm currently thinking of : if I'm not mistaken, every time an AppImage is launched, it ends up being mounted on a different folder.

This is to ensure applications distributed as AppImages are truly relocatable in the filesystem and do not depend on fixed hardcoded paths. If this is an issue for build toolchains, there is an easy workaround described here which works for Qt Creator.

cesss commented 7 years ago

When you suggest CentOS 6 as a good candidate for building a multi distro executable, what 6.x version and what developer tools versions are you thinking of? I ask this because I'd like to copy headers and libs from it, and try to create a sort of cross-compiler to multi-distro executables.

probonopd commented 7 years ago

I think that CentOS 6 is a reasonable choice because the key libraries in it (e.g. libc) are not too recent but more recent compilers and build tools are still available (e.g., through the devtoolsets). I think you can use the latest release in the 6.x series.

Check https://github.com/portnov/krita-builder for an example.

jcelerier commented 7 years ago

As a very rough guideline, look at what macOS bundles ship inside an .app bundle (e.g., Qt because it cannot be assumed to be part of the base system but not libc because it can).

Honestly, even for libc I'm starting to be a bit dubious. It's extremely rare, but on some occasions the GLIBC ABI did break, and some systems ended up being stuck on the incorrect version (although even more rare on x86). Maybe apple are even more conservative than I wonder if it would not be better sometimes to go all-in with the microsoft policy of shipping the libc along. Or maybe make something such as musl usable ?

@probonopd very cool script, thanks !

I'm sorry, I'd like to get more time to contribute to this (as in, more than posting comments :p) but my work is taking the best part of my time.

probonopd commented 7 years ago

It's extremely rare, but on some occasions the GLIBC ABI did break, and some systems ended up being stuck on the incorrect version (although even more rare on x86).

These I'd call glibc showstopper bugs which should be reported upstream and not be accepted. In fact, Linus Torvalds seems to agree.

probonopd commented 7 years ago

@aleixpol from the KDevelop team is working on using Docker images as SDKs. Would that be an alternative solution?

Suitable Docker images could be built on OBS, e.g., https://build.opensuse.org/package/show/home:probono:branches:OBS:Server:Unstable/OBS-source-services-docker (work-in-progress; any help appreciated).