相信我,我花了很长时间用谷歌搜索没有太多结果。
我正在编写一个非常基本的操作系统作为一个有趣的项目。出于显而易见的原因,它需要编译成一个独立的形式(在我的案例中是i686-elf)。但是我已经确定纯C对我来说还不够,而且我喜欢使用C ++。所以我写了一些代码,它似乎工作,所以我继续,突然间我仍然得到相同的错误,尽管代码没有明显的问题。
./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'
经过一段谷歌搜索后,我发现问题必定是我的g ++交叉编译器缺少c ++库,结果证明是真的。它确实只包含libgcc和libgcov。所以我发现我会以某种方式得到它们,但事实证明这是一项相当困难的任务。找到已编译的libstdc ++几乎是不可能的。所以我必须自己编译它,因为我对makefile并不是特别熟悉,所以绝对不容易理解。
最后我发现了一个bash脚本,它允许我做我需要的东西。它下载gcc 6.1.0,binutils,配置并运行make,make install。如果真的有效,这将是非常好的。就我至少而言,编译器本身就像一个魅力,但是无论我做什么,库都无法工作,至少我怀疑,它是出于某种原因为不同的目标平台构建的。似乎libstdc ++根本无法为i686-elf或类似的东西构建。
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
我的编译/链接脚本(以便您可以看到g ++参数):
${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++
当我尝试链接这些库(libstdc ++和libsupc ++的版本似乎是elf32-i386,它们与i686-elf一样接近)时,我停止了undefined reference to __gxx_personality_v0
,但我仍然得到一些未定义的引用似乎是C函数。 (abort,strlen,malloc,free)
通过不使用模板,类析构函数和一些更具特定于c ++的东西可以避免整个问题(具有讽刺意味的类似乎在大多数情况下都可以正常工作),但它对我来说似乎不是一个很好的解决方案。我宁愿接触这些东西。
有人可以向我解释我做错了什么吗?
答案 0 :(得分:0)
从您的帖子中不清楚您想要获得什么样的确切结果。以下几点可以帮助您找出真正的问题。
-m32
进行编译即可。-march=
,-mcpu=
和-mtune=
选项。sudo apt-get install libstdc++-6-dev:i386
,它还将安装所有必需的依赖项。然后使用gcc -m32 -static
。-march=i386
选项来构建libc,Ubuntu 16.10使用-march=i686
)。-nostdlib
和-lstdc++
,而不是-lc
。 libstdc++
使用标准C库中的函数,因此您需要它。-lsupc++ -lgcc
,如果使用异常处理,则需要-lgcc_eh
(而libgcc_eh.a
来自__gxx_personality_v0
)。不要在独立环境中使用-lstdc++
!希望这会有所帮助并祝你好运!