Ubuntu如何优雅地切换gcc版本(编译“现代C++”程序)

0. “现代C++”

0.1. 最近在学习“现代C++”的内容,在编程的过程中难免会使用到一些C++的新特性,比如C++17中的内联变量:inline variablestd::byte等;然而在编译程序的过程中,发现Ubuntu16.04.6自带的编译器g++会失败,这主要是因为16.04自带的gcc, g++编译器的版本是5.4.0,编译器发布的时间为20160609,那自然肯定编译不了C++17中的东西了。
0.2. 为了能够使用新特性,我们需要升级编译器的版本,而有些古老的程序又需要旧版本来编译,所以这篇博文的重点就来了,也就是:如何优雅地切换gcc, g++编译器的版本,高版本可以当做整个Ubuntu系统默认的编译器,或者高版本为自己编译某些程序时特地指定。

我这里系统的情况:

Linux版本: Ubuntu16.04.6;
使用的C++新特性:C++17;
默认编译器:gcc, g++ (version: 5.4.0)
需要安装的编译器:gcc, g++ (version: 7.4.0)
编译工具: CMake (version: 3.5.1)
用到的IDE(一般指:编辑器+编译器):CLion 2018.1

"现代c++"我浅显的理解就是:C++从2011年(每3年一次,2011的新特性最多,目前使用的也最多,也最为人熟知)开始逐步增加的新特性,比如:C++11 C++14 C++17 C++20等在原先C++标准上延伸出来的新特性)

注:为了能够使用C++17的特性,需要gcc-7以上的版本

1. 系统自带的编译器gcc, g++

1.1. 查看编译器版本,可以发现自带的编译器版本为5.4.0;
(因为我将g++版本改了, 所以是7.4, 你们如果没有安装新的gcc, 两者应该都是5.4.0)在这里插入图片描述
1.2. 非常简单的示例demo如下:

// main.cpp
#include <iostream>
#include <cstddef>  // for std::byte
int main()
{
    std::byte b1{0x3F};
    puts("Hello World!");
    return 1;
}
# CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(c++17_test)
set(CMAKE_CXX_FLAGS "-std=c++17")
add_executable(c++17_test main.cpp)

1.3. 使用CMake工具进行编译如下:
在这里插入图片描述

1.3. 我们可以看到CMake会输出与编译器的一些信息:
– The C compiler identification is GNU 5.4.0
– The CXX compiler identification is GNU 7.4.0

– Check for working C compiler: /usr/bin/cc
– Check for working C compiler: /usr/bin/cc – works

– Check for working CXX compiler: /usr/bin/c++
– Check for working CXX compiler: /usr/bin/c++ – works

主要是使用GNU来找到合适的编译器,比如gcc, g++;
1.3.1. 这里我们主要来分析一下: CXX compiler: /usr/bin/c++
这里我们想,编译器使用的不是g++吗?为什么这里会是c++?
这里应该也是采取了动态库链接那样类似的机制,c++其实也是一个软链接。
1.3.2. 下面是链接情况:
/usr/bin/c++ -> /etc/alternatives/c++;
/etc/alternatives/c++ ->/usr/bin/g++;
/usr/bin/g++ ->g++-5 (这一步才真正地指到了对应版本g++ -5的可执行程序上,前面两个相当于是个bridge

2. 升级编译器版本

2.1. 如果按照默认的编译器去编译的话,会出现下面的error:
main.cpp:6:5: error: ‘byte’ is not a member of ‘std’ std::byte b1{0x3F};
此版本的g++不支持C++17新特性,所以出现了此类问题,下面就需要将编译器升级到g++ -7以前的版本;
2.2. 命令如下:

$ sudo add-apt-repository ppa:ubuntu-toolchain-r/test
$ sudo apt-get update
$ sudo apt-get install gcc-7
$ sudo apt-get install g++-7
  • 安装好新版本的编译器以后,会发现在/usr/bin/目录下出现了g++-7 gcc-7的软链接
    /usr/bin/gcc-7 -> /usr/bin/x86_64-linux-gnu-gcc-7
    /usr/bin/g++-7 -> /usr/bin/x86_64-linux-gnu-g++-7
  • 还可以发现g++ --version的版本依然是默认的5.4.0;这是因为并没有将前面几步讲的bridge进行软链接,所以现在系统的编译器依然是5.4.0;

2.2.1. 如果不进行软链接就不可以使用了吗?那当然不是,就拿CLion这个IDE来说吧,它支持使用者选择具体的编译器,这样我们直接就可以将IDE中的编译器直接指定为g++ -7了,然后在IDE中编译程序了。(File->Settings->Build, Execution, Deployment->Toolchains->C++ Compiler)
2.2.2. Clion中修改为新版本编译器如下(其实只需要修改g++编译器就行):
在这里插入图片描述程序可以正常输出“Hello World”:
在这里插入图片描述2.3. 安装好gcc-7, g++ -7以后,我们可以通过下面的指令将系统的编译器设置为对应的高版本(100对应的是优先级,当存在多个版本的gcc时,如果触发了gcc的自动模式(另外还有手动模式),系统就会根据这个优先级进行自动选择版本):

$ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 100
$ sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 100

指令会输出信息:
update-alternatives: 使用 /usr/bin/gcc-7 来在自动模式中提供 /usr/bin/gcc (gcc)
update-alternatives: 使用 /usr/bin/g++ -7 来在自动模式中提供 /usr/bin/g++ (g++)

注:可以通过$ update-alternatives --help命令明白各个参数的意义。

2.3.1. 这个时候如果去查看版本号,就会发现是新版本7.4.0
在这里插入图片描述
这个时候各个编译器的链接情况如下(又多添加了alternatives里面的g++ gcc的软链接(相当于一个bridge),最终会链接到新版本的g++ gcc):
/usr/bin/c++ -> /etc/alternatives/c++;
/etc/alternatives/c++ ->/usr/bin/g++;
/usr/bin/g++ -> /etc/alternatives/g++;
/etc/alternatives/g++ -> /usr/bin/g++-7;
/usr/bin/g++-7 -> /usr/bin/x86_64-linux-gnu-g++-7;
2.4. 编译程序
目前g++版本已经是7.4了,支持C++17新特性了,所以现在可以在1.3节的基础上,进行编译运行:
在这里插入图片描述

3. 多版本间的g++, gcc切换

现在g++, gcc版本已经是新版了,但是如果我们某些程序还是需要依赖低版本的gcc, g++版本编译怎么办?这种情况下就需要我们降级!
3.1. 以下使用g++来进行举例说明,gcc类似的操作;在2.3.1节中通过--config子命令时会输出信息:
链接组 g++ (提供 /usr/bin/g++)中只有一个候选项:/usr/bin/g++ -7 无需配置。
3.2. 下来我们要做的就是再次install一个软链接(关于低版本的g++ -5):

$ sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 120

由于经常使用旧版本,所以这里将优先级设高为“120”,可以发现此时会触发自动模式,g++会选择优先级高的g+±5作为编译器:
在这里插入图片描述
3.2.1. 如果install的时候,指定旧版本的g++优先级低,它就不会自动切换,因为它会选优先级高的编译器;
在这里插入图片描述
3.3. 此种情况下,如果我们想手动指定某个版本的g++,就需要下面的命令来进行切换:

$ sudo update-alternatives --config g++

在这里插入图片描述
所以我们可以通过该命令实现对g++版本的切换;(手动输入需要的序号即可)

注意:对于gcc其他的软链接gcc-ar, gcc-nm等并不会因为install这些建立软链接,因为install的时候压根没有涉及相关的文件;由于其他使用的并不是很多(一般使用编译器),所以没有考虑这些版本的问题。

3.4. 如果想删除某一个版本的g++,可以使用下面的命令:
例如不再需要g++ -7,则可以使用(且会自动切换为g+±5):

$ sudo update-alternatives --remove g++ /usr/bin/g++-7

在这里插入图片描述
3.5. 如果两个g++都删除了,对应的软链接也就失效了,再次install就可以再建立软链接。

4. 总结

4.1. 首先描述了为了编译C++17程序,需要安装g++ -7版本以上的g++;
4.2. 然后进行安装gcc -7, g++ -7;
4.2.1. 对于支持自选编译器的IDE,直接进行指定就更加方便了,不需要其他复杂的操作,只需要安装,指定即可。
4.3. 然后讲解了如何切换版本,以及编译器的调用过程(各种软链接);
4.4. 虽然升级个g++易如反掌,但是中间的一些处理操作还是值得我们学习。
在这里插入图片描述

5. 现代C++学起来

6. 软连接和硬连接

6.1. 软连接相当于Windows里面的快捷方式;而硬链接创建以后,可以保持对源文件的同步修改,源文件变,硬连接文件变;硬连接变,源文件变。(可以好好利用硬连接这个特性
6.2. 硬连接的inode号和源文件的inode号一样,也就是一个i节点号可以对应多个文件名;

在多用户的操作系统里,你写一个脚本,程序等,没有完成,保存后等下次有时间继续写,但是其他用户有可能将你未写完的东西当成垃圾清理掉,这时,你对你的程序,脚本等做一个硬链接,利用硬链接的同步更新,就可以防止别人误删你的源文件了。

i节点是文件和目录的唯一标识,每个文件和目录必有i节点,不然操作系统就无法识别该文件或系统。(也就解释了为什么硬连接和源文件会同步更新);;;;而Git在一方面做得更好

参考文献

[1]. 软连接和硬链接的区别
[2]. 也可以通过C++官方使用的在线编译器来编译现代C++, 可以指定gcc版本, 指定C++标准, 是一个不错的工具.
[3]. GCC与gcc,g++区别
[4]. Linux的gcc和g++的区别
[5]. Linux——gcc & g++的使用和区别

  • 6
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值