If you don't want to depend on the libcurl provided by the OS, ship your own.
If you don't want to depend on the glibc provided by the OS, ship your own, with your own dynamic linker.
readelf -n <your binary> will tell you the oldest kernel that will run your stuff. Put that in the requirements document. Write a bash script that sets LD_LIBRARY_PATH correctly and make sure that's the main entry point to your application during deployment.
You're set.
Can you ship with your own version of GNOME different from the currently running one?
I'm confused. GNOME is a desktop environment. It implements a task bar, a control panel, a way to set your desktop wallpaper etc. Why would you ship GNOME?
Maybe you meant shipping a proprietary application that uses a GTK version that is different than the OS-provided GNOME uses?
If so, of course you can. GTK is a bunch of shared objects that generate system calls, X messages, etc. It has no reason to interfere with the OS-provided GTK as long as it's got everything it needs in your bundle.
Snap and Flatpack will hopefully help with the dependency aging problem, but they're brand new, and they both still suck one way or another.
To give you an idea of what swapping out glibc would involve, here is the list of shared libraries loaded by 'glxgears' on my machine, arguably the simplest possible OpenGL program:
/lib/x86_64-linux-gnu/ld-2.28.so
/lib/x86_64-linux-gnu/libbsd.so.0.9.1
/lib/x86_64-linux-gnu/libc-2.28.so
/lib/x86_64-linux-gnu/libdl-2.28.so
/lib/x86_64-linux-gnu/libexpat.so.1.6.8
/lib/x86_64-linux-gnu/libgcc_s.so.1
/lib/x86_64-linux-gnu/libm-2.28.so
/lib/x86_64-linux-gnu/libnsl-2.28.so
/lib/x86_64-linux-gnu/libnss_compat-2.28.so
/lib/x86_64-linux-gnu/libnss_files-2.28.so
/lib/x86_64-linux-gnu/libnss_nis-2.28.so
/lib/x86_64-linux-gnu/libpthread-2.28.so
/lib/x86_64-linux-gnu/librt-2.28.so
/lib/x86_64-linux-gnu/libz.so.1.2.11
/usr/lib/x86_64-linux-gnu/dri/i965_dri.so
/usr/lib/x86_64-linux-gnu/libdrm_intel.so.1.0.0
/usr/lib/x86_64-linux-gnu/libdrm_nouveau.so.2.0.0
/usr/lib/x86_64-linux-gnu/libdrm_radeon.so.1.0.1
/usr/lib/x86_64-linux-gnu/libdrm.so.2.4.0
/usr/lib/x86_64-linux-gnu/libglapi.so.0.0.0
/usr/lib/x86_64-linux-gnu/libGLdispatch.so.0.0.0
/usr/lib/x86_64-linux-gnu/libGL.so.1.7.0
/usr/lib/x86_64-linux-gnu/libGLX_mesa.so.0.0.0
/usr/lib/x86_64-linux-gnu/libGLX.so.0.0.0
/usr/lib/x86_64-linux-gnu/libpciaccess.so.0.11.1
/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
/usr/lib/x86_64-linux-gnu/libX11.so.6.3.0
/usr/lib/x86_64-linux-gnu/libX11-xcb.so.1.0.0
/usr/lib/x86_64-linux-gnu/libXau.so.6.0.0
/usr/lib/x86_64-linux-gnu/libxcb-dri2.so.0.0.0
/usr/lib/x86_64-linux-gnu/libxcb-dri3.so.0.0.0
/usr/lib/x86_64-linux-gnu/libxcb-glx.so.0.0.0
/usr/lib/x86_64-linux-gnu/libxcb-present.so.0.0.0
/usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0
/usr/lib/x86_64-linux-gnu/libxcb-sync.so.1.0.0
/usr/lib/x86_64-linux-gnu/libXdamage.so.1.1.0
/usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0
/usr/lib/x86_64-linux-gnu/libXext.so.6.4.0
/usr/lib/x86_64-linux-gnu/libXfixes.so.3.1.0
/usr/lib/x86_64-linux-gnu/libxshmfence.so.1.0.0
/usr/lib/x86_64-linux-gnu/libXxf86vm.so.1.0.0I do agree that shipping your glibc is "the road to hell" and shipping with the glibc could be qualified as "shipping in the form of its own Linux distro", as amusing as that sounds :) But that's the price of freedom you pay if you want to draw your platform boundary at the kernel -- you need to ship the whole userland! Where's the surprise in that? That means you need to understand the interactions between different version of /usr/lib64/opengl/nvidia/lib/libGLX_nvidia.so.0 (that you need to ship) and nvidia.ko (that is nvidia's binary driver loaded by the kernel, that you do NOT ship)
That's what people mean when they say they "are targeting Linux", even when they don't really understand the kind of work that that statement entails :)
Linux is an OS kernel. I'd wager it's the most popular one by far, in terms of the number of platforms that uses it.
Saying that "Linux is fragmented" is the wrong way to look at the problem. One should rather realize that Linux is just and OS kernel that is used by countless platforms. It's up to the developer to draw platform boundaries and focus engineering effort on the chosen ones.
If you need to support GNU/Linux with glibc-2.25, then you need to set up your testing bench to accommodate that. If you need to have native look and feeling in ubuntu, kubuntu and lubuntu, you already have 3 platforms with at least 2 LTS versions that you need to test with.
Each platform has its own quirks. Linux distros are the ones with the least amount of quirks, but in exchange we get many many platforms, because it's so easy to create them.
I guess that's life :)
I wanted to check whether the official Nvidia driver uses C++, but it's not installed on this machine just now, and of course that I even have to check just highlights the problem with this approach.
I don't know for nvidia, but I had a problem two years ago on a machine with a radeon card: I was developing a GUI software which used LLVM at some point. Insta-crash at runtime on this computer whenever I'd oepn a window. The reason ? the radeon driver linked and initialized LLVM which didn't support being initialized twice...
> So it means for every product, have a build for every distro / version combination you want to support.
Of course it's a total pain in the ass, but it's still vastly preferable to unfixable bugs sometime in the distant future
The actual difference is that Visual C++ and XCode (presumably) automate most or all of this, since this is the standard way of compiling and distributing applications for those platforms. In contrast, Linux development tends to revolve around software that can be recompiled for each distribution, so the tooling is going to be optimized around a workflow of relying on system-wide libraries and binaries and other data managed by a package manager.
I won't comment on shipping your own glibc, because that probably could cause issues.
The thread has then been detached for the crime of discussing voting, so only we can see it.
The first rule of HN voting is not to discuss voting.
Now there is an opportunity for silent memory corruption in your program, one that even once detected, which may not happen for years, cannot easily be fixed without completely rearchitecting the build.
When using a wide variety of system APIs including at least NSS and OpenGL, there is little control over what dynamic libraries end up loaded, the exact configuration will vary across machines
Substitute libcurl for libexpat or libX11 or libstdc++ and the principle continues to apply. I can't think of a good reason something like libcurl would be used by the Nvidia driver or some bizarro embedded board's GL driver, but that doesn't mean the Nvidia driver doesn't now or in the future link it, and if/when that day arrives, the problem lies entirely with the program that mixed random system deps with random self-compiled deps.
This whole thread is about avoiding this.
But isn't this what you're doing with Windows? No version of Windows comes with libcurl (as far as I know) so you put the DLL in your application directory. It's no different.
On Linux, I could have statically linked curl, but didn't realize it was going to become an issue. Ubuntu 18.04 was released and curl3 was removed, so that means our software that was working was either automatically removed by the package manager or it started crashing.
libcurl may or may not be a good example but surely all software has dependencies that isn't shipped with OS. In Linux case the special pain is, library that is shipped with OS might be outdated but bundling compiled lib/o/so files should work.
Of course, quite a few game developers are curiously averse to publishing any kind of source code, which tends to thus require compatibility efforts to happen on the developer side instead of the package maintainer side. This can still be worked around by targeting a specific distro (say, Ubuntu or SteamOS) and letting package maintainers for other distros apply whatever workarounds they deem necessary to get the app running outside of a "supported" environment (see also: Steam, Spotify, Slack, etc.).
All of the commercial packages I've used at work for the past 15 years target either one or a handful of distros. Even the open source stuff that's either too new or outside of the default repos I much prefer to install from a package; turbovnc, grafana, chrome, etc. The few games I've seen have worked the same way as other commercial user-oriented apps.
The automatic fallback to system libraries can also lead to mysterious problems.
${ORIGIN}/lib will be the relative library path.
Some useful stack overflow answers on this topic. First, the trick to get GCC to pass the ORIGIN option to the linker: -Wl,-z,origin.
Secondly, how to pass it as the rpath option:
"-Wl,-rpath,'$ORIGIN' -- note that you need quotes around it to avoid having the shell interpret it as a variable, and if you try to do this in a Makefile, you need $$ to avoid having make interpret the $ as well."
https://stackoverflow.com/questions/38058041/correct-usage-o...
The chrpath utility is also fascinating, as it allows you to rewrite the elf headers to change the rpath. Possibly better for installs than passing lots of env variables.
Various warnings on this topic to not use actual relative paths unless you really want that behaviour.
We statically link everything except glibc, which we've decided to dynamically link to glibc 2.23 (meaning that Ubuntu 16.04 is the oldest we support). We've had no problems with this approach, although the disadvantage is that we have to use an old version of GCC to compile the software, since I haven't figured out a way to make a new GCC version produce binaries which link to old glibc.
No need for containers or anything, just make a mostly-static-except-for-glibc binary.
I personnally compile with latest GCC or LLVM on centos 7, this way I can use the very latest C++ standards with a venerable glibc
I maintain about two dozen software packages in the AUR, including some really old stuff like the Heretic 2 Linux release from 1999 and RBDoom 3 BFG which has a boatload of dependencies. Breakages are extremely rare for the average package even with the rolling release and generally any breaking change in a common library will see the legacy version hang around since stuff will still depend on it.
For the freedesktop one, they have following policy[1]:
- When a new stable release release is done, the changes on that branch will only be:
- security updates
- stable releases (tested carefully); no ABI breaks / API build breaks.
- we will try to keep updating that branch as much as we can
- We release a new major release every year, only if:
- There is a ABI break
- There is a "API build" break (apps might not compile because new major releases of important packages (GCC))
- Looking at the GCC and other major project cadences, this is likely going to happen annually.
- We only maintain the current stable release and the previous one, this means:
- Stable releases get 2 years of security updates
- We maintain maximum 3 releases at any given time:
- Development
- Stable
- Old stable
[1] https://gitlab.com/freedesktop-sdk/freedesktop-sdk/wikis/rel...But there is always static linking, is it not? (And now flatpak+snap+...)
I used to but I'm switching to a different model
> Do you do a separate AppImage for each plugin?
no, they are just loaded as .so / .dll / .dylib in the ~/Documents/score/addons folder. They can't have further dependencies though.
Some people have written about AppImages, this also applies to FlatPak and similar techs too. Isolating anything more complicated than a command line tool is the way forward and the tech exists. Not using isolation this way is a recipe for pain, whether it be on the desktop or the server (or the phone).
It depends how the plugins are loaded - it'd be great if they could use sockets so that AppImages were viable. No idea myself, though.
I did this once with a ruby gem that had particular c++ dependencies that kept breaking when the build machine had different library versions than the production machines. If you aren't integrated directly with the development of a linux distro, it's best not to use their packages as runtime dependencies, since they really only consider their own use before changing things up.
it is a blessing to be able to work with a different paradigm than piano roll and with such modern tooling (renoise supports vsts, rewire integration and whatnot), being essentially a supercharged tracker.
Doing audio synthesis with JS or any other interpreted language really is totally possible and has been done in a more or less serious way in several implementations and webtoys etc. But if you need extremely low latency and guarantees you cannot go that route, sadly.
the UI is the minority of the code. the main engine is gonna need to be implemented in some language which has strict guarantees about performance. also, not having a garbage collector that fires in a seemingly random way helps a lot too :)
ad to the third point: Music producers already require and use pretty powerful rigs: 32-128GB RAM is not uncommon, CPU as good as it gets. There's great benefit when you can run 100 instrument synthesizer instances parallel vs 14 instances - it's a difference between a differentiated orchestra and a rock band.
What if game developers release the game's source code and let community developers help with porting to different distros and platforms? The game's assets can remain paid. For example, Doom has been ported to pretty much all platforms, and it's up to maintainers to ensure compatibility. I guess at this point it becomes a partly open source/free software game.
I'm aware this may not align with current business practices.
> And distos aren't backwards compatible. ie when libcurl4 is released, they remove libcurl3. So you can't have one binary for Ubuntu 18.04 and 16.04.
Release the source and the community will help you with many of these issues.
In contrast to Windows you can provide or pay someone to provide libcurl3 if you want to continue to use it. MS will just say you can go F yourself.
In contrast to Windows you can study the source code and write a wrapper that provides a central API point that you can use in your single code base.
In contrast to Windows you can actually go there and provide patches. Even if the original authors won't merge it you can still use it via a fork etc.
And last but not least I bet there are actually still people supporting and providing libcurl3 binaries to this day and you just need to google their package server and add 2 lines to your installer script (one to add the public key for that package repo and one to add the package repo to your package manager).
PS: If you provide software for sizable amounts of people you need to provide 1-3 out of 3 reasonable Distros: Debian, RHEL, Suse. Even if you just provide one most people can deal with it thanks to VMs or docker.
In my experience, MS doesn't say go F yourself. They go to extreme lengths to keep old software working.
I think you picked a terrible example there, because quite often people do; certainly Vista upwards is quite normal (that was the transition point for lots of APIs).
Windows is much clearer about how you're supposed to solve "DLL hell". You have the OS libraries, which provide a stable API; COM, where interfacing is done at runtime dynamically; and for everything else you put it in your application's directory.
Theoretically if COM components aren't interchangeable - the API has expanded - they should have a different CLSID and therefore not clash.
The main issue is that 'Linux' is not a thing you can support. You have to pick the distros you want to support, and then once you've picked a distro, what versions you want to support.
And you need to use the C++ version that ships with that distro, so if you want to support old versions then the entire project is held back from using latest C++.
And distos aren't backwards compatible. ie when libcurl4 is released, they remove libcurl3. So you can't have one binary for Ubuntu 18.04 and 16.04.
So it means for every product, have a build for every distro / version combination you want to support.
So now the solution is AppImages where you bundle up your app with all dependencies like a container. Haven't investigated this yet, not sure it will work for plugins.