任务场景
在centos7
上需要使用cmake
编译一份包含
b
r
p
c
brpc
brpc等的项目,并将编译出的可执行文件放到目标ubuntu
机器使其能够直接运行。但是其中需要链接一些包含高版本glibc
的.so
文件,直接cmake编译会报错,类似下图,说明当前主机glibc
版本不够,无法连接高版本glibc
编译出来的动态链接库,需要升级glibc
版本
glibc下载升级
升级较为简单,只需要下载你需要的版本的glibc
版本包(尽量保持和目标机器一致),可以查看包中的
I
N
S
T
A
L
L
INSTALL
INSTALL查看前置需要的环境条件,,一般来说就是
m
a
k
e
make
make的升级,他可能检查的
g
m
a
k
e
gmake
gmake,软连接到
m
a
k
e
make
make就行,以及对应的
g
c
c
gcc
gcc版本和
p
y
t
h
o
n
python
python版本,
g
c
c
gcc
gcc我找了个现成的,从头编译应该会比这个复杂,
p
y
t
h
o
n
python
python用了
m
i
n
i
c
o
n
d
a
miniconda
miniconda(优先解决这几个版本不对的问题,一些莫名的报错很可能只是这些没装对的连锁反应。)
最后 m a k e make make加 m a k e i n s t a l l make \,\,install makeinstall即可,具体的指令去问下 a i ai ai,安装这里基本都是对的
CMAKE配置与编译
先说我实际实验之后可行的方案
首先在cmake
中更改CMAKE_EXE_LINKER_FLAGS
set(CMAKE_EXE_LINKER_FLAGS -fuse-ld=gold)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/opt/glibc-2.35/lib")
然后还需要去往/lib64
路径下更改
crt1.o
\textbf{crt1.o}
crt1.o文件,将其替换为glibc-2.35(你的目标版本glibc路径)/crt1.o
,否则将会报错 error: undefined reference to __libc_csu_fini/__libc_csu_init'
更新!!!,这里不一定非要修改/lib64下的crt1.o,在CMakeLists.txt中加上
\textbf{更新!!!,这里不一定非要修改/lib64下的crt1.o,在CMakeLists.txt中加上}
更新!!!,这里不一定非要修改/lib64下的crt1.o,在CMakeLists.txt中加上-B${GLIBC_PATH}/lib
就可以了,之后甚至都不需要patchelf
,根据gpt-4o
,这里原因是-B
会影响gcc
和ld
搜索的路径查找顺序。同时glibc
版本的更新重点在于libc.so.6
,而对解释器(
i
n
t
e
r
p
r
e
t
e
r
interpreter
interpreter)版本限制很松,所以使用系统的ld
(即/lib64/ld-linux-x86-64.so.2
)即可,不使用glibc
对应版本的ld
仍然能达到升级glibc
的效果。
// 这样写就可以了,不需要修改其他的文件,也不需要patchelf
set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=gold -B${GLIBC_PATH}/lib -L${GLIBC_PATH}/lib")
然后应该就可以编译成功了。
(这里一定记得
备份
\textbf{备份}
备份原有的crt1.o
,否则当你更换gcc
版本并试图用原先版本的glibc
编译时,很可能编译成功,但是一旦运行就直接报错segmentfault
而且很难找到原因。。)
− f u s e − l d = g o l d -fuse-ld=gold −fuse−ld=gold这一句非常关键,不然就会报各种错误,包括但不限于
// 可能出现的各类错误
undefined reference to 'pthread_once'
/usr/lib64/libpthread.so.0: undefined reference to `__libc_dlopen_mode@GLIBC_PRIVATE'
/usr/lib64/libdl.so.2: undefined reference to `_dl_vsym@GLIBC_PRIVATE'
各类问题具体出现和解决的原因完全没搞懂,后面再研究吧。
可执行文件执行
这样的文件生成好之后,如果你的glibc
安装了路径并不在默认路径,将其移动到目标系统后,仍然是无法运行的。需要使用patchelf
更改其解释器路径,改成你系统的glibc
路径,一般是这样:
/path/to/patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2(或者是你想用的版本的glibc路径) /path/to/your_elf
然后就可以顺利运行了
一些令人无语的问题
b
r
p
c
brpc
brpc和
g
l
o
g
glog
glog存在冲突,尽量编译
b
r
p
c
brpc
brpc时就加入
g
l
o
g
glog
glog选项,否则后期可能无法使用
g
l
o
g
glog
glog,需要将#include<glog/logging.h>
都替换成#include<butil/logging.h>
否则会报错
flag 'v' was defined more than once (in files 'src/vlog_is_on.cc' and '/brpc/src/butil/logging.cc').
protobuf
用4.8.5
以下的版本和以上的版本编译存在区别,如果是用老版本编译的,之后又用新的版本试图连接,需要在cmake
内加上add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0)