Ubuntu + CLion + GCC 搭建C++20开发环境
简介
最近因课题需求安装最新Ubuntu系统、CLion IDE 并配置 C++20 开发环境,踩坑主要在 gcc 与 g++ 的更新与配置上
详细过程记录在下文,可直接跳到“总结”去看四大步骤的主要注意事项和测试代码
Ubuntu20.04
参照Windows 下安装 Ubuntu 双系统(更新)安装新版本Ubuntu系统,如有其他疑问比如仅需要Ubuntu系统,参照双系统完美安装或单双系统都适用
下载镜像、U盘刻录工具、开机启动控制工具(双系统)
注意进入BIOS设置U盘启动,然后断网安装更迅速
CLion 2021.1
按照官网指引,直接申请学生免费并安装即可,参见其他博客
也可在终端直接
sudo snap install clion --classic
toolchain配置如下:
gcc 12.0.0
另外, gcc 镜像网站
据此链接可安装操作系统、编译功能包、开发文档、git、新版gcc
注意:如果是极简安装的ubuntu系统,那必须用apt-get update、apt-get upgrade先更新所有软件包,否则GCC的clone之后make无法成功
作者当时的最新版是11.0,我安装时得到12.0
注意:
- 其中clone gcc源码和make源码的过程耗时很长,可以考虑多线程
- 这种方式使两个版本GCC共存,9.3和11.0。11.0是首选项,支持大部分C++20特性
结果与上面链接作者对比如下:
初步结果(C++20特性使用失败了)
CLion在正确配置toolchain之后,编译包含C++20特性的程序会报错
程序包含了 ranges 头文件,然后使用 view,error——“找不到文件”,代码见下文,报错如下图所示:
尽管GCC版本已经以最新版(11.1或12.0)作为首选项,但在终端手动编译同样报错
原因——动态库并没有更新
参照 类似/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21’ not found 的问题 可解决动态库未能在GCC升级时替换老版本的动态库问题
与这篇文章不同的是,我的动态库空空如也,报错是 `GLIBCXX_3.4.29’ not found 。
因此动态库不能支持c++20新特性,所以IDE编译报错——未生成 .out 文件,所以终端手动编译报错——生成 .out 文件但无法执行
进一步结果(手动编译成功、IDE编译失败)
动态库问题解决后,手动编译成功,但IDE编译仍失败。
动态库问题解决前后,手动编译结果对比如下:
- 终端 gcc -v 与 g++ -v 都显示新版本(支持C++20)
- CLion配置toolchain正确(另外,工程创建之初,就选择 “-std=c++20” )
- 手动编译成功——说明g++配置可以完成期待的编译结果,但IDE报错
在此三点情况下
似乎g++版本仍为11?果然如此
原因—— g++ 版本配置在 CLion 视角仍为旧版本
在网上发现类似的 gcc、g++ 配置问题如下:
那么根据之前配置 gcc 版本切换的经验,自检 g++
$ sudo update-alternatives --config gcc
结果是啥也没有hhh,那么 g++ 显然停留在旧版本——9.3.0
于是照猫画虎配置 g++ 版本切换
$ sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/x86_64-linux-gnu-g++-9 90
$ sudo update-alternatives --install /usr/bin/g++ g++ /usr/local/bin/x86_64-pc-linux-gnu-g++ 100
结果如下:
结果—— IDE 仍有红色波浪线标识error,但已经可以正确编译、运行
总结
- Ubuntu 20.04 和 CLion 尽可以按照上文或大量类似博文去安装、配置
- 装了新版 gcc 后,必须同样更新动态库配置
- 必须把g++ 配置为与 gcc 同样的可切换状态
- 仍有问题没有完全明了、解决
暂且先用着吧,测试 C++11 与 C++20 特性的代码如下:
#include <iostream>
#include <vector>
#include <ranges>
int main() {
std::cout << "Hello, World!" << std::endl;
auto otherVariable = 5;
std::cout << otherVariable << std::endl;
std::vector<int> ints{0,1,2,3,4,5,6};
auto res1= std::views::reverse(ints);
for(int i:res1) std::cout << i << ' ';
std::cout<<std::endl;
ints.push_back(7);
for(int i:res1) std::cout << i << ' ';
std::cout<<std::endl;
return 0;
}