How do I cross compile a static library built on the target with static linkage using c++11 utilities - c++11

**Edit: Found my problem. As explained by the following answer, I was not actually doing any linking when making the static library. Instead, I made a shared library and linked libstdc++ statically.
Compile a static library link with standard library (static)**
I am trying to create a method to use c++11 on an ancient arm platform running kernel (2.6.37). Unfortunately the latest cross compile our BSP contains is GCC 4.5.3, which does not support all the c++11 utilites we need.
Initially I tried to use old versions of crosstool-ng to build a cross compiler, but the older versions were too broken. The newer versions did not support the 2.6.37 kernel. I was able to complete one build, however the g++ binary was not built, making the whole endeavor useless (I did check that c++ was enabled in the menuconfig).
Thus my last option was to build gcc natively at version 4.9.4 and create a statically linked library to have my gcc 4.5.3 cross compiler link against. This seems to work for the most part. I create my library on the target with the following:
g++ -std=c++11 --static -c main2.cpp
ar -cvq libmain2.a main2.o
I then copy over the files and try build on the host machine with gcc 4.5.3 and get the following:
arm-angstrom-linux-gnueabi-g++ simple.cpp -lmain2 -L.
(I cleaned up some of the output)
undefined reference to `std::_Hash_bytes(void const*, unsigned int, unsigned int)'
undefined reference to
std::__throw_regex_error(std::regex_constants::error_type)'
However, when I use nm, I get the following:
$ arm-angstrom-linux-gnueabi-nm libmain2.a | grep Hash_bytes
U _ZSt11_Hash_bytesPKvjj
U _ZSt11_Hash_bytesPKvjj
$ arm-angstrom-linux-gnueabi-nm libmain2.a | grep throw_regex
U _ZSt19__throw_regex_errorNSt15regex_constants10error_typeE
U _ZSt19__throw_regex_errorNSt15regex_constants10error_typeE
Does anyone know what the heck is going on? Unfortunately we need to be able to use our cross compiler on the host system for most work, but we are also needing to integrate this specific library which uses c++11.
Also note that if I take out the regex and hash functionality from my code but leave other c++11 concepts like nullptr, type inference, delegation etc, the code compiles and runs on the target fine.
Edit: Okay, so after a little more investigation, it looks like the functions _Hash_bytes and __throw_regex_error are not being statically linked into the static library. I guess I need to know why this is the case in order to fix the issue.

Related

remove search paths from arm-linux-gnueabihf-g++ while cross compiling with sysroot

I want to cross compile my c++ program for an arm beaglebone. Compilation and linking works, but the binary is linked to the wrong version of libstdc++ and execution fails with
/usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version `GLIBCXX_3.4.21' not found
On my host I have:
strings /usr/lib/gcc-cross/arm-linux-gnueabihf/5/libstdc++.so | grep GLIBCXX_3
...
GLIBCXX_3.4.20
GLIBCXX_3.4.21
An image of the beaglebone is mounted on ~/bbsysroot:
strings ~/bbsysroot/usr/lib/arm-linux-gnueabihf/libstdc++.so.6 | grep GLIBCXX_3
...
GLIBCXX_3.4.20
So, clearly, there is a version mismatch. That version mismatch is hard to avoid, since the host system is a different distribution.
The compilation command starts with
/usr/bin/arm-linux-gnueabihf-g++ -mfloat-abi=hard --sysroot=/home/user/bbsysroot
so I'm supplying the sysroot of the beaglebone to the compiler. I want that it looks for the libs in there and only in there. But
/usr/bin/arm-linux-gnueabihf-g++ --sysroot=/home/user/bbsysroot -print-search-dirs | grep libraries | sed 's/:/\n/g'
libraries
=/usr/lib/gcc-cross/arm-linux-gnueabihf/5/
/usr/lib/gcc-cross/arm-linux-gnueabihf/5/../../../../arm-linux-gnueabihf/lib/arm-linux-gnueabihf/5/
/usr/lib/gcc-cross/arm-linux-gnueabihf/5/../../../../arm-linux-gnueabihf/lib/arm-linux-gnueabihf/
/usr/lib/gcc-cross/arm-linux-gnueabihf/5/../../../../arm-linux-gnueabihf/lib/../lib/
/home/user/bbsysroot/lib/arm-linux-gnueabihf/5/
/home/user/bbsysroot/lib/arm-linux-gnueabihf/
/home/user/bbsysroot/lib/../lib/
/home/user/bbsysroot/usr/lib/arm-linux-gnueabihf/5/
/home/user/bbsysroot/usr/lib/arm-linux-gnueabihf/
/home/user/bbsysroot/usr/lib/../lib/
/usr/lib/gcc-cross/arm-linux-gnueabihf/5/../../../../arm-linux-gnueabihf/lib/
/home/user/bbsysroot/lib/
/home/user/bbsysroot/usr/lib/
shows, that it also looks on the host. I presume, that the host libraries have a higher priority and hence the wrong version is taken.
Is it possible to force the cross compiler to use the libraries from sysroot only? Or is that utterly wrong for some reason?
I got an answer, which might solve the problem, but i've moved on to another project since and can't test it. Though it might help others:
libstdc++ and also libgcc are actually part of the compiler and I think
that the best solution is:
use compiler version used by the BBB system (or earlier version)
upgrade those libraries on the BBB system
use '-static-libstdc++' option
You can try to use never compiler with older libgcc and libstdc++,
but I think that gcc may reference some newer functions. g++
also links libgcc dynamically by default.

Can't get GCC's -static-libgcc working with DYLIB libraries on Mac OS X

I've installed GCC 4.6.3 into a non-system path on a Mac system and it works fine. However, GCC wants to use code from libgcc for all the binaries I compile, and running otool -L shows that these compiled programs look for libgcc_s.1.dylib in GCC's install path. I can override this by passing -static-libgcc, which just compiles the stuff needed into the binary and that's fine. The problem is this only seems to work with executables, not shared libraries. If I use GCC to compile some third-party lib I want to use in one of my programs as a .dylib, these libraries still look for libgcc_s.1.dylib in the local GCC install path even if I specify -static-libgcc! Needless to say, this is a problem as there's no guarantee that those libraries will find libgcc when run on some other system.
I tried this with ffmpeg. If I look at config.log, the -static-libgcc is most certainly being used. GCC is just not linking libgcc statically with the resulting dylibs. I even tried the -nostdlib, -nostartfiles and -nodefaultlibs options but they were ignored. Again, I checked config.log and they're definitely there!
I believe this is to do with throwing exceptions across the shared library boundary. This page says:
There are several situations in which an application should use the
shared libgcc instead of the static version. The most common of these
is when the application wishes to throw and catch exceptions across
different shared libraries. In that case, each of the libraries as
well as the application itself should use the shared libgcc.
Therefore, the G++ and GCJ drivers automatically add -shared-libgcc
whenever you build a shared library or a main executable, because C++
and Java programs typically use exceptions, so this is the right thing
to do.
The rest of that sections gives a possible workaround (it appears) and that is to use the GCC driver to link your shared library, however if the statically-linked library throws exceptions you'll probably get a Segmentation Violation.

GCC link order changed?

I am trying to link a C++ module using GCC, essentially like this:
gcc -c hello.c
g++ -c world.cpp
gcc -ohello -lstdc++ hello.o world.o
Note that I use -lstdc++ to link the C++ module in, so that I can use gcc instead of g++. The problem is that I'm getting the error:
undefined reference to `operator new(unsigned long)'
(Assuming that world.cpp contains at least one call to new.)
This error is fixed if I put -lstdc++ at the end of the linker line, like this:
gcc -ohello hello.o world.o -lstdc++
I am aware that this question has been asked many times here, but I have a special requirement. I am not directly calling GCC. I am using a build system for a different programming language (Mercury) which is calling GCC on my behalf, and I can't easily modify the way it calls GCC (though I can specify additional libraries using the LDFLAGS environment variable). So I have two additional requirements:
I cannot use g++ to link (only gcc) -- that is why I am doing the -lstdc++ trick above rather than simply linking with g++).
I don't think that I can control the order of the linker commands -- Mercury will put the .o files on the command-line after any libraries.
I understand the basic reason why the order is important, but what is baffling me is why did this break now? I just updated to Ubuntu 11.10 / GCC 4.6.1. I have been successfully compiling this program for years using precisely the above technique (putting -lstdc++ first). Only now has this error come up. An unrelated program of mine links against OpenGL using -lgl and that too broke when I upgraded and I had to move -lgl to the end of the command-line. I'm probably going to discover that dozens of my programs no longer compile. Why did this change? Is there something wrong with my new system or is that the way it is now? Note that these are ordinary shared libraries, not statically linked.
Is there anything I can do to make GCC go back to the old way, where the order of libraries doesn't matter? Is there any other way I can convince GCC to link libstdc++ properly without moving it after the .o files on the command-line?
If Mercury puts object files after libraries, Mercury is broken. Libraries belong after object files - always. You may sometimes get away with the reverse order, but not reliably. (Static libraries must go after the object files that reference symbols in the static library. Sometimes, a linker will note the symbols defined by a shared library even when none of the symbols are used; sometimes, the linker will only note the shared library symbols if the shared library provides at least one symbol.)

Is it possible to build gcc statically using buildroot?

I am using buildroot to build a fresh gcc cross-compiler on a dedicated machine.
It worked fine, but I now need to run this gcc from another machine, on which I have not the same libc version :-(. Of course gcc then crashed.
Is it possible to build gcc statically using buildroot ?
You could try passing -static to the linker (via LDFLAGS), but be aware that full static linking is not supported by glibc anymore (resp. it needs a glibc build which supports static linking).
This is due to the fact that nss libraries (name server switch) will be loaded dynamically (unless you compile your own glibc - but that defeats the purpose of nss). This might be enough for you however to reduce dependencies against system libraries.
But I could assume that a statically linked gcc is fairly huge - this might result in long startup times.
If your objective is only to make a relocatable toolchain, statically link with expat, gmp, mpfr and mpc should enough. You can simply apply https://patchwork.ozlabs.org/patch/359841/

How to statically compile an SDL game on Windows

I have been trying to produce a statically linked "single binary" version of my game for windows. I want to link with sdl, sdl_image and sdl_mixer which in turn pull in a few support libraries. Unfortunately I haven't found a way to get them all to compile and link using cygwin/mingw/gcc. As far as I can tell all existing public versions are only shared libraries / dlls.
Please note that I'm not talking about licencing here. The source will be open thus the GPL/LGPLness of sdl is not relevant.
When compiling your project, you need to make just a couple changes to your makefile.
Instead of sdl-config --libs, use sdl-config --static-libs
Surround the use of the above-mentioned sdl-config --static-libs with -Wl,-Bstatic and -Wl,-Bdynamic. This tells GCC to force static linking, but only for the libraries specified between them.
If your makefile currently looks like:
SDLLIBS=`sdl-config --libs`
Change it to:
SDLLIBS=-Wl,-Bstatic `sdl-config --static-libs` -Wl,-Bdynamic
These are actually the same things you should do on Unix-like systems, but it usually doesn't cause as many errors on Unix-likes if you use the simpler -static flag to GCC, like it does on Windows.
Via this SDL mailing list post it seems that the sdl development tools ship with a sdl-config script that you can use with the --static-libs flag to determine what linker flags you need to use.
Environment: VMWare Virtual Machine with Windows 7 x64 and Equipment we Dev c + + build 7.4.2.569, complilador g+ + (tdm-1) 4.6.1
Once, SDL2-2.0.3 API installed as configuration Dev c ++ is not very clear what I've done as tradition requires command line.
The first problem is that Windows 7 appears to have changed the methodology and they go to his ball. Inventory. Ref. https://stackoverflow.com/users/464581/cheers-and-hth-alf
After the first hurdle, SDL_platform.h is that bad, it's down another, I do not remember where I downloaded, but the next does not work in the indicated version.
We must put SDL2.h ls in the directory of the executable.
D:\prg_desa\zsdl2>g++ bar.cpp main.cpp -o pepe1 -ID:\SDL2-2.0.3\i686-w64-mingw32\include\SDL2 -LD:\SDL2-2.0.3\i686-w64-mingw32\lib -lmingw32 -lSDL2main -lSDL2 -mwindow
I've finally compiled and works SDL2 testing.
That's because the SDL libs are under the LGPL-license.
If you want to static link the libs (you can do that if your recompile them. It needs some hacking into the makefiles though) you have to place your game under some compatible open source license as well.
The SDL-libs come as shared libraries because most programs that use them are closed source. The binary distribution comes in a form that most people need.
On my system (Ubuntu) I have to use the following flags:
-Wl,Bstatic -lSDL_image `sdl-config --libs` -lpng12 -lz -ltiff -ljpeg -lasound -laudio -lesd -Wl,-Bdynamic `directfb-config --libs` -lpulse-simple -lcaca -laa -ldl
That links SDL, SDL_image, and many of their dependencies as static. libdl you never want static, so making a fully-static binary that uses SDL_image is a poor idea. pulse,caca,aa, and directfb can probably be made static. I haven't got far enough to figure them out yet.

Resources