views:

678

answers:

7

What are some methods I can use to ship a closed-source application for linux?

At the moment the application links against a few libraries (WxWidgets, GraphcisMagic, Crypto++, etc).

  • Statically link everything to a single executable?
  • Include the Libraries in a package?
  • Ship the Dynamically Linked executable (and have the user get the libs needed)
+9  A: 

Linux is a tough platform to deploy client software to, if the software isn't open source (though if it is OSS, you can often get the more popular distributions to include it right in their repositories). I suspect that the biggest reason there isn't more commercial software for Linux is that the distributions are so fragmented. They all have different versions of libraries (which I believe is your concern), they install things to different places, they have different package formats, and the most popular distributions release new versions of everything on 6-8 month release cycles.

Skype does something interesting: They offer pre-compiled packages built for specific popular distributions. They also offer a statically-linked bundle (also one that is dynamically linked, but for an app like that, probably not as useful). I imagine that it is a fair amount of work, since they have to at least keep a VM around to do builds for each distribution/version combination, but it does mean that for the more common distributions, things are really easy, and for everyone else, it is still possible to use it. And with a few VMs and some clever scripting, the whole thing can be automated, albeit with a bit of work getting it right the first time around.

Adam Batkin
i think that's the way to go. novell has an online build service, that can handle most of the grunt work. when launched, it was supposed to support several distros; but i'm not sure if it delivered on that front
Javier
Do you know if you can you use their build service for non-OSS?
Adam Batkin
+2  A: 

If you want to support multiple versions or distros, your best bet is to link statically to such libraries(and try your best to link dynamically to common libraries that's pretty ABI stable and found on most distros, e.g. libc, X libraries).

Even that is hard, there's always some minor differences between distros and versions. Compile your app on RedHat 5.x and it might fail on RedHat 4.x cause of some libc@GLIBC_X_X symbols(Compile on RH 4, it'll likely run fine on RH 5 though).

So in the end, to be able to support your customers, you're going to have to install and build for the distro your customer has. VMWare or something similar is great for this kind of support.

nos
+6  A: 

The additional complexity is that you should not link glibc statically, because if you do, the libnss plugin system won't work properly since the glibc that is statically linked may require a different API or version to communicate with the dynamically loaded nss plugins.

Follow the thread on trolltech about "Almost Completely Static Binaries":

Unfortunately, it is not so straightforward when there are different glibc major versions involved. If you can allow for only a specific glibc major version, then you should link everything static EXCEPT glibc, and you can use the -Wl gcc option to pass options to 'ld' like '-Wl,-Bdynamic' and '-Wl,-Bstatic' for each individual library; see http://linux.sys-con.com/node/48565 for examples.

It is probably best to set up a hudson build server with a bunch of virtual machines running the different linux distributions that you DO want to explicity support and compile the binaries on them.

--jdkoftinoff

jdkoftinoff
not that it's relevant to the content of the response at all, but sys-con.com has a reputation for stealing content. you might want to find another source for that link.
DDaviesBrackett
thank you, i did not know that.
jdkoftinoff
+3  A: 

The Linux Standard base aims to solve the issue of variance between distribution. In theory, packaging your app according to their recommendations should ensure it works on most common distributions. In practice, I don't know how well that work.

Note that if your application is important enough for your customer, you may be in position to say "we support only these distributions with at least that set of patches". That's what we do and in practice our customers are using other distributions without problem. As we are doing no important effort for that, that means that the variation between distribution aren't so important for what we do.

We are using dynamic libraries, but our application is launched via a script which set the LD_LIBRARY_PATH so that it finds the libraries we are providing: nearly all of them (included QT) excepted things like libc and libX.

AProgrammer
+5  A: 

For standard libraries (like crypto++, pthreads, etc) that are likely to be available in a distribution -- link dynamically and tell users to get them from their distro repository. Or link statically if it is feasible.

For weird libraries that you must control version of (if you want to deploy Qt4 app on territory of enemy gnomes for example), compile them yourself and install into a private spot only your app knows about.

Never install private libs into standard places unless you can be sure to not interfere with package systems of all distros you support. (and that they can't interfere with you either).

Use rpath instead of LD_LIBRARY_PATH, and set it properly for all you binaries and all dlls that reference each other. You can set rpath on you binary to "$ORIGIN;$ORIGIN/../lib;/opt/my/private/libs" and have linker search those places before any standard paths. (have to setsome linker flag for origin to work I think). Make sure to set rpath on your libs too: for example QtGui needs QtCore, and if user happens to install standard package with different version, you absolutely don't want it picked up (exe -> ../lib/QtGui.so (4.4.3) -> /usr/local/lib/QtCore.so (4.4.2) -- a sure way to die early).

If you compile with any rpath, you can change it later with chrpath, thus making it possible to tweak install location as part of post processing or install script.

Maintain binary compatibility. GLIB_C is pretty much static for your users, so you should link against some sufficiently old version. 2.3 is a safe bet. You can use APBuild -- a gcc wrapper that enforces GLIB_C version and does few other binary compatibility tricks, so you don't have to compile all you apps on a really old distro.

If you link to anything statically, it generally will have to be rebuilt with APBuild too, otherwise it is bound to drag newer GLIB_C symbols. All .so's you install privately will naturally have to be built with it too. Sometimes you have to patch third party libs to use older symbols. (I had to patch ruby to return real permissions instead of effective ones, since there is no such functions in older GLIB_C. Still not sure if I broke anything :)).

For integration with desktop environments (file associations, mime-types, icons, start menu entries, etc) use xdg-utils. Beware though, like everything on linux they don't really like spaces in filenames :). Make sure to test those things on each target distro -- xdg implementations are riddled with bugs and quirks.

For actual install you can either provide variety of native packages (rpm, deb and a few more), or roll out your own installer, or find installer that works on all distros bypassing native package managers. We successfully used Autopackage (same people who made APbuild) for that.

Eugene
+3  A: 

For our Qt based application on Linux we deploy in a similar way to windows with the libraries along side the application binary, however we need to update the library path to read them. For starting the application we have a shell script to do the launching:

# Lynx.sh
export LD_LIBRARY_PATH=./plugins/imageformat:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=./plugins/sqldrivers:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./Lynx.bin

This has proven to work best for us as we know its going to work as expected. The downside is that we have to update the libraries to keep up with bug fixes. However with continuous integration and built in application auto-update its not so painful.

Phil Hannent
We do the same on our company and I think is really the best way (because is simple and works.)
juanjux
We have a crossplatform installation tool (http://bitrock.com) and many of our users are Qt app vendors. They do exactly as Phil mention. In many cases the installer is simply to provide some feedback during installation and then substitute the wrapper scripts with the right installdir. For the widest platform adoption, it is important to compile in a platform with a relatively older glibc (like Red Hat 9)
Daniel Lopez
+1  A: 

Your question is a legal question as much as it is a technical one as you are using OSS components with a closed source application you have to be clear on how the OSS licenses affect your application.

The requirements of the different OSS licenses will restrict the choices you have when it comes to re-distribution.

To get a proper answer to your question you need to specify all the OSS components you are using and how they are linked to your application.

Eoin