2023年11月29日发(作者:)
Ubuntu16.04系统中GCC9.1编译器安装⽅法及C++17标准测试⽰例
严正声明:本⽂系作者davidhopper原创,未经许可,不得转载。
2019年8⽉2⽇更新:
本⽂⽅法适⽤于GCC 9.1.0,只需将原⽂中的GCC 7.3.0替换为GCC 9.1.0即可。
为什么要更新到GCC 9.1.0?因为该版本可⽀持C++ 17标准的并⾏策略。
如何使⽤C++17标准的并⾏策略,参考我的另⼀篇博客:《》。
2017年底,C++17标准正式颁布,该标准的最⼤贡献是,提供了STL库算法的并⾏运算版本,对于我这种喜欢追求算法性能的程序员⽽
⾔,⽆疑是⼀个极⼤的福⾳。幸运地是,Linux系统标准编译器GCC能完美地⽀持C++ 17标准,但需升级到7.0以上版本;不幸地
是,Ubuntu 16.04版本⾃带的GCC版本为5.4.0,可⽀持C++ 14标准,但基本不⽀持C++ 17标准。怎么办?那就从零开始,从GCC官
⽅⽹站下载、安装最新标准的编译器吧。
⼀、下载GCC 7.3.0版本源代码
⼆、编译安装GCC 7.3.0
2.1 解压源代码压缩包
此时,我以为只要进⼊构建⽂件夹,然后执⾏如下配置命令就可以⽣成Makefile了,真是“too simple, sometimes naive”,世界哪有这
么美好?
cd ~/code/gcc/gcc-7.3.0-build
../gcc-7.3.0/configure
果不其然,上述命令产⽣的错误信息如下,原来是缺少⼏个依赖包:GMP 4.2+, MPFR 2.4.0+, MPC 0.8.0+,需要我们⾃⼰下载。
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:///pub/gcc/infrastructure/. See also
bash contrib/download_prerequisites
如果提⽰如下信息,则代表下载并解压成功:
2018-03-24 21:01:37 URL:/gnu/gcc/infrastructure/2 [2383840/2383840] -> "./2" [1]
2018-03-24 21:01:46 URL:/gnu/gcc/infrastructure/2 [1279284/1279284] -> "./2" [1]
2018-03-24 21:01:51 URL:/gnu/gcc/infrastructure/ [669925/669925] -> "./" [1]
2018-03-24 21:01:58 URL:/gnu/gcc/infrastructure/2 [1626446/1626446] -> "./2" [1]
2: 确定
2: 确定
: 确定
2: 确定
All prerequisites downloaded successfully.
如果出现如下信息,则表⽰包:2没有下载成功:
2018-03-24 20:54:39 URL:/infrastructure/ [669925/669925] -> "./" [1]
2018-03-24 20:56:16 URL:/infrastructure/2 [1626446/1626446] -> "./2" [1]
2: 失败
sha512sum: 警告:1 个校验和不匹配
error: Cannot verify integrity of possibly corrupted file 2
这是因为⽹络连接不正常造成的,解决⽅案是,进⼊⽬录“/home/davidhopper/code/gcc/gcc-7.3.0”,⼿动将已下载的“mpc-
”、“2”⽂件删除,重新执⾏命令下载。如果仍然提⽰失败,则应使⽤vi
bash contrib/download_prerequisites
也就是说,推断本机没有32位开发库,如果的确有就加上选项,否则就使⽤选项只构建64位版
configure--enable-multilib--disable-multilib
本。现在的机器谁还⽤32位系统,于是我⽴即重新运⾏配置程序如下:
../gcc-7.3.0/configure --disable-multilib
结果令⼈欣慰,总算在构建⽬录“/home/davidhopper/code/gcc/gcc-7.3.0-build”中⽣成了Makefile。
2.5 运⾏命令编译构建GCC编译器
make
接下来的事情似乎很简单,只要运⾏命令(需指出的是, Make程序⽀持并发处理,你的处理器有⼏个核,就可以加上选项,以
make-j x
便加快编译速度)就可以编译构建GCC编译器了,事实证明,我⼜把问题估计简单了⼀些。
cd ~/code/gcc/gcc-7.3.0-build
make -j 8
编译了不⼀会,就出现如下错误:
checking LIBRARY_ contains current directory
configure: error:
*** LIBRARY_PATH shouldn't contain the current directory when
*** building gcc. Please change the environment variable
*** and run configure again.
于是⽴即在⽹上搜索解决⽅案,找到如下类似的:
出现这个错误的原因是由于环境变量的LD_LIBRARY_PATH中出现了当前⽬录。
找了好久不知道是啥原因,因为不可能把这⽬录放在环境变量啊。后来发现,
通常我们写环境变量都喜欢写:
export LD_LIBRARY_PATH = $LD_LIBRARY_PATH:foo/bar
如果⼀开始LD_LIBRARY_PATH不存在的话,这个上⾯这串环境变量开头就是冒号,
这就把当前⽂件夹包含进去了。⼀般来说我们挺需要这种效果,因为在编译的时候
可以include某些东西,但是对于编译glibc来说这个是多余的。
最简单的解决⽅法就是unset LD_LIBRARY_PATH,这能把这个环境变量直接⼲掉。
好吧,开始照⽅抓药,重新执⾏如下命令:
unset LIBRARY_PATH
../gcc-7.3.0/configure --disable-multilib
make -j 8
在我机器上⼤约等了⼀个⼩时,最后全部构建成功。
cd ~/code/gcc/gcc-7.3.0-build
sudo make install
因为我在运⾏命令时,没有指定安装⽬录,因此上述命令会将最新版本的GCC编译器安装到默认位置:,也就是说,头
configure/usr/local
⽂件在⽬录,可执⾏⽂件在⽬录,库⽂件在⽬录。
/usr/local/include/usr/local/bin/usr/local/lib
2.7 指定本机使⽤最新版本GCC编译器
使⽤命令配置增加最新版本编译器,注意:gcc是编译C程序的默认程序,g++是编译C++程序的默认程序。
update-alternatives
# 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++
有 2 个候选项可⽤于替换 gcc (提供 /usr/bin/gcc)。
选择 路径 优先级 状态
------------------------------------------------------------
* 0 /usr/local/bin/gcc 50 ⾃动模式
1 /usr/bin/gcc-5 20 ⼿动模式
2 /usr/local/bin/gcc 50 ⼿动模式
要维持当前值[*]请按<回车键>,或者键⼊选择的编号:
有 2 个候选项可⽤于替换 g++ (提供 /usr/bin/g++)。
选择 路径 优先级 状态
------------------------------------------------------------
* 0 /usr/local/bin/g++ 50 ⾃动模式
1 /usr/bin/g++-5 20 ⼿动模式
2 /usr/local/bin/g++ 50 ⼿动模式
要维持当前值[*]请按<回车键>,或者键⼊选择的编号:
可以使⽤如下命令查询当前的及版本:
gccg++
# gcc
查询版本
gcc --version
# g++
查询版本
g++ --version
三、C++ 17标准程序测试
写⼀个C++ 17标准中关于结构化绑定(structured bindings)的⼩程序,代码如下:
#include
#include
#include
#include
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", },
{"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 chickens on this planet.
There are 7000000000 humans on this planet.
There are 1086881528 sheep on this planet.
四、可能遇到的问题
4.1 使⽤G++7.3.0构建多线程程序,运⾏程序时出现类似“./main: /usr/lib/x86_64-linux-gnu/libstdc++.so.6:
version `GLIBCXX_3.4.22’ not found (required by ./main)”的错误
写⼀个使⽤C++ 17标准实现多线程的⼩程序,代码如下:
#include
#include
#include
#include
#include
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)
这是因为没有使⽤“libstdc++.so.6”版本不够新造成的,解决⽅法如下:
⾸先,在GCC 7.3.0的安装⽬录(如果未更改,默认安装路径为:/usr/local)中查找“libstdc++.so.6”,命令如下:
find /usr/local -name "libstdc++.so.6"
结果如下:
/usr/local/lib64/libstdc++.so.6
接着,将修改后缀名备份,并将复制到本地,命令如下:
/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++.
#
复制新版本
sudo cp /usr/local/lib64/libstdc++.so.6 ./
#
最后,进⼊测试程序所在⽬录,重新运⾏⽣成的程序:
cd ~/code/C++17/SimpleProducerConsumerThread/
./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!
# 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

发布评论