簡體   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