Ubuntu 16系统中GCC 9.2编译器安装方法及C++17标准测试示例
1 下载源文件
http://mirror.linux-ia64.org/gnu/gcc/releases/gcc-9.2.0/
2 编译安装
#解压
tar zxvf gcc-9.2.0.tar.gz
#创建编译目录
mkdir gcc-9.2.0-build
如图所示
3 下载依赖包
cd /home/gcc/gcc-9.2.0-build
../gcc-9.2.0/configure
会报错
configure: error: Building GCC requires GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+.
Try the --with-gmp, --with-mpfr and/or --with-mpc options to specify
their locations. Source code for these libraries can be found at
their respective hosting sites as well as at
ftp://gcc.gnu.org/pub/gcc/infrastructure/. See also
http://gcc.gnu.org/install/prerequisites.html for additional info. If
you obtained GMP, MPFR and/or MPC from a vendor distribution package,
make sure that you have installed both the libraries and the header
files. They may be located in separate packages.
解决办法
cd /home/gcc/gcc-9.2.0
vi contrib/download_prerequisites
将该文件里的
base_url='ftp://gcc.gnu.org/pub/gcc/infrastructure/'
替换为:
base_url='http://mirror.linux-ia64.org/gnu/gcc/infrastructure/',
即将不存在的服务器地址替换为镜像服务器地址。接下来,执行如下命令自动下载并解压依赖包:
bash contrib/download_prerequisites
有提示这个,证明成功
All prerequisites downloaded successfully.
cd /home/gcc/gcc-9.2.0-build
../gcc-9.2.0/configure --disable-multilib #选项disable-multilib 禁用32位
make
等了好久好久。。。。
make install
指定本机使用最新版本GCC编译器
使用update-alternatives
命令配置增加最新版本编译器,注意:gcc是编译C程序的默认程序,g++是编译C++程序的默认程序。
# update-alternatives --install <链接> <名称> <路径> <优先级>
sudo update-alternatives --install /usr/bin/gcc gcc /usr/local/bin/gcc 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/local/bin/g++ 50
使用下述命令查询当前已经安装的GCC编译器版本:
# 查询本机已有GCC编译器情况
sudo update-alternatives --query gcc
# 查询本机已有G++编译器情况
sudo update-alternatives --query g++
Name: gcc
Link: /usr/bin/gcc
Status: auto
Best: /usr/local/bin/gcc
Value: /usr/local/bin/gcc
Alternative: /usr/bin/gcc-5
Priority: 20
Alternative: /usr/local/bin/gcc
Priority: 50
Name: g++
Link: /usr/bin/g++
Status: auto
Best: /usr/local/bin/g++
Value: /usr/local/bin/g++
Alternative: /usr/bin/g++-5
Priority: 20
Alternative: /usr/local/bin/g++
Priority: 50
选择默认使用的GCC编译器版本:
# 交互配置GCC编译器
sudo update-alternatives --config gcc
# 交互配置G++编译器
sudo update-alternatives --config g++
可以使用如下命令查询当前的gcc
及g++
版本:
# 查询gcc版本
gcc --version
# 查询g++版本
g++ --version
C++ 17标准程序测试
#include <iostream>
#include <tuple>
#include <map>
#include <stdexcept>
bool divide_remainder(int dividend, int divisor, int &fraction, int &remainder)
{
if (divisor == 0)
{
return false;
}
fraction = dividend / divisor;
remainder = dividend % divisor;
return true;
}
std::pair<int, int> divide_remainder(int dividend, int divisor)
{
if (divisor == 0)
{
throw std::runtime_error{"Attempt to divide by 0"};
}
return {dividend / divisor, dividend % divisor};
}
int main()
{
{ // old school way
int fraction, remainder;
const bool success{divide_remainder(16, 3, fraction, remainder)};
if (success)
{
std::cout << "16 / 3 is " << fraction << " with a remainder of " << remainder << "\n";
}
}
{ // C++11 way
const auto result(divide_remainder(16, 3));
std::cout << "16 / 3 is " << result.first << " with a remainder of " << result.second << "\n";
}
{ // C++11, ignoring fraction part of result
int remainder;
std::tie(std::ignore, remainder) = divide_remainder(16, 5);
std::cout << "16 % 5 is " << remainder << "\n";
}
{ // C++17, use structured bindings
auto[fraction, remainder] = divide_remainder(16, 3);
std::cout << "16 / 3 is " << fraction << " with a remainder of " << remainder << "\n";
}
{ // C++17, decompose a tuple into individual vars
std::tuple<int, float, long> tup{1, 2.0, 3};
auto[a, b, c] = tup;
std::cout << a << ", " << b << ", " << c << "\n";
}
{ // C++17, use structured binding in for-loop
std::map<std::string, size_t> animal_population{
{"humans", 7000000000},
{"chickens", 17863376000},
{"camels", 24246291},
{"sheep", 1086881528}
/* … */
};
for (const auto & [ species, count ] : animal_population)
{
std::cout << "There are " << count << " " << species << " on this planet.\n";
}
}
}
g++ -g -Wall -std=c++17 *.cpp -o test
./test
16 / 3 is 5 with a remainder of 1
16 / 3 is 5 with a remainder of 1
16 % 5 is 1
16 / 3 is 5 with a remainder of 1
1, 2, 3
There are 24246291 camels on this planet.
There are 17863376000 chickens on this planet.
There are 7000000000 humans on this planet.
There are 1086881528 sheep on this planet.
使用G++9.2.0构建多线程程序,运行程序时出现类似“./main: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.22’ not found (required by ./main)”的错误
#include <iostream>
#include <queue>
#include <tuple>
#include <condition_variable>
#include <thread>
using namespace std;
using namespace chrono_literals;
queue<size_t> q;
mutex mut;
condition_variable cv;
bool finished = false;
void producer(size_t items) {
for (size_t i = 0; i < items; ++i) {
this_thread::sleep_for(100ms);
{
lock_guard<mutex> lk(mut);
q.push(i);
}
cv.notify_all();
}
{
lock_guard<mutex> lk(mut);
finished = true;
}
cv.notify_all();
}
void comsumer() {
while (!finished) {
unique_lock<mutex> lk(mut);
cv.wait(lk, []() {
return !q.empty() || finished;
});
while (!q.empty()) {
cout << "Got " << q.front() << " from queue. " << endl;
q.pop();
}
}
}
int main() {
thread t1(producer, 10);
thread t2(comsumer);
t1.join();
t2.join();
cout << "Finished! " << endl;
return 0;
}
g++ -g -Wall -std=c++17 -pthread *.cpp -o main
./main
./main: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.22' not found (required by ./main)
将/usr/lib/x86_64-linux-gnu/libstdc++.so.6
修改后缀名备份,并将/usr/local/lib64/libstdc++.so.6
复制到本地,命令如下:
cd /usr/lib/x86_64-linux-gnu
# 备份原有版本
sudo mv libstdc++.so.6 libstdc++.so.6.bk
# 复制新版本
sudo cp /usr/local/lib64/libstdc++.so.6 ./
# 更新共享库缓存
sudo ldconfig
然后,确认检查新的“libstdc++.so.6”文件已包含`GLIBCXX_3.4.22’版本(该步骤可不执行)。
strings ./libstdc++.so.6 | grep GLIBC
重新编译生成
g++ -g -Wall -std=c++17 -pthread *.cpp -o main
./main
Got 0 from queue.
Got 1 from queue.
Got 2 from queue.
Got 3 from queue.
Got 4 from queue.
Got 5 from queue.
Got 6 from queue.
Got 7 from queue.
Got 8 from queue.
Got 9 from queue.
Finished!
无法将GCC编译器版本降级
最新版本的GCC编译器虽然用起来很舒服,但一些旧代码可能还是需要老版本的GCC编译器才能编译,这时我们自然想到使用
sudo update-alternatives --config gcc
命令去配置版本,但经过实践发现,无论我怎么设置选项,gcc -v
命令总是输出如下信息:
使用内建 specs。
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-pc-linux-gnu/9.2.0/lto-wrapper
目标:x86_64-pc-linux-gnu
配置为:../gcc-9.2.0/configure --disable-multilib
线程模型:posix
gcc 版本 7.2.0 (GCC)
也就是说,无法将GCC版本降级。
该问题产生的原因是,我们将GCC7.3.0的优先级设置得太高了。由于GCC7.3.0的优先级高、版本也新,无论我们怎么手动选择GCC版本,系统仍然会匹配版本较新的GCC程序。
解决方法是:将老版本的GCC程序优先级设置得更高。具体操作如下:
# 1.删除原有低优先级的老GCC配置项
sudo update-alternatives --remove gcc /usr/bin/gcc-5
sudo update-alternatives --remove g++ /usr/bin/g++-5
# 2.以更高的优先级重新安装老GCC配置项
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 70
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 70
# 3.这时就可以更改当前使用的GCC版本了
sudo update-alternatives --config gcc
sudo update-alternatives --config g++