背景
因為有在Linux環境編譯C++程式的需求,故我於近日在電腦上安裝了WSL。鑑於APT(Ubuntu的包管理器)提供的GCC版本較老(確切來說,APT會根據Ubuntu版本來下載並安裝某個版本的GCC,不一定為最新,例如對Ubuntu 22.04而言,從APT獲取的最新版本GCC為11.2.0),我便嘗試自己編譯一套GCC工具鏈。
在編譯之前,我發現GNU提供的GCC安裝教程內容組織較為混亂,新手容易踩坑(羊頭你這是生怕新手能順利編譯好GCC啊,你不會寫教程就別寫😠)。於是,在查閱了其他人編寫的GCC編譯教程後,我結合了我自己的(踩坑)經驗,編寫了這篇文章。
準備
- Linux環境(我用的是WSL Ubuntu 22.04,因為這是WSL目前所提供的最新版本的Ubuntu)
- 暢通無阻的網路環境
- 先前的GCC編譯器
- 一些其他的軟體包
步驟
開啟終端,先將本機上現有的軟體包更新至最新:
sudo apt update && sudo apt upgrade
若遇到網路問題,則需要更改映象源。本人推薦中科大映象源和清華映象源。具體修改方法參見映象源提供的幫助資訊,此處不再贅述。
更新完成後,根據此頁面,我們需要安裝編譯GCC所需的軟體包:
sudo apt install build-essential python3 gnat gdc gm2 gawk binutils gzip bzip2 make tar perl libgmp-dev libmpfr-dev libmpc-dev libisl-dev zstd gettext autoconf m4 automake gperf dejagnu expect tcl autogen guile-3.0 flex texinfo texlive sphinx-common git ssh diffutils patch libtool
隨後,我們將GCC原始碼clone至本地:
git clone git://gcc.gnu.org/git/gcc.git
讀者可以自己修改存放原始碼的資料夾名稱,只需在連結後面加上資料夾名稱即可,例如gcc_src
。這裡我就用預設的gcc
資料夾來指代GCC原始碼目錄了,以下同理。
若遇到網路問題,則同樣可以從映象源clone。只需把連結換成https://mirrors.tuna.tsinghua.edu.cn/git/gcc.git
即可(此處以清華映象源舉例)。
在進入GCC原始碼目錄之前,我們可以先建立一個名為gcc_build
的資料夾(即存放GCC臨時編譯檔案及GCC本體的資料夾),與GCC原始碼目錄同級:
mkdir gcc_build
此時執行ls
,終端輸出如下:
gcc gcc_build
隨後透過cd gcc
進入GCC原始碼目錄。
在配置GCC編譯配置前,我們需要切換tag至某個release版本,否則編譯產物將為當前最新的GCC開發版。當前最新的發行版GCC的版本號為14.1.0
,因此我們執行此命令:
git checkout releases/gcc-14.1.0
這樣就可以了。
- 可能讀者知道GCC原始碼裡已經包含了自動安裝依賴的指令碼,即
./contrib/download_prerequisites
。我們還需要執行它嗎?答案是不需要。我大致分析了指令碼內容,發現這個指令碼下載並安裝的是這五個軟體包:gmp
、mpfr
、mpc
、isl
及gettext
,相關原始碼可見此。而這些軟體包,我們已經在前面安裝過了,所以我們無需再安裝一遍它們。
接下來,我們進入到我們剛剛建立的新資料夾:
cd ..
cd gcc_build
根據此頁面,我們需要先配置好GCC編譯配置。這裡給出我的編譯配置,讀者可以按需修改:
../gcc/configure --prefix=/usr/local/gcc-14.1.0 --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --enable-languages=c,c++,go,jit,lto,rust --enable-host-shared --enable-shared --enable-static --enable-libatomic --enable-graphite --enable-fully-dynamic-string --enable-libstdcxx-filesystem-ts --enable-lto --enable-libgomp --enable-linker-build-id --enable-threads=posix --enable-nls --enable-bootstrap --enable-locale=gnu --enable-cxx-locale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time --enable-gnu-unique-object --enable-plugin --enable-default-pie --enable-cet --enable-checking=release --enable-link-serialization=2 --disable-multilib --with-build-config=bootstrap-lto --with-boot-ldflags=-static-libstdc++ --with-stage1-ldflags=-static-libstdc++ --with-libiconv --with-default-libstdcxx-abi=new --with-system-zlib --with-target-system-zlib=auto --with-tune=generic --without-included-gettext --without-cuda-driver
- 由於本人也有Rust相關需求,故
--enable-languages
一項新增了rust
。新增rust
時,讀者應確保本機已安裝Rust。若不安裝Rust就執行此命令,則此命令會報錯,提示“找不到Cargo”。安裝Rust的步驟見此。
接下來就可以愉快的make
了!(然後編譯失敗時就愉快不起來了XD)
編譯完成後,執行sudo make install
,編譯好的GCC便會安裝至/usr/local/gcc-14.1.0
。
接下來,我們可以選擇替換掉系統原來的GCC:
sudo update-alternatives --install /usr/bin/gcc gcc /usr/local/gcc-14.1.0/bin/gcc 60
sudo update-alternatives --install /usr/bin/g++ g++ /usr/local/gcc-14.1.0/bin/g++ 60
替換掉原來的GCC的好處是,你可以直接執行gcc
命令而無需新增目錄字首,使用起來會更方便。
我們再執行命令gcc -v
,就會得到如截圖所示的輸出:
這就表示我們的替換已經生效了!
總結
編譯GCC會鍛鍊耐力,原因有二:
-
GCC配置非常多,這便是在鍛鍊耐力與英語閱讀理解能力(當然逃課辦法是用CharGPT,不過它可能會給你錯誤答案)。
-
GCC編譯過程非常慢,短則半小時,長則好幾個小時,期間還有可能發生意外(我遇到的意外有“找不到
xxx.cc
”,以及因記憶體不足,從而編譯器程序被系統殺死等)導致編譯失敗,這便也是在鍛鍊耐力,即:有條不紊、鎮定自若地處理錯誤,然後從頭開始編譯/配置(痛苦面具.jpg)之耐力。
不說了,好累!我要去休息一下!