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

您所在的位置:网站首页 linux如何升级gcc运行版本 Ubuntu如何优雅地切换gcc版本(编译“现代C++”程序)

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

2024-07-13 11:53| 来源: 网络整理| 查看: 265

0. “现代C++”

0.1. 最近在学习“现代C++”的内容,在编程的过程中难免会使用到一些C++的新特性,比如C++17中的内联变量:inline variable、std::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 #include // 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++的使用和区别



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3