繁体   English   中英

交叉编译和链接i686-elf的libstdc ++(在Ubuntu 16.04上使用g ++)

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

相信我,我花了很多时间在Google搜寻上没有多大成果。

我正在编写一个非常基本的OS,作为一个有趣的项目。 由于明显的原因,它需要编译成独立形式(在我的情况下为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 ++。a。 所以我必须自己编译它,因为我对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++

当我尝试链接那些库(似乎是elf32-i386的libstdc ++和libsupc ++版本)时,我不再获得undefined reference to __gxx_personality_v0undefined reference to __gxx_personality_v0 ,但是我仍然得到了一些对似乎是C函数的未定义引用。 (中止,strlen,malloc,免费)

可以通过不使用模板,类析构函数和其他一些c ++特定的东西(讽刺地是,类本身在大多数情况下似乎都可以正常工作)来避免整个问题,但这对我来说似乎不是一个很好的解决方案。 我宁愿接触这些东西。

有人可以告诉我我做错了什么吗?

从您的帖子中还不清楚您要获得什么确切结果。 下面是一些观察结果,它们可以帮助您弄清楚真正的问题是什么。

  1. 首先,如果需要在我的64位Ubuntu主机上编译32位代码,则不需要跨工具链,只需使用-m32编译即可。
  2. 如果要针对特定​​的CPU变体优化代码,只需使用适当的-march= ,- -mcpu=-mtune=选项。
  3. 如果需要将32位程序与C ++库静态链接,则在Ubuntu上,只需安装软件包libstdc ++-6-dev:i386。 运行sudo apt-get install libstdc++-6-dev:i386 ,它还将安装所有必需的依赖项。 然后只需使用gcc -m32 -static编译程序。
  4. 如果您需要使用针对特定CPU 优化的标准库,而不是针对通用i386,则需要手动构建它们。 这不仅适用于libstdc ++,而且适用于libc(IIRC,Ubuntu 16.04仍使用通用-march=i386选项来构建libc,Ubuntu 16.10使用-march=i686 )。
  5. 您从链接输出中获得了未定义的引用,因为您使用的是-nostdlib-lstdc++而不是-lc libstdc++使用标准C库中的函数,因此您需要它。
  6. 当您开发OS内核并且需要一个独立的环境时,我想您确实不需要标准库。 在这种情况下,请参阅C ++标准的17.6.1.3节,以查找可以在应用程序中使用的标准标头。 您必须在编译器命令行上使用-lsupc++ -lgcc ,此外,如果您使用异常处理(并且libgcc_eh.a__gxx_personality_v0来源),则还需要-lgcc_eh 不要在独立的环境中使用-lstdc++

希望这会有所帮助,并祝您好运!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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