2

I need to cross compile C/C++ code for the Raspberry Pi (armV6). I followed the instructions on http://hertaville.com/2012/09/28/development-environment-raspberry-pi-cross-compiler/ and I got the building on my host machine (Ubuntu 14.04) working.

So my project builds on my host machine after some irritation with the needed libraries, I was happy enough. But when I transferred the program to my Raspberry Pi, I got the following error:

{ProjectName}: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version `GLIBCXX_3.4.18' not found (required by {ProjectName})
{ProjectName}: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version `GLIBCXX_3.4.19' not found (required by {ProjectName})

So I suspect the crosscompiler is using the libstd++.so of my host machine instead of the one that is part of the crosscompiler, but I have no idea how to fix it.

I'm using the gcc-linaro-arm-linux-gnueabihf-raspbian/arm-linux-gnueabihf-g++ crosscompiler.

The program that I try to get working is written by someone else directly on the pi, there it builds, compiles and runs perfectly.

My makefile looks like this:

CC=arm-linux-gnueabihf-g++
IFLAGS=-pthread -I./headers -lwiringPi -lortp -llinphone 
LIBB = -I/home/david/rpi/rootfs/usr/lib/arm-linux-gnueabihf/
CFLAGS=-Wall -std=c++0x
LDFLAGS=-Wall
SOURCES=$(wildcard src/*cpp)
OBJECTS=$(addprefix obj/,$(notdir $(SOURCES:.cpp=.o)))
EXECUTABLE=bin/wackytalky

all: $(SOURCES) LINK_EXEC

debug: CFLAGS += -g
debug: $(SOURCES) LINK_EXEC

LINK_EXEC: $(OBJECTS)
    $(CC) $(LDFLAGS) -o $(EXECUTABLE) $^ $(LIBB) $(IFLAGS)

obj/%.o: src/%.cpp
    $(CC) $(CFLAGS) -o $@ -c $< $(IFLAGS)

clean:
    rm $(EXECUTABLE) obj/*.o
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Cerebres
  • 343
  • 3
  • 16

2 Answers2

3

I had the same problem (exactly) as you yesterday. I don't have time to follow up on the Pi side yet, so I just modified modified my cross compile options (I use eclipse) and added -static-libstdc++ to the linker command. This statically links in the code on the Ubuntu side, so the problem with the .so on the Pi side never arises.

Obviously it makes for a much larger executable file.

frogatto
  • 28,539
  • 11
  • 83
  • 129
Greycon
  • 793
  • 6
  • 19
  • not that obvious: if you build just one very special app this way, the statically built exec does not have to be that much larger than the combined size of the dynamically linked exec plus its dedicated libs. The extra storage cost, if any, for that larger size might be worth it if this saves you the trouble of getting the libs right – Roland May 26 '20 at 21:55
0

You have to copy the libstdc++ and others to your respary pi. If you use an newer compiler which generate executables which needs a newer lib this lib must be present on the target. Static linking is not a useful option. Simply copy the new libs to the appropriate path on your target.

So I suspect the crosscompiler is using the libstd++.so of my host machine instead of the one that is part of the crosscompiler, but I have no idea how to fix it.

No, I don't believe this. If your compiler was configured correctly, it uses the correct libs. And if it tries to use you x86 libs, you don't get an message of wrong version because the dynamic linker can not work with x86 libs at all.

For the downvoters :-): You can have more then one version on the target, so it is no problem to do this, see ldconfig for details. Also you can have the lib in the local or any other path without a problem, for this you can use LD_LIBRARY_PATH. And yes, I have not written that you should remove older versions. Linux is not windows so a added library will not break the system. Linux have no problems like the dll hell of win...

Of your special request I build one program with two different compilers and get from ldd:

gcc 4.9:

linux-vdso.so.1 =>  (0x00007fff4b7fe000)
librt.so.1 => /lib64/librt.so.1 (0x00000030f2200000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000030f1200000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00000030f0e00000)
libstdc++.so.6 => /opt/linux-gnu_4.9-20140105/lib64/libstdc++.so.6 (0x00007fa4aadc4000)
libm.so.6 => /lib64/libm.so.6 (0x00000030f1600000)
libgcc_s.so.1 => /opt/linux-gnu_4.9-20140105/lib64/libgcc_s.so.1 (0x00007fa4aabad000)
libc.so.6 => /lib64/libc.so.6 (0x00000030f0a00000)

gcc 4.8.2:

linux-vdso.so.1 =>  (0x00007fff4b7fe000)
librt.so.1 => /lib64/librt.so.1 (0x00000030f2200000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000030f1200000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00000030f0e00000)
libstdc++.so.6 => /opt/linux-gnu_4.8.2/lib64/libstdc++.so.6 (0x00007fa4aadc4000)
libm.so.6 => /lib64/libm.so.6 (0x00000030f1600000)
libgcc_s.so.1 => /opt/linux-gnu_4.8.2/lib64/libgcc_s.so.1 (0x00007fa4aabad000)
libc.so.6 => /lib64/libc.so.6 (0x00000030f0a00000)

As you can see: Two versions of one library one one system and no problems at all.

Some more infos on different of libs on the os look here at:

How do applications resolve to different versions of shared libraries at run time?

If it will not work on your system, feel free to ask again.

Community
  • 1
  • 1
Klaus
  • 24,205
  • 7
  • 58
  • 113
  • 2
    No, you don't have to copy any libs to the raspberry. The toolchain must match the libs on the device. Some toolchains (namely the Windows cross toolchain for Rasbperry) allow to update their libs by copying them from the device to the build machine, but never the other way round. – jasal Jul 07 '14 at 09:02
  • 2
    If you did copy the libs from the cross compilation environment onto the target environment, then you would find the existing programs on the target might stop working! – harmic Jul 07 '14 at 10:29
  • 1
    I do not fully understand why I would need to put new libraries on the target machine if the crosscompiler sysroot has the same library as the target machine in it? Isn't the whole point of a crosscompiler just to avoid the endless transfer of libraries? – Cerebres Jul 07 '14 at 12:50
  • sysroot delivers not glibcxx! This lib comes from the libstdc++ which is part of gcc distribution. If you build a new compiler which supports a newer version of the library that library must be present on your target. This lib is simply not on your target system. This will not mean to replace libc or something which comes from the kernel and the kernel c interface. As you can see in my ldd output, these libs are located in /opt/... which comes from my personal configurations. The libs from the os are placed in /lib or /usr/lib ( maybe others...) – Klaus Jul 07 '14 at 12:53
  • So just copying the libstdc++.so.6.19 from host to target machine should solve the problem? I don't need to make some symbolic references? – Cerebres Jul 07 '14 at 12:59
  • You can place where you want. You have to add the path to it in the ld.so.config configuration and run ldconfig. The second solution is to place it somewhere and add the path manually to LD_LIBRARY_PATH. Please see man pages of ldd, ldconfig, ld.so. No need to add some symlinks somewhere. You should keep your optional libs separate from the os delivered ones! – Klaus Jul 07 '14 at 13:05
  • I added /opt/libstdc++/ to the ld.so.config file on the target machine, whereafter I ran ldconfig. /opt/libstdc++ contains these items:lrwxrwxrwx 1 root root 19 Jul 7 14:26 libstdc++.so.6 -> libstdc++.so.6.0.19 -rwxr-xr-x 1 root root 5337032 Jul 7 14:11 libstdc++.so.6.0.19 But the problem remains. I copied the libstdc++.6.0.19 from the debian toolchain folder of my host machine to the target machine. But there's also this one on my host machine: /usr/lib32/libstdc++.so.6.0.19 I doubt that transferring that one will help, but I'll try. – Cerebres Jul 07 '14 at 13:31
  • As suspected the other libraries won't work because the arm-architecture won't recognize them. However the one from the linaro raspbian folder do work, but the problem remains. I noticed however that the libstdc++.so.6 still points to the libstdc++.so.6.0.17 – Cerebres Jul 07 '14 at 13:38
  • Output of ldconfig -p|grep libstdc gives libstdc++.so.6 (libc6,hard-float) => /usr/lib/arm-linux-gnueabihf/libstdc++.so.6 libstdc++.so.6 (libc6,hard-float) => /opt/libstdc++/libstdc++.so.6 – Cerebres Jul 07 '14 at 13:46
  • Oh my, exporting LD_LIBRARY_PATH fixed the problem. How can I make this permanent? – Cerebres Jul 07 '14 at 13:57
  • You can simply add `export LD_LIBRARY_PATH=...` to your .bashrc or any other shell startup script. At first take a look which shell you start from. If you do not start your prog from a shell, maybe from cron or others take a look at `man env` typically installed in /usr/bin/env – Klaus Jul 08 '14 at 08:18
  • Just to inform everyone: I compiled a different program that doesn't need libstdc++.so.6.0.19 and it works like a charm. The linker now just links to the right library. Thanks a lot Klaus! – Cerebres Jul 09 '14 at 09:39
  • "Linux is not windows so a added library will not break the system" - sorry, but not always true. I've experienced, even if rarely, cases when installing a library broke something in something completely unrelated. It was, however, a "non-free" library, so not part of the official repository. – vsz Oct 22 '15 at 09:57