简体   繁体   中英

Cross-compile and link libstdc++ for i686-elf (using g++ on Ubuntu 16.04)

Believe me I've spent quite some time Googling without much of an outcome.

I'm writing a very basic OS as a fun project. It, for obvious reasons, needs to be compiled into a standalone form (i686-elf in my case). However I've decided that pure C isn't enough for me and that I'd love to use C++. So I've written a bit of code and it seemed to work, so I went on and all of sudden I kept getting the same error despite no obvious problem with the code.

./sh/../obj/class_string.o:(.eh_frame+0x4f): undefined reference to __gxx_personality_v0' ./sh/../obj/kernel.o:(.eh_frame+0x13): undefined reference to __gxx_personality_v0' /home/natiiix/crosscompiler/out/path/bin/../lib/gcc/i686-elf/6.1.0/libgcc.a(unwind-dw2.o): In function read_encoded_value_with_base': /home/natiiix/crosscompiler/out/src/build-gcc/i686-elf/libgcc/../../../gcc-6.1.0/libgcc/unwind-pe.h:257: undefined reference to abort'

After a bit of Googling I've figured out the problem must be that my g++ cross-compiler lacks c++ libs, which turned out to be true. It indeed contains just libgcc and libgcov. So I've figured out I'd get them somehow, but it turned out to be quite a difficult task to do. It's virtually impossible to find the already compiled libstdc++.a. So I had to compile it myself and as I'm not particularly familiar with makefile it definitely wasn't easy to figure out.

Finally I've found a bash script that somewhat allowed me to do what I needed. It downloads gcc 6.1.0, binutils, configures both and runs make, make install. That would be really nice if it actually worked. The compiler itself works like a charm as far as I can tell at least, but the library won't work no matter what I do since, at least I suspect, it is being built for a different target platform for some reason. It appears that libstdc++ simply cannot be built for i686-elf or something along the lines.

gccbuild.sh:

#!/bin/bash

set -e

if [ "$#" -ne 1 ]; then
  echo "Supply one parameter: the target to use!!"
  exit 1
fi

sudo apt install libgmp3-dev libmpfr-dev libisl-dev libcloog-isl-dev libmpc-dev texinfo -y

cd "$(dirname "$0")"

rm -rfv out/
mkdir out/
cd out/

rm -rfv path/
mkdir path/
rm -rfv src/
mkdir src/
cd src/

wget ftp://ftp.gnu.org/gnu/binutils/binutils-2.26.tar.gz
wget ftp://ftp.gnu.org/gnu/gcc/gcc-6.1.0/gcc-6.1.0.tar.gz

tar -xvzf binutils-2.26.tar.gz
tar -xvzf gcc-6.1.0.tar.gz

export PREFIX="$(pwd)/../path/"
export TARGET=$1
export PATH="$PREFIX/bin:$PATH"

rm -rfv build-binutils/
mkdir build-binutils/
cd build-binutils/
../binutils-2.26/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --disable-werror
make
make install

cd ..

rm -rfv build-gcc/
mkdir build-gcc/
cd build-gcc/

../gcc-6.1.0/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers

make all-gcc
make all-target-libgcc

make install-gcc
make install-target-libgcc

../gcc-6.1.0/libstdc++-v3/configure --host=$TARGET --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --disable-libstdcxx-threads

make
make install

My compile / link script (so that you can see the g++ arguments):

${BASH_SOURCE%/*}/../../crosscompiler/out/path/bin/i686-elf-g++ -c ${BASH_SOURCE%/*}/../src/*.cpp --std=c++11 -ffreestanding -O2 -Wall -Wextra
echo moving object files from active directory to obj/

mv *.o ${BASH_SOURCE%/*}/../obj/

${BASH_SOURCE%/*}/../../crosscompiler/out/path/bin/i686-elf-g++ -T ${BASH_SOURCE%/*}/../src/linker.ld -o ${BASH_SOURCE%/*}/../bin/kokos.bin -ffreestanding -O2 -nostdlib ${BASH_SOURCE%/*}/../obj/*.o -lgcc -lstdc++ -lsupc++

When I try to link those libraries (versions of libstdc++ and libsupc++ that appear to be elf32-i386, which is as close as they get to the i686-elf) I stop getting the undefined reference to __gxx_personality_v0 , but I still get a handful of undefined references to what appear to be C functions. (abort, strlen, malloc, free)

The whole problem can be avoided by not using templates, class destructors and some more c++ specific stuff (ironically classes alone seem to work just fine for the most part), but it doesn't seem like a very good solution to me. I'd rather have access to such things.

Could someone please explain to me what have I done wrong?

It is not clear from your post what exact result you want to get. Below there are few observations that may help you to figure out what your real problems are.

  1. First, if you need 32-bit code to be compiled on your (I guess) 64-bit Ubuntu host, you do not need a cross toolchain, just compile it with -m32 .
  2. If you want your code to be optimized for specific CPU variant, just use appropriate -march= , -mcpu= and -mtune= options.
  3. If you need your 32-bit program to be statically linked with C++ libraries, then on Ubuntu you just need to install a package libstdc++-6-dev:i386. Run sudo apt-get install libstdc++-6-dev:i386 , it will also install all necessary dependencies. Then just compile your program with gcc -m32 -static .
  4. If you need to use standard libraries optimized for specific CPU, rather than for generic i386 then you need to build them manually. This is true not only for libstdc++, but also for libc (IIRC, Ubuntu 16.04 still uses generic -march=i386 option to build libc, Ubuntu 16.10 uses -march=i686 ).
  5. You got the undefined references from your link output because you are using -nostdlib and -lstdc++ but not -lc . libstdc++ uses the functions from standard C library,so you need it.
  6. As you develop an OS kernel and you need a freestanding environment, I suppose that you really do not need standard libraries. In that case refer to C++ standard, clause 17.6.1.3, to find which standard headers you may use in your application. You have to use -lsupc++ -lgcc on your compiler command line and additionally you need -lgcc_eh if you use exception handling (and libgcc_eh.a is where __gxx_personality_v0 comes from). Do not use -lstdc++ in a freestanding environment!

Hope this helps a bit and have a good luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM