前几天使用c++11以上的新语法编译程序,发现在ubuntu服务器编译都有异常提示,分析是ubuntu自带的编译工具及库太老的,不支持新的语法。针对找个问题,这两天将服务器的gcc/g++工具链升级到了11版本(之前是5.4),同时更新了glibc库到3.4.29.完成这些工作后,后续的编译可以直接使用最新的语法,对后续升级ubuntu的工具链和库有较大意义。
以下是完成步骤,阅读过程中,有几点需要注意:
1:本文手动升级,如果能用简单方法(添加ppa软件源),会更加快捷,但手动升级对完成升级流程及可能问题有更深入理解。
2:升级过程的顺序比较重要,随意修改会带来较大调试量,得不偿失
3:现在软件包都需要configure,之后生成makefile,之后make,configure的参数需要理解。
4:更新glibc的方法。
1:问题描述
前几天测试一个对比目录生成日期的代码,代码如下:
- #include <vector>
- #include <string>
- #include <string.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <dirent.h>
- #include <sys/stat.h>
- #include <time.h>
- using std::vector;
- using std::string;
- int main(int argc, char *argv[])
- {
- struct stat dirstat;
- int result;
- DIR *d;
- struct dirent *de;
- vector<string>dirVec;
- struct timespec tstmtime;
- if (argc < 2)
- {
- printf("param-num:%d \r\n", argc);
- return -1;
- }
- d = opendir(argv[1]);
- if (d == NULL)
- {
- printf("opendir: %s failed ! \r\n", argv[1]);
- return -1;
- }
- while((de = readdir(d)) != NULL)
- {
- string str(de->d_name);
- dirVec.push_back(str);
- }
- for(auto& dir : dirVec)
- {
- lstat(dir.c_str(), &dirstat);
- if ((dirstat.st_mode & S_IFMT) == S_IFDIR) //目录文件
- {
- printf("dir:%s, at-time:%ld, mt-time:%ld, ct-time:%ld \r\n",
- dir.c_str(), dirstat.st_atime, dirstat.st_mtime, dirstat.st_ctime);
- string strTmp1 = ".";
- string strTmp2 = "..";
- if (dir.compare(".") || dir.compare(".."))
- {
- printf("Don't touch current dir:%s \r\n", dir.c_str());
- continue;
- }
- clock_gettime(CLOCK_REALTIME, &tstmtime);
- time_t ttSec = tstmtime.tv_sec;
- printf("Current time:%ld \r\n", ttSec);
- if (ttSec > dirstat.st_ctime + 300)
- {
- printf("dir:%s, created over 100 \r\n", dir.c_str());
- }
- }
- }
- closedir(d);
- }
- 直接编译的时候,出现错误
问题分析:
此时很多语法并不支持,需要升级到新版本的gcc/g++才能满足要求.
目前老的工具链不支持新的C++语法,查看gcc编译器版本:
需要升级到一个新版本,以下就详细讲解如何升级ubuntu的gcc/g++工具链。
2:简单方法及失败分析
参照网络的方式,主要的流程包括:
sudo apt-get update
sudo apt-get upgrade
以上就是使用/etc/apt/source.list中指定的网站来更新当前的软件,
之后增加一个第三方软件来源:
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
此处会等待很长时间,也可能会通过,通过之后,就会将:
ppa:ubuntu-toolchain-r/test添加到你的程序源地址,这个地址在:/etc/apt/sources.list.d
之后更新软件源:sudo apt-get update
之后安装最新gcc:sudo apt-get install gcc-11
但实际安装的时候,会提示无法下载,,如下:
或者认证等问题
按照网上处理方法,将source.list从阿里服务器修改为中科大的,如下source.list
效果也是一样的,最后没办法,只有自己下载编译了,以下就是完整过程
3.手动下载软件包
3.1 先下载gcc的软件包
先下载gcc包:gcc-11.2.0.tar.gz
通过清华的镜像网站:
mkdir sys-upd //创建一个目录
cd sys-upd
wget https://mirrors/tinghua/gnu/gcc-11.2.0/gcc-11.2.0.tar.gz
下载完后,解压
tar -zxvf gcc-11.2.0.tar.gz
3.2 执行依赖文件下载
./contrib/download_prerequisites
提示文件下载,但下载失败了,实际下载的只有4K吧,实际文件都是1~2M的,
查看download_prerequisites文件,实际需要下载如下4个文件
gmp='gmp-6.1.0.tar.bz2'
mpfr='mpfr-3.1.6.tar.bz2'
mpc='mpc-1.0.3.tar.gz'
isl='isl-0.18.tar.bz2'
文件下载来源为:base_url='http://gcc.gnu.org/pub/gcc/infrastructure/'
手动wget下载这个几个包试试,按照download_prerequisites上的下载地址:
wget http://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2
实际获取的文件确实就只有4K,显然不正确,使用浏览器查看和下载就1.9M,这个可能是公司网络的限制吧。
3.3 手动下载依赖文件
既然不能自动下载依赖文件,那就找个可用的镜像网站下载,如清华镜像网站
base_url='https://mirrors.tuna.tsinghua.edu.cn/gnu/'
实际浏览器可以打开查看的,不过挺尴尬的是:清华的gnu下面多了一级目录,和gcc.gnu.org/pub/gcc/infrastructure/ 下直接文件不同
如下图就是gnu官网的
下图是清华镜像网站的:
实际的压缩文件包在各自的目录中,不好直接修改download_prerequisites文件,那就手动下载吧。
以下操作网上也有描述:
3.3.1:下载、编译、安装gmp-6.1.0.tar.bz2
- wget https://mirrors.tuna.tsinghua.edu.cn/gnu/gmp/gmp-6.1.0.tar.bz2
- tar -vxf gmp-6.1.0.tar.bz2
- cd gmp-6.1.0/
- ./configure --prefix=/usr/local/gmp-6.1.0
- make
- sudo make install
- cd..
3.3.2:下载、编译、安装mpfr-3.1.6.tar.bz2
- wget https://mirrors.tuna.tsinghua.edu.cn/gnu/mpfr/mpfr-3.1.6.tar.bz2
- tar -xvf mpfr-3.1.6.tar.bz2
- cd mpfr-3.1.6/
- ./configure --prefix=/usr/local/mpfr-3.1.6 --with-gmp=/usr/local/gmp-6.1.0
- Make
- sudo make install
- cd ..
3.3.3:下载、编译、安装mpc-1.0.3.tar.gz
- wget https://mirrors.tuna.tsinghua.edu.cn/gnu/mpc/mpc-1.0.3.tar.gz
- tar -xvf mpc-1.0.3.tar.gz
- cd mpc-1.0.3/
- ./configure --prefix=/usr/local/mpc-1.0.3 --with-gmp=/usr/local/gmp-6.1.0 --with-mpfr=/usr/local/mpfr-3.1.6
- Make
- sudo make install
- cd ..
特别注意:以上1.2.3步是固定的,因为mpfr需要依赖--with-gmp,而mpc需要依赖--with-gmp和with-mpfr,如果顺序不对,make就会提示出错。
4.安装
4.1 :设置环境变量
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/mpc-1.0.3/lib:/usr/local/gmp-6.1.0/lib:/usr/local/mpfr-3.1.6/lib
4.2:生成gcc编译makefile
./configure --prefix=/usr/local/gcc-11.2 -enable-threads=posix -disable-checking -disable-multilib -enable-languages=c,c++ -with-gmp=/usr/local/gmp-6.1.0 -with-mpfr=/usr/local/mpfr-3.1.6 -with-mpc=/usr/local/mpc-1.0.3
4.3:编译、安装
Make –j4 //此过程比较漫长,我编译了将近2小时(电脑比较菜)
Sudo make install
5 配置
5.1:查看版本及配置
还是老的, 直接到目录下看看:
已经是更新到11.2.0了,那是环境变量不正确
5.2 修改下环境变量
export PATH=/usr/local/gcc-11.2/bin:$PATH
gcc –v
此时就已经是最新的了。
编译最初的测试代码测试下:
No error, no warning!!!
最后,为了保证每次登陆及每个用户登陆都使用最新的PATH,需要修改下环境变量
sudo vim /etc/profile
//最后增加一行
export PATH=/usr/local/gcc-11.2/bin:$PATH
6. 运行配置
6.1 直接执行程序
kongcb@tcu-pc:~/testcode$ kongcb@tcu-pc:~/testcode$ ./testdir ./
./testdir: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by ./testdir)
kongcb@tcu-pc:~/testcode$
无法执行,问题分析就是:
调用的高版本的gcc,生成的动态库没有替换老版本gcc
的动态库导致的,需要找到新版的gcc库更新。
6.2更新系统gcc库
查找库:
kongcb@tcu-pc:~/sys-upd/gcc/prev-x86_64-pc-linux-gnu/libstdc++-v3/src/.libs$ locate libstdc++.so.6.0.29
/home/clou-tcu/kongcb/sys-upd/gcc/prev-x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.so.6.0.29
查找库支持的libc版本
kongcb@tcu-pc:~/sys-upd/gcc/prev-x86_64-pc-linux-gnu/libstdc++-v3/src/.libs$ strings libstdc++.so.6.0.29 | grep GLIBCXX_3.4.29
GLIBCXX_3.4.29
GLIBCXX_3.4.29
将该文件迁移过去
sudo rm /usr/lib/x86_64-linux-gnu/libstdc++.so.6
sudo ln /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.29 /usr/lib/x86_64-linux-gnu/libstdc++.so.6 -s
再运行程序,结果正确,如下: