自己动手编译 GCC!

因为我们学校里的在线评测系统没有办法屏蔽 #pragma GCC optimize 预处理指令,因此出现了如下的状况:

因此,今天我决定从根源上禁止这些行为。

正好前两天看到洛谷上屏蔽手动 O2 O3 Ofast 的方式,于是今天自己就来试着修改 GCC 的源代码,并计划手动编译并上线测试。

需求整理

  1. 魔改编译器禁止手动优化;
  2. 编译器版本之间可以分离,不予系统自带的编译器冲突;
  3. GCC 9 + GCC 12

准备工作

如果你也是某个 OJ 的运维/管理,直接在服务器上构建源代码会更好,但是注意资源占用。

如果你只是自用,那么无所谓。

但是前提是一定要在一个 Linux 环境下操作。(我也只写了 Linux (Ubuntu) 的记录啥的)

正式安装

安装需要的库

文档是按照最新的正式版 GCC 12 写的,向下兼容。

根据 Prerequisites for GCC 所说,总结下来,最省心的情况(我的情况)需要如下条件:

  • 通常是系统自带的
    • Ubuntu >= 20.04 (当然可以不是这个发行版,但 CentOS 算了)
    • 一个 POSIX Shell,但不包括 zsh
    • GCC >= 9.4
    • Python 3
    • ssh, git 等
  • 需要手动构建安装的

安装依赖库的过程相对简单。步骤总价下来无外乎以下几点:
1. 下载依赖库源码包
2. 上传源码包到服务器
3. 解压源码包
4. cd 到源码包解压到的目录
5. 执行:./configure && make && sudo make install

一定要从上往下依次安装。

配置

现在假定你的源代码存放在 src 目录下。在 src 的上级菜单新建文件夹 obj

/path/to/your/project
    |--- src
        |--- configure
        `--- [Another Files]
    `--- obj

obj 目录下执行 configure 指令。

比方说,我的指令是:

../src/configure --with-pkgversion="gcc-12.2.0_Imken_Customized (Build On JudgeMachine)" --host=x86_64-pc-linux-gnu --disable-multilib

(32 位机器大概不适用)

--with-pkgversiong++ --version 时显示的版本号(下面括号里的内容),具体如下:

$ g++ --version
g++ (gcc-12.2.0_Imken_Customized (Build On JudgeMachine)) 12.2.0
Copyright (C) ...

--host=x86_64-pc-linux-gnu 是说目标平台的架构。

更多配置项目参见 Installing GCC: Configuration

构建

本过程大约需要 0.6 ~ 4 小时。期间服务器的资源会爆满。建议使用 screen 在后台运行。

构建很简单,在 obj 文件夹下执行 make 即可。或者说,机子够强,可以并行构建,执行 make -j <线程数> 即可。

然后就是艰难的等待。我个人建议在机子终端面前守着,防止意外错误。

我遇到了一个错误,libgsl.so.23 没找到。这个 issue 解决得还不错,就是修改 ld 寻找 so 文件的目录。

LD_LIBRARY_PATH=/usr/local/lib/
export LD_LIBRARY_PATH

若构建中断,可以从断点重新开始构建。make 还是比较智能的。

安装

要是不出意外的话,构建将会在很长一段时间之后结束。此时可以执行 make install

但!是!我要版本隔离!

make DESTDIR=<目标目录> install 可以让 GCC 安装在指定目录。比如:

make DESTDIR=/opt/imken_oi/gcc/1220 install  # GCC 12.2.0
make DESTDIR=/opt/imken_oi/gcc/940 install   # GCC 9.4.0

目录不存在的话会自动新建。

安装好的 GCCbin<DESTDIR>/usr/local/bin/

总结

等死我了。最后 make install 的可执行文件对于每一台机子都不一样,不可直接复制构建出来的文件。烦死了。白编译三个小时。

更新信息

Update at 2023/5/10: Fix typo