Featured image of post GCC-13.2.0 编译安装

GCC-13.2.0 编译安装

GCC-13 是一个重大更新,在这个版本,GCC 的静态分析器继续改进,有更多的 C23 和 C++23 功能,并支持许多新的 x86_64/RISC-V/AArch64 处理器。为了普及使用 C++ 新标准而不是一直写 C++17 甚至 C++11,我决定编译安装 GCC-13.2.0,体验一下新的 C++ 标准。

# GCC-13.2.0 编译安装

GCC 13.1 已被发布为 GCC 13 的第一个稳定版本,作为 GNU 编译器集合的年度功能发布。

GCC 13.1 是一个重大更新,为那些对一些老式编程感兴趣的人添加了 Modula-2 语言前端,虽然有新的 GCC Rust gccrs 代码,但它在 v13.1 中被禁用。在这个版本,GCC 的静态分析器继续改进,有更多的 C23 和 C++23 功能,并支持许多新的 x86_64/RISC-V/AArch64 处理器。

GCC 13.1 还提供了对 Ryzen 7000 系列和 EPYC 9004 系列处理器的初始 AMD Zen 4(Znver4)支持,OpenMP 卸载改进,支持以 JSON 为基础的 SARIF 格式发出诊断程序,Ada 2022 附加功能,各种新的 C/C++警告,支持 AMD 本能 MI200 系列用于 AMDGCN 后端,Ampere-1A 支持,Neoverse-V2/Cortex-X3/Cortex-X1C/Cortex-A715 支持,以及许多新的 Intel CPU 支持。GCC 13 增加了针对 Raptor Lake, Meteor Lake, Sierra Forest, Grand Ridge, Emerald Rapids 以及 Granite Rapids 的英特尔 CPU Target,以及相关的新英特尔 CPU 指令集扩展,如 AMX-FP16、AVX-IFMA、AVX-VNNI-INT8、AVX-NE-CONVERT、RAO-INT 和 AMX-Complex。

为了体验 C++20 的新功能,GCC 13.1 也是一个很好的选择,因为它包括对 C++20 的许多新功能的支持。截止到本文撰写时,GCC-13.2 也已发布,所以我直接选择了最新的版本。

# 下载 GCC-13.2.0 源码

wget https://mirror.koddos.net/gcc/releases/gcc-13.2.0/gcc-13.2.0.tar.gz
tar -xzvf gcc-13.2.0.tar.gz
cd gcc-13.2.0

# 开始编译

  • 编译命令:
./contrib/download_prerequisites
mkdir build && cd build

../configure --prefix=/root/software/gcc-13.2.0 \
--with-pkgversion='glibc gcc V13.2.0' \
--enable-checking=release \
--enable-languages=c,c++ \
--disable-multilib \
--enable-bootstrap \
--enable-threads=posix \
--with-system-zlib \
--with-gmp=$GMP_HOME \
--with-mpfr=$MPFR_HOME \
--with-mpc=$MPC_HOME \

make -j$(nproc)
make install

# 设置环境变量

# gcc-13.0.2.env
export GCC13_HOME=/root/software/gcc-13.2.0
export PATH=$GCC13_HOME/bin:$PATH
export LD_LIBRARY_PATH=$GCC13_HOME/lib64:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$GCC13_HOME/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$GCC13_HOME/libexec:$LD_LIBRARY_PATH
export CPATH=$GCC13_HOME/include:$CPATH
export INCLUDE=$GCC13_HOME/include:$CPATH
export CC=$GCC13_HOME/bin/gcc
export CXX=$GCC13_HOME/bin/g++
export FC=$GCC13_HOME/bin/gfortran
export F77=$GCC13_HOME/bin/gfortran
export F90=$GCC13_HOME/bin/gfortran
export F95=$GCC13_HOME/bin/gfortran

# 命令行测试

$ gcc -v

输出结果为:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/root/software/gcc-13.2.0/libexec/gcc/x86_64-pc-linux-gnu/13.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../configure --prefix=/root/software/gcc-13.2.0 --with-pkgversion='glibc gcc V13.2.0' --enable-checking=release --enable-languages=c,c++,fortran --enable-threads=posix --enable-bootstrap --disable-multilib --with-system-zlib --with-gmp=/root/software/gmp/6.2.1 --with-mpfr=/root/software/mpfr/4.1.0 --with-mpc=/root/software/mpc/1.2.1
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 13.2.0 (glibc gcc V13.2.0)

即为编译安装成功。

# C++ 20 主要新特性

  • C++ 20 的主要新特性如下:
    • Concepts(概念):概念是对模板参数的类型约束,它们使得模板代码更加清晰和易于理解。概念允许开发者定义一个接口,模板参数必须满足这个接口才能被接受。
    • Ranges(范围库):这是对标准模板库(STL)的一个重大扩展,它引入了“范围”概念,以支持更加声明式的数据处理方式。
    • Spaceship Operator(三路比较运算符):<=>被称为三路比较运算符,它可以一次性比较两个值,返回它们的相对顺序(小于、等于、大于)。
    • Modules (模块):模块旨在替代传统的头文件和源文件分离方式,提供一种新的编译单元,可以显著改善编译时间和代码组织。
    • Coroutines (协程):协程是一种轻量级的线程,它可以在不同的执行点之间切换,而不是在函数调用之间切换。协程是一种用于编写异步代码的新方法,它允许函数在不同的时间点暂停和恢复执行,而不需要回调函数或复杂的状态机。
    • constexpr 改进:C++20 大大扩展了可以在编译时计算的代码的范围,包括允许 virtual 函数、trycatch 块在 constexpr 函数中使用。
    • 初始化器列表的 std::to_array :这允许将初始化器列表转换为 std::array ,从而提供了一种类型安全的方式来处理固定大小的数组。
    • 模板语法的简化:typename 和 class 在模板参数中可以互换使用,简化了模板的语法。
    • 新的标准属性:引入了多个新的属性,如 [[likely]][[unlikely]] ,用于向编译器提供分支预测的提示。
    • 新的标准库组件:例如 std::span ,它提供了一个视图,可以表示数组或其他连续序列的一部分,而不需要复制数据。
    • 新的同步库:例如 std::latchstd::barrier ,为多线程编程提供了新的同步原语。
    • std::format:这是一个新的格式化库,它提供了一种类型安全的方式来格式化字符串。
    • 其它等等

# C++ 23 主要新特性

  • C++ 23 的主要新特性如下:
    • Lambada
      1. 修复省略参数括号 () 的问题。
      2. 更改 lambda 尾部返回类型的作用域。
      3. 让支持函数的 attributes 都支持 lambda。这个功能其实很多编译器早已支持。
    • 编译期计算:主要修复一些 bug 和继续完善编译期计算的能力。
    • Deducing this : Deducing this 是 C++23 中最重要的特性之一。它其实就是提供一种将非静态成员函数的“隐式对象参数”变为“显式对象参数”的方法。
      • Deducing this 的主要动机是消除成员函数修饰所带来的冗余。
    • 多维数组:
      1. 支持多维下标运算符,即 operator[a, b, c, …]。
      2. 标准库引入 std::mdspan。
    • 标准库:
      • 增强 std::string 和 std::string_view
      • 增强 std::optional
      • std::flat_map 和 std::flat_set, 替代 std::map 和 std::set。
      • std::stacktrace:用于 exception 捕获后,展开调用栈,方便调试。将 stacktrace 引入标准库,可以看作是对 C++ 异常处理能力的加强。
      • std::excepted:对 C++ 通过返回值进行错误处理的能力加强。和 std::optional 差不多,但是 std::optional 只能表示正常值和空值(std::nullopt)。而 std::expected 则可以表示一个期望的值和一个错误的值,相当于两个成员的 std::variant,但是 std::excepted 的接口使用起来更方便。
      • std::unreachable():给编译器的优化提示,告诉编译器这个地方是不可到达的。如果 std::unreachable() 被调用,其结果是 undefined behavior。
    • 其它:
      • 静态 operator() 和 静态 operator[]
      • 假定表达式 [[assume(expr)]]
      • size_t 字面量

# Corutines 协程示例

#include <coroutine>
#include <iostream>
#include <optional>

template<typename T>
struct Generator {
    struct promise_type;
    using handle_type = std::coroutine_handle<promise_type>;

    struct promise_type {
        std::optional<T> current_value;
        static auto get_return_object_on_allocation_failure() { return Generator{nullptr}; }
        auto get_return_object() { return Generator{handle_type::from_promise(*this)}; }
        auto initial_suspend() { return std::suspend_always{}; }
        auto final_suspend() noexcept { return std::suspend_always{}; }
        void unhandled_exception() { std::exit(1); }
        template<typename U>
        auto yield_value(U&& value) {
            current_value = std::forward<U>(value);
            return std::suspend_always{};
        }
        void return_void() {}
    };

    handle_type coro;

    Generator(handle_type h): coro(h) {}
    Generator(Generator const&) = delete;
    Generator(Generator&& o) : coro(o.coro) { o.coro = nullptr; }
    ~Generator() { if (coro) coro.destroy(); }

    T next() {
        if (coro) {
            coro.resume();
            if (coro.done()) {
                coro.promise().current_value.reset();
            }
            return *coro.promise().current_value;
        }
        return T{};
    }
};

Generator<int> generateNumbers(int start, int end) {
    for (int i = start; i <= end; ++i) {
        co_yield i;
    }
}

int main() {
    auto numbers = generateNumbers(1, 5);
    for (int i = 1; i <= 5; ++i) {
        std::cout << numbers.next() << std::endl;
    }
    return 0;
}

编译命令:

g++ -o coroutines coroutines.cpp -std=c++20 -fcoroutines -O3

运行结果:

./coroutines
1
2
3
4
5

# Deducing this 示例

#include <iostream>

struct Test {
    template <typename Self>
    void explicitCall(this Self&& self, const std::string& text) {
        std::cout << text << ": ";
        std::forward<Self>(self).implicitCall();
        std::cout << '\n';
    }

    void implicitCall() & {
        std::cout << "non const lvalue";
    }

    void implicitCall() const& {
        std::cout << "const lvalue";
    }

    void implicitCall() && {
        std::cout << "non const rvalue";
    }

    void implicitCall() const&& {
        std::cout << "const rvalue";
    }
};

int main() {
    std::cout << '\n';

    Test test;
    const Test constTest;

    test.explicitCall("test");
    constTest.explicitCall("constTest");
    std::move(test).explicitCall("std::move(test)");
    std::move(constTest).explicitCall("std::move(consTest)");

    std::cout << '\n';
}

Licensed under CC BY-NC-SA 4.0
本博客已稳定运行
总访客数: Loading
总访问量: Loading
发表了 73 篇文章 · 总计 323.75k

使用 Hugo 构建
主题 StackJimmy 设计
基于 v3.27.0 分支版本修改