Compile C++ for all linux distributions - c++

How can i compile my C++ files to work on ALL linux distributions.
The machine that i'll compile them on is Ubuntu 10.10
If i compile them on Ubuntu 10.10, will they work on other Distros like ubuntu, fedora, debian, non debian distros.. etc?

% gcc -o foo foo.c -static
the resulting binary should work on most distros, given that it runs on the same architecture (64bit, 32bit, arm, mips etc).
the main point is: since you do not know what can be found on the target systems in advance, you have to bundle everything you can into either the binary you are shipping or in some kind of "chrooted" environment where you deploy external libs as well (stuff that can't be linked statically) and then have some kind of a wrapper to use your deployed libs instead of the system libs.

Although #akira answer will probably work for your case, it isn't the best solution. Most Linux distros have packing systems which retrieve the dependencies for you.
If you are serious about writing Linux software which is used on other people's boxes, you will need to look into 'GNU Autotools' which is what drives the ' ./configure && make all && make install ' thing which you will have run more than once by now!

It is much harder than it should be, at least for C++: http://www.trilithium.com/johan/2005/06/static-libstdc/

Provided you only use the libraries listed in the Linux Standards Base, a dynamic executable should be fine.
For other libraries, either link with static versions of them, or ship dynamic libraries; I prefer the former.
I would personally recommend avoiding static-linking the C library, as this prevents some useful functionality provided by it working, for example the nss stuff..

Related

what is the difference between lib-mingw and lib-vc2019

I'm new to Windows programming and found that lots of prebuilt libraries for Windows offer libraries like lib-mingw, lib-vc2019, lib-vc2017...
Could anyone help to point out
what is the difference? Which library should I use in what case?
If I want to use Clang on Windows, which one should I use?
Why these different libraries rarely seen on Linux (let's say
Ubuntu), does package managers like apt hide this detail? In other word, why there's no such thing like lib-gcc.a, lib-clang.a on Linux platform?
Mingw (GCC), VC2019 and VC2017 are different compilers. Use the library corresponding to your compiler.
I'm not sure but I think none of them will work with Clang. At least on Linux GCC and Clang are very similar. I mean they are mostly binary compatible, many same compiler flags, many same compiler extensions. Clang tried to make it possible to easily replace GCC in your build pipeline. But all these information is for Linux.
These libraries are not seen on Linux because all these compilers are Windows compilers
You can always build a library with your compiler to use it in your project with your compiler (if you have the sources).
If it's a third party closed source library and you are a paying customer you can ask if they build it for you. It's usually better the add a new compiler to the build pipeline than to lose a customer.

How to deploy C++ app on Linux

My c++ app depends on GCC, MongoDB C++ driver and Boost. My current way is to keep the OS consistent. I develop C++ on Ubuntu 12.04 64bit Desktop, and deploy it on Ubuntu 12.04 64bit server. Also I should install the same version of dependencies on target server.
But If I want to develop my C++ app on Ubuntu 13.04 and use newest Boost, MongoDB driver and GCC 4.8.1, which way is easy to deploy C++ app on Ubuntu 12.04 server.
static linking
Dynamic linking, also deploy all dependencies to target server?
Which way is simple? Sometimes, I cannot compile libraries on target server.
If the dependencies are small easiest way is to compile everything statically. It is fairly easy during the build step, and nothing fancy is needed. However, with bigger libraries, and a bigger project this might get inconvenient.
I think that best practice would be to compile dependencies into shared objects ship them along the binaries and execute stuff in a way that ld will look for your stuff 1st. I think it's possible by for example using LD_LIBRARY_PATH e.g. LD_LIBRARY_PATH=/where/did/i/ship/lib:$LD_LIBRARY_PATH my_binary.
It can be somewhat cumbersome as you need to set up your build system to compile stuff as shared objects and properly pack everything.
I'm pretty sure some of the pre-compiled programs that are shipped for linux work this way. Strangely, I can't find any custom pre-compiled app under my hand at the moment.
It depends on your application. If your application consists of only one specific binary, then static linking of all C++ libraries is in order. You can safely link dynamically all C libraries, as the C ABI is unchanging; this just leaves you with version dependencies. However in most cases the major SO-Name verions are mostly compatible and libraries of differing major SO-Name can be installed in parallel. So I'd rely on the package manager to install those. C++ libraries are tricky due to lack of a common ABI. Even a mere compiler version bump can make them incompatible *sigh*.

Building Boost with LSB C++ Compiler

I want to build my program with LSB C++ Compiler from the Linux Standard Base http://www.linuxfoundation.org/collaborate/workgroups/lsb. Program depends on the Boost library, built with gcc 4.4 version. Compilation fails. Is it possible to build the Boost library with LSB C++ Compiler? Alternatively, is it possible to build the Boost library with some old gcc version, what version is recommended? My final goal is to get my executable and third-party Boost libraries running on most Linux distributions.
Generally, what can be done to get better binary compatibility for Linux distributions, developing C++ closed-source application depending on the Boost library?
I've recently had call to do this, in the event that it's of use to anyone else these are the steps I followed:
Download and install the LSB SDK
Download a version of boost and extract to /opt/boost/boost_<version> (I used 1.43)
Make sure libbz2-dev is installed.
Bootstrap with
cd /opt/boost/boost_<version>
./bootstrap.sh --prefix=/opt/boost --without-libraries=python,mpi --without-icu
Edit /opt/boost/boost_<version>/project-config.jam and add the line
using gcc : : /opt/lsb/bin/lsbc++ : <cflags>-U_GNU_SOURCE <cxxflags>-U_GNU_SOURCE ;
near the top of the file. Note that this will fail if you have a using declaration in one of the other files bjam reads its configuration from, you can pass --debug-configuration to get an idea of which files it's reading.
Run
./bjam cflags=-fPIC cxxflags=-fPIC linkflags=-fPIC install
I didn't try to get either the python or MPI libraries working, nor did I try to get ICU working with the boost.regex library. The latter is probably a case of building static versions of the ICU libraries with the LSB toolset.
The -fPIC isn't strictly necessary for 32-bit Linux, but is required if you want to link static libraries into a shared library for 64-bit Linux.
The end result should be binaries in /opt/boost/lib and headers in /opt/boost/include, obviously you can modify the prefix to suit your own preferences. I still have a fair amount of work to do before I've ported all our code to the LSB, so I can't report on how well the certification process goes yet.
LSB C++ compiler is not actually a compiler. The lsbc++ executable is a wrapper around GCC compiler that is installed on your system (the actual compiler can be controlled via --lsb-cxx option). You will most likely hack into boost build system for it to call LSB wrapper instead of native gcc compiler.
So the issues that may arise are most likely not that LSB compiler can't compile the language constructs, but instead, that there are some linking issues.
For example, LSB compiler by default discards any shared libraries the code is linked against, unless they belong to LSB. This may lead to linking errors if BOOST relies on such libraries. This can be controlled via LSBCC_SHAREDLIBS environment variable, but you should make sure you ship these libs along with your product.
Another issue is that LSB falls behind GCC compiler releases (and BOOST may crawl into all dark corners of compilers). As far as I know, GCC 4.4 is not tested sufficiently, so you'd better try it with 4.3 compiler.
And Google doesn't seem to find anything related to building boost with LSBCC, so if you manage to do it, please, share your experience, for example, as your own answer to your question.

Can I use a shared library compiled on Ubuntu on a Redhat Linux machine?

I have compiled a shared library on my Ubuntu 9.10 desktop. I want to send the shared lib to a co-developer who has a Red Hat Enterprise 5 box.
Can he use my shared lib on his machine?
First point: all of the answers regarding compiler version seem misguided. What's important are the linkages (and the architecture, of course).
If you copy the .so file over to the start system (into its own /usr/local/* or /opt/* directory, for example) then try to run the intended executable using an LD_PRELOAD environment settings. If the linker (ld-linux.so) manages to resolve all the symbols between the two then the program should load and run.
So it should be possible, and reasonably safe (so long as you're not over-writing any of the existing system libraries and just using LD_* /etc/ld.so.preload (in a chroot?) magic to link the target executables to this library.
However, I think it's a bad idea. You have a package management issue. Both Ubuntu and Red Hat have fine package management tools. Use them! (Note the proper place to ask questions about package management would be ServerFault or SuperUser, definitely not SO).
Unlikely: you wouldn't have asked this question if it just worked, would you?
According to DistroWatch, Ubuntu 9.10 uses glibc-2.10.1, while RHEL-5.4 uses glibc-2.5. This means that if your library references any symbols with versions GLIBC_2.6 and above, it will not work on RHEL-5.
You can tell whether you use any such symbols (and which ones) with:
readelf -s /path/to/your/library.so | egrep 'GLIBC_2.([6-9]|10)'
If the output is non-empty, then the library will not work on RHEL-5.
You might be able to build a library compatible with RHEL-5 by using autopackage.
I join to Xinus. IMHO compiler, in case of Ubuntu and RHEL, it will be gcc, is tightly coupled with glibc. So if on both machines it's same, than most probably it caa run.
But why guessing, do a small test drive (main with couple of lines) and if it's running than there's a good chance that a bigger program can run on a "hostile" environment :)
The best solution is to give your code to your co developper,
and let's compile it !!!!
You have several solution
Upgrading his gcc to the same version as your
Install his gcc version on your computer and compile it
You must check if you both work on the same architecture 32 bits or 64 bits.
My opinion is that you can have some problems , because you probably do not use the same glibc
.
Yes, it is possible. Provide a static library to your partner and keep your gcc to the same or compatible version. you can check my post here: https://zqfan.github.io/2021/07/01/cpp-static-library/

Portable shared objects?

Is it possible to use shared object files in a portable way like DLLs in Windows??
I'm wondering if there is a way I could provide a compiled library, ready to use, for Linux. As the same way you can compile a DLL in Windows and it can be used on any other Windows (ok, not ANY other, but on most of them it can).
Is that possible in Linux?
EDIT:
I've just woke up and read the answers. There are some very good ones.
I'm not trying to hide the source code. I just want to provide an already-compiled-and-ready-to-use library, so users with no experience on compilation dont need to do it themselves.
Hence the idea is to provide a .so file that works on as many different Linuxes as possible.
The library is written in C++, using STL and Boost libraries.
I highly highly recommend using the LSB app / library checker. Its going to tell you quickly if you:
Are using extensions that aren't available on some distros
Introduce bash-isms in your install scripts
Use syscalls that aren't available in all recent kernels
Depend on non-standard libraries (it will tell you what distros lack them)
And lots, upon lots of other very good checks
You can get more information here as well as download the tool. Its easy to run .. just untar it, run a perl script and point your browser at localhost .. the rest is browser driven.
Using the tool, you can easily get your library / app LSB certified (for both versions) and make the distro packager's job much easier.
Beyond that, just use something like libtool (or similar) to make sure your library is installed correctly, provide a static object for people who don't want to link against the DSO (it will take time for your library to appear in most distributions, so writing a portable program, I can't count on it being present) and comment your public interface well.
For libraries, I find that Doxygen works the best. Documentation is very important, it surely influences my choice of library to use for any given task.
Really, again, check out the app checker, its going to give you portability problem reports that would take a year of having the library out in the wild to obtain otherwise.
Finally, try to make your library easy to drop 'in tree', so I don't have to statically link against it. As I said, it could take a couple of years before it becomes common in most distributions. Its much easier for me to just grab your code, drop it in src/lib and use it, until and if your library is common. And please, please .. give me unit tests, TAP (test anything protocol) is a good and portable way to do that. If I hack your library, I need to know (quickly) if I broke it, especially when modifying it in tree or en situ (if the DSO exists).
If you'd like to help your users by giving them compiled code, the best way I know is to give them a statically linked binary + documentation how they can run the binary. (This is possibly in addition to giving the source code to them.) Most statically linked binaries work on most Linux distributions of the same architecture (+ 32-bit (x86) statically linked binaries work on 64-bit (amd64)). It is no wonder Skype provides a statically linked Linux download.
Back to your library question. Even if you are in an expert in writing shared libraries on Linux, and you take your time to minimize the dependencies so your shared library would work on different Linux distributions, including old and new versions, there is no way to ensure that it will work in the future (say, 2 years). You'll most probably end up maintaining the .so file, i.e. making small modifications over and over again so the .so file becomes compatible with newer versions of Linux distributions. This is no fun doing for a long time, and it decreases your productivity substantially: the time you spend on maintaining the library compatibility would have been much better spent on e.g. improving the functionality, efficiency, security etc. of the software.
Please also note that it is very easy to upset your users by providing a library in .so form, which doesn't work on their system. (And you don't have the superpower to make it work on all Linux systems, so this situation is inevitable.) Do you provide 32-bit and 64-bit as well, including x86, PowerPC, ARM etc.? If the .so file works only on Debian, Ubuntu and Red Hat (because you don't have time time to port the file to more distributions), you'll most probably upset your SUSE and Gentoo users (and more).
Ideally, you'll want to use GNU autoconf, automake, and libtool to create configure and make scripts, then distribute the library as source with the generated configure and Makefile.in files.
Here's an online book about them.
./configure; make; make install is fairly standard in Linux.
The root of the problem is that Linux runs on many different processors. You can't just rely on the processor supporting x86 instructions like Windows does (for most versions: Itanium (XP and newer) and Alpha (NT 4.0) are the exceptions).
So, the question is, how to develop shared libraries for Linux? You could take a look at this tutorial or the Pogram Library Howto.
I know what you are asking. For Windows, MSFT has carefully made the DLLs all compatible, so your DLLs are usually compatible for almost every version of Windows, that's why you call it "portable".
Unfortunately, on Linux there are too many variations (and everyone is thinking to be "different" to make money) so that you cannot get same benefits as Windows, and that's why we have lots of same packages compiled for different distributions, distro version, CPU type, ...
Some say the problem is caused by (CPU) architecture, but it is not. Even on same arch, there's still different between distributions. Once you've really tried to release a binary package, you would know how much hard it is - even C runtime library dependency is hard to maintain. Linux OS lacks too much stuff so almost every services involves dependency issue.
Usually you can only build some binary that is compatible to some distribution (or, several distributions if you are lucky). That's why releasing Linux programs in binary always screwed up, unless bound to some distro like Ubuntu, Debian, or RH.
Just putting a .so file into /usr/lib may work, but you are likely to mess up the scheme that your distro has for managing libraries.
Take a look at the linux standard base - That is the closest thing you will find to a common platform amongst linux distros.
http://www.linuxfoundation.org/collaborate/workgroups/lsb
What are you trying to accomplish?
Tinkertim's answer is spot on. I'll add that it's important to understand and plan for changes to gcc's ABI. Things have been fairly stable recently and I guess all the major distros are on gcc 4.3.2 or so. However, every few years some change to the ABI (especially the C++ related bits) seems to cause mayhem, at least for those wanting to release cross-distro binaries and for users who have gotten used to picking up packages from other distros than they actually run and finding they work. While one of these transitions is going on (all the distros upgrade at their own pace) you ideally want to release libs with ABIs supporting the full range of gcc versions in use by your users.