0. 前言
一直想尝试一下C++20新的特性--module,但是最新的GCC稳定版10.2好像还没有支持,查看官网得知,GCC11的dev/module分支会对此有较好的支持。那只能从源码编译GCC11了。此文就此做个记录。
编译环境:Ubuntu 2004,GCC10.2,x86_64.
1. 安装依赖
先安装一些编译GCC11需要使用的依赖,可能不全。
$ sudo apt install curl bzip2 build-essential flex bison zlib1g-dev
2. 下载源码
下载源码,我选择从国内的gitee镜像源下载,可以大幅加快下载速度。gitee源每天与官方源同步一次,基本可以保证和官方保持同步。
$ git clone --depth=1 https://gitee.com/mirrors/gcc.git -b devel/c++-modules
3. 进入源码目录,下载依赖。
下载完成后,进入源码目录,执行 download_prerequisites
自动下载解压GCC需要的依赖。创建一个 bulid
目录用来安装GCC。
$ cd gcc/
$ ./contrib/download_prerequisites
$ mkdir build
4. 配置
进行编译前的环境配置,我选择安装在刚才创建的build目录中,如果不设置的话,将会默认安装到系统目录。然后因为只用来写C和C++,所以只使能C和C++。
如果配置的过程中出现错误,可以根据错误提示安装相应的依赖或执行相应的动作。
$ ./configure --prefix=/home/ngx/workspace/gcc/build --enable-threads=posix --enable--long-long --with-system-zlib --enable-languages=c,c++
5. 编译
配置完成后,就可以直接执行 make
进行编译。在这里可以根据需要使用多线程编译,在我的笔记本电脑上,I7 6700HQ
开启16个线程编译,大概需要25分钟。
如果编译的过程出错,大概率还是依赖问题,直接安装相关的依赖就可以了。需要注意的是,有时可能需要重新执行上一步的配置才能应用下载的依赖。
$ make -j16
6. 安装
编译完成后执行 make install
安装在指定的目录。
$ sudo make install
7. 安装完成
执行进入安装目录下的GCC,可以看见输出信息如下所示:
gcc/build/bin$ ./gcc -v
Using built-in specs.
COLLECT_GCC=./gcc
COLLECT_LTO_WRAPPER=/home/ngx/workspace/gcc/build/libexec/gcc/x86_64-pc-linux-gnu/11.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ./configure --prefix=/home/ngx/workspace/gcc/build --enable-threads=posix --enable--long-long --with-system-zlib --enable-languages=c,c++ --disable-multilib
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 11.0.0 20210104 (experimental) [c++-modules revision 20210117-1750] (GCC)
但是因为我们没有安装到系统目录,想要方便使用,还需要将相关的目录添加到环境变量;包括二进制文件和GCC11的库文件。
$ echo 'PATH=/home/ngx/workspace/gcc/build/bin:$PATH' >> ~/.bashrc
$ source ~/.bashrc
$ sudo echo '/home/ngx/workspace/gcc/build/lib64' >> /etc/ld.so.conf
$ ldconfig
将新版本的GCC程序链接到 /usr/bin
下代替原来的。
$ sudo ln -s ~/workspace/gcc/build/bin/gcc /usr/bin/gcc
$ sudo ln -s ~/workspace/gcc/build/bin/g++ /usr/bin/g++
8. 例子
以下是一个很简单的例子。
// hello.cc
module;
#include <iostream>
export module helloworld;
export void hello() {
std::cout << "Hello world!\n";
}
// main.cc
import helloworld;
int main() {
hello();
}
编译的时候需要添加 -fmodules-ts
编译选项。
$ g++ hello.cc main.cc -fmodules-ts
$ ./a.out
Hello world!
9. 另一个例子
// sum.cpp
module;
export module Sum;
export template <typename... Args>
auto sum(Args... args){
return (0 + ... + args);
}
// math.cpp
module;
import Sum;
export module Math;
export template <typename T>
auto add(T a, T b){
return sum(a, b);
}
// main.cpp
#include <iostream>
import Math;
using namespace std;
int main(int argc, char const *argv[])
{
cout << add(1, 2) << endl;
return 0;
}
编译输出:
$ g++ -std=c++20 -fmodules-ts sum.cpp math.cpp main.cc
$ ./a.out
3
10. 参考链接
https://gcc.gnu.org/wiki/cxx-modules
https://gcc.gnu.org/projects/cxx-status.html#cxx20