2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 让C/C++程序一次编译 到处运行 (仅限Linux)

让C/C++程序一次编译 到处运行 (仅限Linux)

时间:2019-10-19 12:23:00

相关推荐

让C/C++程序一次编译 到处运行 (仅限Linux)

本文不考虑静态链接方式,很多库在静态链接的时候会有问题,比如libunwind,它的异常处理API会和gcc原有的冲突。还有一个显著的问题就是nss。它根据配置文件/etc/nsswitch.conf来动态决定加载哪个so,然后用这个so执行名称解析服务等等。(nss是glibc的一部分,是系统很基本的东西)。还有,jni的so,想要静态链接很难。意思就是说,我要编译一个so,但是这个so所依赖的其它库又都必须是静态链接的,很难,而且也许会引入很多BUG。出于种种原因,我完全放弃了静态链接。(程序采用静态链接完美世界的传统) 即便你的程序简单到只是一个hello world,那么也需要链接到libc.so。很明显,不同的glibc版本之间,差别很大,经常不兼容。那么我能不能在低版本的Linux上使用高版本的Linux的libc.so呢? 于是我做了一个测试,我这边主要有两种Linux系统:CentOS 5和CentOS 6。 CentOS 5下ld-linux-x86-64.so.2指向的是ld-2.5.so CentOS 6下ld-linux-x86-64.so.2指向的是ld-2.12.so 如果强行把CentOS 5的这个so替换成CentOS6的那个,那么会发现任何elf都执行不了, relocation error: /lib64/libc.so.6: symbol _dl_tls_get_addr_soft, version GLIBC_PRIVATE not defined in file ld-linux-x86-64.so.2 系统基本是僵死状态。(还好我今天用/lib64/ld-2.5.so ln -s -f ld-2.5.so ld-linux-x86-64.so.2的方式救回来了) 如果我们不替换ld.so,而只是替换libc.so,例如: LD_LIBRARY_PATH=/home/changming/apps/lib64 ls (/home/changming/apps/lib64放的是CentOS6的libc.so) 那么会报告:error while loading shared libraries: /home/changming/apps/lib64/libc.so.6: ELF file OS ABI invalid 用file查看一下: CentOS 6的libc.so.6: ELF 64-bit LSB shared object, AMD x86-64, version 1 (GNU/Linux), for GNU/Linux 2.6.18, not stripped CentOS 6的libc.so.6: ELF 64-bit LSB shared object, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, not stripped CentOS 6的libstdc++.so.6: ELF 64-bit LSB shared object, AMD x86-64, version 1 (SYSV), stripped 这个差别在于elftype。 于是我从FreeBSD 9下面,把brandelf.c复制到Linux,稍作修改后编译。然后用它更改elftype。 ./brandelf -t SVR4 /home/changming/apps/lib64/libc.so.6 apps/lib64/libm.so.6 然后在CentOS 5 下面用CentOS 6的ld.so执行CentOS 6的bash LD_LIBRARY_PATH=/home/changming/apps/lib64 /home/changming/apps/lib64/ld-linux-x86-64.so.2 ./bash error while loading shared libraries: /home/changming/apps/lib64/libc.so.6: unexpected reloc type 0×25 这个问题在于,bash会fork新进程,而新进程采用哪个ld.so,是我无法控制的。 综上所述:用老的ld.so配合新的libc.so,只有两种结果:"ELF file OS ABI invalid”或 “unexpected reloc type 0×25”。 结论:ld.so的版本必须和glibc的版本匹配。 但是,大多数情况下,这不是一个问题。因为大部分程序(我写的)是不会fork的。 我想说一个什么事情呢? 我想说,Linux的这套动态链接库命名机制(soname、linker name、realname)并未能解决DLL hell的问题。参见:/HOWTO/Program-Library-HOWTO/shared-libraries.html 我现在写好一个程序,当把它扔到别的系统上运行时,它对OS的依赖应当越小越好,否则难道我为每个发行版的每个主版本都编译一次?虽然大部分开源项目都是这么做的,但是我实在是不想。我希望只编译一次,并且编译时所采用的so和运行时采用的so是完全一样的!综上所述,如果不fork,那么you can ! 如果我就是非要fork,那么怎么办呢? 答:对于无源代码的程序,改ELF文件的Program Headers。将PT_INTERP的值设置为我自己的ld.so。(原来的默认值是/lib64/ld-linux-x86-64.so.2)。改完之后可以用readelf这个命令检查一下。对于自己有源代码的程序,可以重新编译,加上–dynamic-linker ./ld-linux-x86-64.so.2 这样的参数。注意,对于setuid程序,这里一定要写绝对路径,否则就是一个安全漏洞哇。 在解决这些问题之后,只要我的程序没有用到Linux Kernel的新特性,那么就可以在相当大范围内的Linux上,自由执行了。 show几个脚本: 打包so,并扔到http server上: #!/bin/bash

rm -rf /tmp/lib64tar

mkdir /tmp/lib64tar

cp /lib64/ld-linux-x86-64.so.2 /tmp/lib64tar

cp /lib64/libc.so.6 /tmp/lib64tar

cp /lib64/libdl.so.2 /tmp/lib64tar

cp /lib64/libgcc_s.so.1 /tmp/lib64tar

cp /lib64/libm.so.6 /tmp/lib64tar

cp /lib64/libpthread.so.0 /tmp/lib64tar

cp /usr/lib64/libstdc++.so.6 /tmp/lib64tar

tar -zcvf /tmp/lib64tar.tar.gz -C /tmp/ lib64tar

scp /tmp/lib64tar.tar.gz 10.4.1.27:/home/changming/public_html/glu/ 自动安装脚本 (glu script): class LinuxLib64{

def install = {

log.info "Installing…"

def skeleton = shell.fetch(params.linuxlib64url)

def distribution = shell.untar(skeleton)

shell.rmdirs(mountPoint)

shell.mv(shell.ls(distribution)[0], mountPoint)

shell.toResource(mountPoint.path).list().each{ f ->

log.info f.path

shell.chmodPlusX(f)

}

log.info "Install complete."

} def createChild = { args ->

return args.script

}

} glu static model: {

"agent": "10.4.1.14",

"mountPoint": "/lib64",

"initParameters": {

"linuxlib64url": "http://10.4.1.27/~changming/glu/lib64tar.tar.gz",

},

"entryState": "installed",

"parent": "/",

"metadata": {},

"tags": [],

"script": "http://10.4.1.27/~changming/glu/linuxlib64.groovy"

} 今天试了一下,从icu的网站下载为RHEL6编译的二进制包(一个tar包),然后在CentOS 5上解压到任意目录,这么执行:

“ /home/changming/apps/lib64/ld-linux-x86-64.so.2 –library-path ../lib:/home/changming/apps/lib64 ./uconv –list” All Things Works Fine! 原文链接:/redirect/6855

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。