I have an old application framework that must be compiled with gcc 4.4.4 and an old libstdc++.so, which don't support C++14.
I want to use gcc 6.2 to write my new functions in C++14, and compiled them into a static library myslib.a.
myslib.a exports its functions only in pure C interfaces for ABI compatibility.
My issue is: The framework uses an old libstdc++.so, which is not compatible with C++14.
Is it possible to enforce myslib.a to statically link the latest libstdc++.a and ignore the older libstdc++.so?
Related
The common explanation for not fixing some issues with C++ is that it would break the ABI and require recompilation, but on the other hand I encounter statements like this:
Honestly, this is true for pretty much all C++ non-POD types, not just exceptions. It is possible to use C++ objects across library boundaries but generally only so long as all of the code is compiled and linked using the same tools and standard libraries. This is why, for example, there are boost binaries for all of the major versions of MSVC.
(from this SO answer)
So does C++ have a stable ABI or not?
If it does, can I mix and match executables and libraries compiled with different toolsets on the same platform (for example VC++ and GCC on Windows)? And if it does not, is there any way to do that?
And more importantly, if there is no stable ABI in C++, why are people so concerned about breaking it?
Although the C++ Standard doesn't prescribe any ABI, some actual implementations try hard to preserve ABI compatibility between versions of the toolchain. E.g. with GCC 4.x, it was possible to use a library linked against an older version of libstdc++, from a program that's compiled by a newer toolchain with a newer libstdc++. The older versions of the symbols expected by the library are provided by the newer libstdc++.so, and layouts of the classes defined in the C++ Standard Library are the same.
But when C++11 introduced the new requirements to std::string and std::list, these couldn't be implemented in libstdc++ without changing the layout of these classes. This means that, if you don't use the _GLIBCXX_USE_CXX11_ABI=0 kludge with GCC 5 and higher, you can't pass e.g. std::string objects between a GCC4-compiled library and a GCC5-compiled program. So the ABI was broken.
Some C++ implementations don't try that hard to have compatible ABI: e.g. MSVC++ doesn't provide such compatibility between major compiler releases (see this question), so one has to provide different versions of library to use with different versions of MSVC++.
So, in general, you can't mix and match libraries and executables compiled with different versions even of the same toolchain.
C++ does not have an ABI standard as of yet. They are attempts to have it in the standard; You can read following it explains it in details:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2028r0.pdf
Having gone through a number of similar questions (see below), I don't think any of them cover this case.
Problem
Is it possible to dlopen and use a C++11 shared library compiled using gcc 4.9 from a C++03 application compiled with gcc 4.1? Both the library and application use libstdc++, including on the API (but not std::list, which is apparently a problem). I can't change the way the application is compiled (sadly), and must be certain that existing code doesn't break (e.g. if it ends up dynamically linking to a new version of libstdc++.so).
As far as I understand it (which is not very), on Linux the dynamic linker uses a flat namespace, meaning that is not possible to have the same symbol defined in two libraries. Does statically linking the library against the newer libstdc++ help at all here, or is there perhaps some other way?
Some similar questions that don't seem to answer this
C++11 backwards compatibility
C++03 library with C++11 source code
C++11 compatibility with existing libraries/frameworks
Can a compiled C++11 library (lib,dll,etc.) be linked in older C++ compilers? [softwareengineering.stackexchange.com]
If you do that, you definitely need to use the newer libstdc++.so.6, which should be compatible with the system libstdc++.so.6 based on GCC 4.1 (in the sense that GCC upstream intends to preserve ABI compatibility for the library). It would be a very good idea to use the libstdc++.so.6 library that came with the GCC 4.9 compiler.
Once you do that, it is supposed to work, unless you hit the few of the compatibility gotchas you already listed, and as long as the C++ part of the library interface actually sticks to the C++98 subset and does not use any constructs which are not expressible in the language subset.
All this assumes that the library was actually compiled on the the system which uses GCC 4.1, which probably has something like glibc 2.5. If the library was compiled on a completely different, newer system, then you will likely run into library compatibility issues beyond libstdc++.so.6, and these libraries tend to be even harder to upgrade.
(There is also the possibility that the library was explicitly compiled for use with the 4.1-based system libstdc++.so.6 and everything just works, just as if by magic, but then you wouldn't be asking here, I suppose.)
If you still have problems there is the option to use a statically linked C-API library as border between the two, application and your library, see this post.
Also you may be able to explicitely demand an old version of a symbol, see this post
I am writing an application and I would like to use GCC 4.8 on rhel7. My problem is that I need to use a 3rd party shared lib which was built using GCC 4.4 built on rhel6.
Someone suggested I create an interface between my app
and the library using extern "C" to avoid ABI issues of going between c++03
to c++11, and only pass simple C structs in the interface.
That's a meaningful suggestion as it's too hard to preserve ABI compatibility in C++ interfaces.
But they also suggested its possible I might have to copy and link
libstdc++ and libgcc from the rhel6 machine since the 3rd party lib
(and my interface) is built using those. This is where I am confused.
Both libgcc and libstdc++ preserve backwards compatibility (unless in GCC5 but that's not your case) so the 3rd party lib should work just fine with RHEL7 libs.
Given that the major version (libName.so.major.minor.x.z) of libstdc++
and libgcc is the same on rhel6 and 7, do I really need to copy them
from rhel6 to 7?
No (see above).
Cant I build my interface on rhel6, and just copy it along
with 3rd party lib to rhel7 (without copying old libstdc++/libgcc)?
Yes, this will work.
I mean, since stuff built using old libstdc++/libgcc
should be forward compatiable, no?
Correct (they usually say that "new versions of standard libs are backwards compatible i.e. software compiled with older libs will continue to work").
Can I run into issues (ABIs)?
If you somehow manage to pass STL object created in one libstdc++ to another you'll have weird errors. But if both your and 3rd party library have pure C interfaces this should not be an issue (as there's no way for STL objects to escape their containing libraries).
If I do need to copy libstdc++ and libgcc from rhel6,
and link new and old versions together -- how do i do that?
will there suggestion of statically linking the new versions work?
This would be unnecessary burden.
I am currently writing a library and am considering moving from GCC 4.1.2 to 4.5.2 (latest release) of GCC. If I compile my code into a static library can I assume compiler compatibility (on the same OS obviously) should be a non-issue for clients?
EDIT
To further clarify: if I provide a client a statically linked library compiled with gcc 4.5.2, what restrictions does this place on users of this library in terms of the compiler and version they must use?
Just came across this which I believe answers my question from http://gcc.gnu.org/bugs/#nonbugs:
ABI changes The C++ application binary
interface (ABI) consists of two
components: the first defines how the
elements of classes are laid out, how
functions are called, how function
names are mangled, etc; the second
part deals with the internals of the
objects in libstdc++. Although we
strive for a non-changing ABI, so far
we have had to modify it with each
major release. If you change your
compiler to a different major release
you must recompile all libraries that
contain C++ code. If you fail to do so
you risk getting linker errors or
malfunctioning programs. Some of our
Java support libraries also contain
C++ code, so you might want to
recompile all libraries to be safe. It
should not be necessary to recompile
if you have changed to a bug-fix
release of the same version of the
compiler; bug-fix releases are careful
to avoid ABI changes. See also the
compatibility section of the GCC
manual.
Remark: A major release is designated
by a change to the first or second
component of the two- or three-part
version number. A minor (bug-fix)
release is designated by a change to
the third component only. Thus GCC 3.2
and 3.3 are major releases, while
3.3.1 and 3.3.2 are bug-fix releases for GCC 3.3. With the 3.4 series we
are introducing a new naming scheme;
the first release of this series is
3.4.0 instead of just 3.4.
From this as I understand it I'll need to ensure clients are linking my library in with a major-release compatable version of gcc.
It doesn't really matter if you are providing a static library or dynamic library, the users will still need to use a compatable compiler/linker to link against it. Usually when GCC does a ABI change they offer a switch that can be set to use the old ABI. I know that they did that when they went from 3.x to 4.x and even a couple of the releases within the 4.x series.
I am working on redhat 5.2 on a project which spans several disparate organizations. Each organization delivers libraries which have been compiled with various versions of g++. Currently, these versions include 4.1.1, 4.1.2 and 4.3.1. I am trying to link all the libraries together into an executable using 4.1.2. What, if any, problems may I expect by doing this? As an aside, is there a way to tell which ABI each compiler version builds to?
This ABI policy document details the compatibility between different ABI versions.
According to that, the libstdc++.so library should be compatible, and the last time gcc broke binary compatibility was at 3.4. You should be fine.
GCC (GNU Compiler Collection) defines version numbers and compatibility.
The G++ libraries between 4.1.1 and 4.1.2 should be compatible; link with the newest.
The G++ libraries between 4.1.x and 4.2.x are not compatible; you need to recompile something.
The G++ libraries between 3.x.y and 4.p.q are not compatible; you need to recompile something.
In your scenario, the code built with 4.3.1 is not compatible with the rest.
Either you will have to rebuild the code currently compiled with 4.3.x so it uses 4.1.x, or you need to recompile the code currently compiled with 4.1.x so it uses 4.3.x instead.
Maybe it is easier to static link the executable... makes a big binary, but runs on all platforms.
There should be no problems linking libraries built from different versions of g++ unless they've been listed on the g++ website. What is important though is that these libraries be built on the same platform which in your case is redhat 5.2. A library built for a platform other than linux/redhat (say solaris) will not link with your exe.
IIRC, there is a C++ compatibility library that is used to do just that. I think it's called libstdc++-compat.