背景
因为有在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)之耐力。
不说了,好累!我要去休息一下!