ADA static library - compatibility with different versions of compilers - static-libraries

I have built a ADA static library and I share it by providing '.a' and ALI files.
Everything works fine while I use the same GNAT compiler version than the one used to build the static library.
But with another compiler version, the ALI files are considered as not valid (the compiler version is stored in all ALI files), and the compiler needs source files to rebuild ALI files.
Is there a solution to avoid this problem ?
updated on 12/11/2015 : We did some tests (with ALI library files in ready only), but we still have the following errors :
error: "package1.adb" and "prog.adb" compiled with different GNAT versions
error: "prog.adb" must be recompiled ("system.ads" has been modified)
So, I think we have to use the same compiler version for the library and the program.

If you are using gnatmake, make the ALI files read-only, so that the compiler does not try to recompile them (you are of course responsible for ensure that the object files are compatible, but this is in general the case).
If you are using project files, add a
for Externally_Built use "True";
attribute to achieve the same effect.

Answer from AdaCore :
This isn't supported: the Ada ABI (Application Binary Interface) is not guaranteed to stay the same across versions (and indeed does change regularly), so you cannot mix objects compiled with different versions of GNAT, you really need to ensure consistency in all your libraries.
So, it's not possible.

Related

How to build and Interface a Fortran95 library with C

I'm porting an old C++ project to run on RHEL 6.7 with gcc 4.4.7. The code was originally made to run on an SGI machine.
I have a library .a which is presumed to have been compiled on the old machine (and thus there's no hope of running it in the new one) however, along with this .a file I also have the headers and source files. I am assuming that these are the ones that are used to make the .a file. The Makefile that was used is now long gone, I just have the source code.
My question is, is there a way to "reverse engineer" the library? I would like to know what functions the .a library contains so I can make it on my machine.
I will add that I am new to static and shared libraries so I'm not entirely sure what the .a file contains or how it is any different from including the headers.
Update:
I have looked into the included code and realized that the C files only work to interface with functions defined using Fortran95. I think that now I'm supposed to build the Fortran95 codebase and somehow interface that with the C code. Once I do that I will have a library that should (hopefully) compile in my native system. How can I do this?

c++ libs from ubuntu 16.04 repo - compiler options

Ubuntu 16.04 comes with GCC 5.4 which does support c++11 and it is the default compiler. By default c++11 is not enabled in that particular version of GCC.
My intent is to use some of the binary libraries (not header only) from their repository (e.g. boost). In my projects I will enable c++ 11.
How were c++ libraries from the repository compiled? Is it possible to use them with c++ 11 enabled? I know that c++ libraries can be called from different languages (Java, Pythons, C# etc) by hiding all c++ stuff behind plain C interface. With boost it is not a case. If a certain function returns me a string or a vector or anything from STL then it is a problem. AFAIK STL objects binary representation depends on compiler flags (eg. std=c++11).
Thank you.
Which exact libraries are you talking about?
If you are talking about the standard library, libstdc++ is a part of gcc. It is always okay to link it no matter which standard you compile at. gcc also made a decision to include ABI tags, so that they can be ABI compatible with code compiled at C++11 and pre C++11. See for instance TC's really nice answer to a question I asked here:
Is this simple C++ program using <locale> correct?
If by
How were c++ libraries from the repository compiled?
you mean, how are all of the C++ libraries in the ubuntu repositories compiled, the answer is, it may be different for each one.
For instance if you want to use libfreetype6-dev or libsdl2-dev, these are C libraries, they will be okay to link to no matter what standard you target.
If you want to use libsilly-dev from CEGUI, that is a C++ library, and it is usually best to use the exact same compiler for your project and the C++ lib that you are linking to. If it appears in ubuntu repository, you can assume it was built with the default g++ version that ubuntu is shipping. If you need to use a different compiler, it's probably best to build the C++ lib yourself -- in general C++ is not ABI stable across different compilers, or even different versions of the same compiler.
If you want to use compiled boost libraries, it's probably best to use the libs they give you and use the compiler they give you. If you only use header-only boost, then the compiler doesn't matter since you don't actually have to link with something they built. So you then have more flexibility with respect to compilers.
Often, if you need to use C++ libraries, it's best to integrate their build system into yours so that it can be easily rebuilt from source and you only have to configure the compiler once. (At least in my experience.) This can save a lot of time when you decide to upgrade compilers later. If you use cmake then it's often feasible, but sometimes this can be hard, especially if you have a lot of C++ dependencies. If you don't use cmake, well, many libraries use cmake and it won't be that easy to integrate them this way. cmake is still kind of a pain anyways, so this might not be such a loss.

How to properly build third-party library to be used in Debug and Release configurations in my project?

When I need to build some third party library to be used in several of my projects under different version of MSVC, I usually build it for every MSVC version and for both Debug and Release configurations. That's what boost does, and that's what we have been done for our whole life in my team.
However, I still don't get, why couldn't I just build this library with like... whatever. All I need is function prototype and object code, right? Since I'm linking CRT statically, I have no external dependencies. But when I'm trying to link library built in Release under MSVC8 with my project in Debug under MSVC10 I have this annoying "already defined" linker errors which we all hate so much.
But why? Can I just "encapsulate" all this functions inside lib and do not export them so that my project will take only what it needs from the lib? Why can I have precompiled version of libpng and zlib which I can link in every project? Yes, they are not build using MSVC, I guess, but the still uses the same functions of CRT. So can anyone please explain in depth or share a link to some enlightened explanation of this issue?
Since I'm linking CRT statically, I have no external dependencies
Well, that's not true, you do have a dependency. On the static version of the CRT. Debug or Release, depending on your build settings. And it is an external dependency, the linker glues the CRT later, when the library gets linked. The code that uses the library also has a dependency on the CRT. And if the compile settings don't match then the linker barfs.
You isolate that dependency by building a DLL instead of a static link library. You must further ensure that the exported functions don't cause a CRT dependency. You can't return a C++ object from the standard C++ library and can't return a pointer to an object that needs to be released by the client code. Even passing structures is tricky since their packing is an implementation detail, but you usually get away with it. A good practical example is COM automation, it forces you into using a subset of types that are universal. Windows is rife with them and all these servers work with any version of the compiler or CRT. Even any language. This however comes at a cost, writing such a library isn't as simple or convenient as just throwing a bunch of code in a static lib.

Runtime Issues While Mixing Libraries from Different Versions of Visual Studio

I have encountered an unexpected Access Error while running a project I've built using two different versions of Visual Studio. My general configuration is as follows:
LibA is a static lib, static runtime linkage, msvc 8.0
LibB is a static lib, static runtime linkage, msvc 9.0
My target project for integration is a msvc 9.0 COM dll, which statically links the above libraries
This project builds, but crashes up at runtime with an access violation in some STL code. The stack seems to indicate that I've passed through headers both versions (8 and 9) during a call into a stream insertion operator. I realize that this is a problem.
Somehow, this call:
ost << std::dec << port_; //(originating from an object in LibA)
...descends through the following stack trace:
std::basic_ostream::operator<<(...) (ostream:283, msvc 8.0 version <-- expected, since LibA was built with this version)
std::num_put::put(...) (xlocnum:888, msvc 8.0 version <-- expected, since LibA was built with this version)
std::num_put::do_put(...) (xlocnum:1158, msvc 9.0 version!! !##$!%! <-- not expected, since LibA was built with msvc 8.0)
std::ios_base::flags() (xiosbase:374, msvc 9.0 version <-- follows from above)
The access violation happens in std::ios_base::flags(). I suspect it is due to the mix of implementations in the call stack (although I am not sure).
My questions are.
1.) Is the likely cause of this access violation the mixing of msvc header implementations?
2.) Is there a way to prevent these implementations from mixing?
3.) Is there a better way to configure these three projects for integration (assuming moving LibA from msvc 8.0 is undesirable)?
I am aware of the ideas raised in this question and this one. Here I am most interested in this specific problem, and if there is some way to avoid it.
Any insights would be appreciated.
You can't use different STL implementation in the same project. This means even different versions from the same compiler. If your LibA has a function that accepts std::vector as an argument you are only allowed to pass vector object from STL that LibA was built with. This is why many C++ libraries expose only C API.
Either you change your API or you rebuild all your projects using the same compiler.
You are doing something that you shouldn't. You are in the world of undefined behavior. There is no point in trying to debug this particular crash. Even if you managed to make this line work you would get a new crash somewhere else.
There is no guarantee of library binary compatibility between major versions of MSVC. STL code is mostly template code that gets expanded into your code. So you're static libraries probably have incompatible chunks of STL code inside of them.
In general, this shouldn't be a problem, unless that STL code is part of the interface to the library. For example, if you pass iterators or a reference to a vector from one library to another, you're in trouble.
The best solution is to build everything with the same version of the compiler. If you can't do that (e.g., if the one of the libraries is from a third-party), you're probably stuck.

Migrating from Winarm to Yagarto

This question must apply to so few people...
I am busy mrigrating my ARM C project from Winarm GCC 4.1.2 to Yagarto GCC 4.3.3.
I did not expect any differences and both compile my project happily using the same makefile and .ld files.
However while the Winarm version runs the Yagarto version doesn't. The processor is an Atmel AT91SAM7S.
Any ideas on where to look would be most welcome. i am thinking that my assumption that a makefile is a makefile is incorrect or that the .ld file for Winarm is not applicable to Yagarto.
Since they are both GCC toolchains and presumably use the same linker they must surely be compatable.
TIA
Ends.
I agree that the gcc's and the other binaries (ld) should be the same or close enough for you not to notice the differences. but the startup code whether it is your or theirs, and the C library can make a big difference. Enough to make the difference between success and failure when trying to use the same source and linker script. Now if this is 100% your code, no libraries or any other files being used from WinARM or Yagarto then this doesnt make much sense. 3.x.x to 4.x.x yes I had to re-spin my linker scripts, but 4.1.x to 4.3.x I dont remember having problems there.
It could also be a subtle difference in compiler behavior: code generation does change from gcc release to gcc release, and if your code contains pieces which are implementation-dependent for their semantics, it might well bite you in this way. Memory layouts of data might change, for example, and code that accidentally relied on it would break.
Seen that happen a lot of times.
Try it with different optimization options in the compile and see if that makes a difference.
Both WinARM and YAGARTO are based on gcc and should treat ld files equally. Also both are using gnu make utility - make files will be processed the same way. You can compare the two toolchains here and here.
If you are running your project with an OCD, then there is a difference between the implementation of the OpenOCD debugger. Also the commands sent to the debugger to configure it could be different.
If you are producing an hex file, then this could be different as the two toolchains are not using the same version of newlib library.
In order to be on the safe side, make sure that in both cases the correct binutils are first in the path.
If I were you I'd check the compilation/linker flags - specifically the defaults. It is very common for different toolchains to have different default ABIs or FP conventions. It might even be compiling using an instruction set extension that isn't supported by your CPU.

Resources