使用高版本GCC进行项目编译
问题背景
CentOS7的GCC版本为4.8.5,这个版本对C++11的支持不完整,比如,对于正则表达式库,编译器本身支持,但标准库不支持。
之前的c++项目在Ubuntu18.04上编译,在迁移到CentOS7后,使用系统自带的GCC编译项目一直出错,经过排查定位到正则库的支持问题。
这种情况有两种解决方案:1,替换使用`Boost`库的`regex`库,工作量非常小;2,编译安装更高版本的GCC来编译项目。
第一种方案在第三方库也用到了regex时没办法处理。作为库开发者,如果要兼容低版本GCC时,通常在CMake脚本中会判断,如果是低版本GCC则依赖安装Boost库作为方案。但一般三方库如果声明是针对c++11开发,则不会做这种兼容性考虑。
第二种方案的问题是,高版本GCC编译出的项目会依赖高版本的标准库,在相同架构的相同系统之间,做不到可移植性。
项目编译
使用高版本GCC进行项目编译时,主要关注两点:1,项目是否确认是使用高版本GCC进行的编译;2,项目使用高版本GCC编译时是否链接的是高版本的标准库。
具体的编译过程和指导跟项目的编译方式相关,下面分别针对不同的编译方式进行说明。当前主要包含:`boost`, `cmake`, `make`
b2编译
b2目前只知道Boost库在使用,它有自己的一套编译和配置逻辑。因此,这里相当于是在说明,如何在编译boost库时指定高版本GCC。
编译boost时,会自动搜索当前系统已安装的编译器,然后在编译时指定。但这有时并不生效,需要主动在user-config.jam文件中进行配置。此文件或者位于用户主目录($HOME)下,或者位于$BOOST_BUILD_PATH目录下。后者在源码编译时,指tools/build/src目录。
文件内容形式为using <toolset-name> : <version> : <cmd-path> : <options>;,例如,如果使用clang编译器时,using clang : 10.0 : /usr/bin/clang++ : -std=c++14。编译选项除了在此处指定外,也可在命令行参数中指定:cxxflags="-std=c++14"指定编译的c++标准。
在配置后,使用b2命令时,指定参数:toolset=<toolset-name>-<version>。
cmake编译
使用cmake进行项目编译,通常会使用3条指令:
mkdir build && cd build # 创建构建目录(1) cmake .. # 创建构建缓存(2) make # 编译(3)
cmake会默认使用系统自带的GCC,并非当前PATH中的GCC。通常,在编译安装高版本GCC后,会将相应的bin目录添加到系统GCC的路径之前,这样在执行gcc --version时会验证是否安装成功。但cmake对GCC的选择,感觉跟默认路径/usr/bin/gcc相关。
在使用(2)命令时,查看输出的日志信息,可以确认当前cmake使用gcc版本。在(3)命令时,开启冗余日志模式,使用VERBOSE=1 make来查看链接时是否使用高版本GCC标准库。
修改cmake的默认GCC有两种方式:1,设置环境变量CC/CXX,与make相同;2,指定CMAKE_C_COMPILER和CMAKE_CXX_COMPILER两个变量,通过-Dkey=value的形式。
make编译
使用make进行项目编译,通常采用设置环境变量CC/CXX的方式来指定编译用的GCC版本。
项目运行
高版本GCC编译安装后的执行文件或动态库依赖高版本的GCC标准库。如果将编译结果移植到另一个同架构同系统的机子,则会运行失败。C++标准库一直存在的ABI不兼容问题,就是对同一个API,不同版本的标准库实现不同,导致在链接时失败。
通常有两种方式来解决:1,静态链接标准库;2,复制高版本的标准库到指定位置(覆盖或链接)。
- 点赞
- 收藏
- 关注作者
评论(0)