素槿
Published on 2025-08-22 / 3 Visits
0

GCC11的C++-module示例

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