[实践Ok]memcache的静态编译lib库在makefile里的引用及h头文件动态指向(编译时用到),对Linux下的Makefile在实践中得以重新认识的记录备案~静态编译问题之warning: Using 'getaddrinfo' in statically linked ...

jackxiang 2015-4-23 16:39 | |
前置:linux下C include搜索的路径,http://blog.csdn.net/chosen0ne/article/details/7210946
背景:其实之前没有研究过c的静态编译,包括对Linux下的make依赖啥的也不太懂,于是试着用c的头文件组织文件相互调用同时,觉得把生成的项目做成一个静态链接版本可执行文件,以便于在各种啥都不装的linux平台上运行(One file ,run as server ok的个人理想主义思想。),有点像像山寨嵌入式开发。我想简单,链接参数加一个-static不就行了,但接下来解决一系列问题的时间远远超出我的意料linux 静态链接 mysql glibc 库的悲催过程,边学习边扯淡,边记录,最后还是硬给扯到最后一步了给glibc的dlopen给挡住了,我看网上也有兄弟遇到类似的,但都最后妥协成动态编译这个glibc,加上参数:-ldl,我是学习实践,所以就不用了,但记录一下总是好事情。
一)关于Makefile的三个特点:
multipepollserver:multipepollserver.o memcachedclient.o writeFile.o memorypool.o readconf.o  multipepollserver.h readconf.h memorypool.h readconf.h memcachedclient.h
    /usr/bin/gcc44 -Wall  -O0 -g -o multipepollserver  multipepollserver.o memorypool.o readconf.o  writeFile.o -lrt -lpthread -lmemcached
(1)把上面这个后面的.h去了也能编译过,那这些.h在Makefile里是不是没有用?
        回答:.h用于符号链接 ,如果不包进去在运行的时候,或动态库加载时会产生符号表找不到。去掉是没问题,我也没加头文件。加上头文件依赖,修改头文件后,也会引起重新编译。

(2)memcachedClientGet找不到,在代码里都包含了,但是make时说找不到。
      你也要依赖memcachedclient.o呀,你的实现在这里面,你不加进去,当然找不到。(这儿是核心:就是上面第二行,说找不到:也就是说第二行才是真正编译时的参数,第一行,主要是以来之用,没有第一行的.o,那么,后面写的这些.oMakefile规则是不会去编译的,所以也得写上涉及到的.o。)

是的,如下,居然说找不到这个函数:
vi multipepollserver.h
#include "memcachedclient.h"
这个我有包含的呀,
vim memcachedclient.c
#include "memcachedclient.h"  
ls  memcachedclient.h
memcachedclient.h
cat memcachedclient.c|grep memcachedClientGet
int memcachedClientGet(char *getKey,char *value){


二)关于静态编译:
问:如何把memcached由动态编译变为静态编译:
答:把 -lmemcached 改成 /.../libmemcached.a
它不是.a,是.la,要.a的,.la为libtool自动生成的一些共享库,可以用vi编辑查看,主要记录了一些配置信息。
它为何不在:/usr/local/libmemcached/下面,而是在,为何不放一块儿?
出现:undefined reference to `sasl_done'
版本对不对??


估计这些接口是在新版本中新定义的,你链接的可能是旧版本。
我对memcached没研究,不清楚。
静态库版本估计看不出,除非它源代码里有版本信息的字符串,可以抓一抓。

你可以执行
strings libmemcached.a | grep 找不到的接口名称
看有没有打印,没打印什么内容,那就说明该静态库里面没这个接口。

兄弟所说的也就是.h的定义和这个.a不匹配是吧:
1)libmemcached/memcached.h  (/usr/local/libmemcached/)
2)/usr/local/lib/libmemcached.a

你这个静态库在编译的时候是不是没有开启sasl支持?导致编译出来的是没带sasl。
[root@test libmemcached-1.0.18]# ./configure --prefix=/usr/local/libmemcached --enable-sasl
[root@test libmemcached-1.0.18]# make clean & make & make install

./libmemcached-1.0/memcached.h:46:23: error: cinttypes: No such file or directory //根据经验,又是gcc的版本不够了。

export CC=/usr/bin/gcc44
export CXX=/usr/bin/g++44
一定要确认是否加成功了,如下:
[root@test libmemcached-1.0.18]# echo $CC
/usr/bin/gcc44
[root@test libmemcached-1.0.18]#  echo $CXX
/usr/bin/g++44

于是编译通过了, 编译再次顺利通过,来自:https://jackxiang.com/post/7693/

问题还有:
/usr/local/libmemcached/lib/libmemcached.a(libmemcached_libmemcached_la-delete.o):(.data.DW.ref.__gxx_personality_v0[DW.ref.__gxx_personality_v0]+0x0): undefined reference to `__gxx_personality_v0'
/usr/local/libmemcached/lib/libmemcached.a(libmemcached_libmemcached_la-hosts.o): In function `update_continuum':
/opt/libmemcached-1.0.18/libmemcached/hosts.cc:222: undefined reference to `floorf'
/usr/local/libmemcached/lib/libmemcached.a(libmemcached_libmemcached_la-sasl.o): In function `sasl_startup_function':
/opt/libmemcached-1.0.18/libmemcached/sasl.cc:126: undefined reference to `sasl_client_init'
/usr/local/libmemcached/lib/libmemcached.a(libmemcached_libmemcached_la-sasl.o): In function `memcached_sasl_authenticate_connection(memcached_instance_st*)':
/opt/libmemcached-1.0.18/libmemcached/sasl.cc:210: undefined reference to `sasl_errstring'
/opt/libmemcached-1.0.18/libmemcached/sasl.cc:218: undefined reference to `sasl_client_new'
/opt/libmemcached-1.0.18/libmemcached/sasl.cc:220: undefined reference to `sasl_errstring'
/opt/libmemcached-1.0.18/libmemcached/sasl.cc:222: undefined reference to `sasl_dispose'
/opt/libmemcached-1.0.18/libmemcached/sasl.cc:231: undefined reference to `sasl_client_start'
/opt/libmemcached-1.0.18/libmemcached/sasl.cc:234: undefined reference to `sasl_errstring'
/opt/libmemcached-1.0.18/libmemcached/sasl.cc:236: undefined reference to `sasl_dispose'
/opt/libmemcached-1.0.18/libmemcached/sasl.cc:276: undefined reference to `sasl_client_step'
/opt/libmemcached-1.0.18/libmemcached/sasl.cc:289: undefined reference to `sasl_dispose'
/usr/local/libmemcached/lib/libmemcached.a(libmemcached_libmemcached_la-sasl.o): In function `sasl_shutdown_function':
/opt/libmemcached-1.0.18/libmemcached/sasl.cc:117: undefined reference to `sasl_done'
估计是引入的memcached.h不一致,找了一下,我是安装在/usr/local/libmemcached下,而我看其它地方还有,于是直接把/usr/local/include/libmemcached-1.0/头文件覆盖得了:
[root@test /]# find . -name "memcached.h"
./home/xiangdong/software/gearmand-1.1.12/libtest/memcached.h
./usr/local/libmemcached2/include/libmemcached/memcached.h
./usr/local/libmemcached/include/libmemcached-1.0/struct/memcached.h
./usr/local/libmemcached/include/libmemcached-1.0/memcached.h
./usr/local/libmemcached/include/libmemcached/memcached.h
./usr/local/include/libmemcached-1.0/struct/memcached.h
./usr/local/include/libmemcached-1.0/memcached.h
./usr/local/include/libmemcached/memcached.h

_________________________________________________________________________________
rm -Rf /usr/local/include/libmemcached/*
rm -Rf /usr/local/include/libmemcachedutil-1.0/*

cp -Rf /usr/local/libmemcached/include/libmemcachedutil-1.0/* /usr/local/include/libmemcachedutil-1.0/.
cp -Rf /usr/local/libmemcached/include/libmemcached/*  /usr/local/include/libmemcached/.
_________________________________________________________________________________
[root@test multepoolserver]# make clean;make
rm -f memcachedclient.o memorypool.o  multipepollserver.o multipepollserver writeFile.o readconf.o
/usr/bin/gcc44  -Wall  -O0 -g3 -gdwarf-2 -c -g multipepollserver.c
In file included from multipepollserver.h:27,
                 from multipepollserver.c:6:
/usr/local/include/libmemcached/memcached.h:39:40: error: libmemcached-1.0/memcached.h: No such file or directory

果然是这儿读取,/usr/local/include/libmemcached-1.0 给我删除了,还是拷贝过去吧:

再一次确认证明,在安装libmemcached时指定目录后,如果在.h里包含(#include <libmemcached/memcached.h>)则加上这个makefile的路径:-I/usr/local/libmemcached/include/ -L/usr/local/libmemcached/lib 否则,默认公位置找不到相关的函数申明及lib库的。【./configure --prefix=/usr/local/libmemcached 这样的,不会放在/usr/local/libmemcached/lib 下的。】
再就是.a的静态文件:/usr/local/libmemcached/lib/libmemcached.a


问题还依旧,怎么办:
[root@test /]# find . -name "libmemcached.a"
./usr/local/lib/libmemcached.a
./usr/local/libmemcached/lib/libmemcached.a

md5对比下是否是一样的,还真不一样,两个同样的文件:
[root@test lib]# md5sum /usr/local/lib/libmemcached.a
d1f93fcf34649c5d72b19e636b2c1b2e  /usr/local/lib/libmemcached.a
[root@test lib]# md5sum /usr/local/libmemcached/lib/libmemcached.a
4026e0e061d0692b3a3b7016ee4a6066  /usr/local/libmemcached/lib/libmemcached.a

这个.a是不是也得从我刚编译的路径给覆盖到/usr/local/lib/,比对了一下,都是一样的,直接拷贝过去得了:
cp -Rf /usr/local/libmemcached/lib/* /usr/local/lib/.
yes|cp -Rf /usr/local/libmemcached/lib/* /usr/local/lib/.


依旧不Ok,编译还是遇到问题,显示无法链接到sasl的一些文件。问题显示如下:

   undefined reference to `sasl_client_step'
   undefined reference to `sasl_dispose'
   undefined reference to `sasl_client_start'
   undefined reference to `sasl_client_new'

————————————————————这种方法不行————————————————————
/usr/bin/gcc44 -Wall  -O0 -g -o multipepollserver  multipepollserver.o memcachedclient.o memorypool.o readconf.o  writeFile.o -lrt -lpthread   /usr/local/lib/libmemcached.a
/usr/local/lib/libmemcached.a(libmemcached_libmemcached_la-delete.o):(.data.DW.ref.__gxx_personality_v0[DW.ref.__gxx_personality_v0]+0x0): undefined reference to `__gxx_personality_v0'

最后加上:-lstdc++
multipepollserver:multipepollserver.o memcachedclient.o writeFile.o memorypool.o readconf.o
    /usr/bin/gcc44 -Wall  -lstdc++  -O0 -g -o multipepollserver  multipepollserver.o memcachedclient.o memorypool.o readconf.o  writeFile.o -lrt -lpthread   /usr/local/lib/libmemcached.a
好了。
备案在:http://jackxiang.com/post/7981/

————————————————————————————————————————————————————————————————————————————
   解决办法是重新执行configure命令,增加相应的参数。sudo执行命令:sudo ./configure --prefix=/usr/local/libmemcached  --enable-sasl --without-memcached LDFLAGS=-Wl,--as-neede ;make; make install

遇到问题:fatal error: sasl/sasl.h: No such file or directory. 在网上搜到的解决办法是:

   Depending on your operating system, you'll need to install the cyrus-sasl development package.

   That would be cyrus-sasl-devel on RedHat based distros and libsasl2-dev on Debian based distros IIRC.

   我在ubuntu下直接用sudo apt-get install libsasl2-dev 安装了。
说明果然是有这个libsal2-dev的安装包的,CentOS不一样,但也类似,于是ls下:
[root@test multepoolserver]# ls /usr/lib/libsasl2*
/usr/lib/libsasl2.a  /usr/lib/libsasl2.so  /usr/lib/libsasl2.so.2  /usr/lib/libsasl2.so.2.0.22
    /usr/bin/gcc44 -Wall  -lstdc++  -O0 -g -o multipepollserver  multipepollserver.o memcachedclient.o memorypool.o readconf.o  writeFile.o -lrt -lpthread   /usr/local/lib/libmemcached.a /usr/lib/libsasl2.a  
于是把:/usr/lib/libsasl2.a 放到makefile里,再编译出现 incompatible with i386:x86-64 output:
rpm -ql cyrus-sasl-devel-2.1.22-5.el5_4.3 发现位置在这儿:
/usr/lib/libsasl2.a   不对,64位的位置在这儿:/usr/lib64/libsasl2.a
/usr/include/sasl/sasl.h
/usr/include/sasl/saslplug.h
/usr/include/sasl/saslutil.h
/usr/lib/libsasl2.a
/usr/lib/libsasl2.so


/usr/include/sasl/prop.h
/usr/include/sasl/sasl.h
/usr/include/sasl/saslplug.h
/usr/include/sasl/saslutil.h
/usr/lib64/libsasl2.a
/usr/lib64/libsasl2.so

修改后,还有错,听说是和openssl有关:
/usr/lib64/libsasl2.a(digestmd5.o): In function `dec_3des':
(.text+0x6c0): undefined reference to `DES_ede3_cbc_encrypt'
/usr/lib64/libsasl2.a(digestmd5.o): In function `init_3des':
(.text+0x3bf2): undefined reference to `DES_key_sched'
/usr/lib64/libsasl2.a(digestmd5.o): In function `init_3des':

[root@test multepoolserver]# rpm -ql openssl-devel-0.9.8e-12.el5_4.6|grep .so
/usr/include/openssl/dso.h
/usr/lib64/libcrypto.so
/usr/lib64/libssl.so
[root@test multepoolserver]# ls /usr/lib64/libssl.a
/usr/lib64/libssl.a

[root@test multepoolserver]# rpm -ql openssl-devel-0.9.8e-12.el5_4.6|grep "ssl.h"
/usr/include/openssl/hmac.h
/usr/include/openssl/kssl.h
/usr/include/openssl/ssl.h
/usr/include/openssl/hmac.h
/usr/include/openssl/kssl.h
/usr/include/openssl/ssl.h


——————————————————————————————————————————
加上:
/usr/lib64/libssl.so
/usr/include/openssl/ssl.h

/usr/include/openssl/ssl.h
/usr/include/sasl/sasl.h
vi memcachedclient.h
#include <sasl/sasl.h>
#include <openssl/ssl.h>  


Makefile里加上:
multipepollserver:multipepollserver.o memcachedclient.o writeFile.o memorypool.o readconf.o
    /usr/bin/gcc44 -Wall  -lstdc++  -O0 -g -o multipepollserver  multipepollserver.o memcachedclient.o memorypool.o readconf.o  writeFile.o -lrt -lpthread   /usr/local/lib/libmemcached.a /usr/lib64/libsasl2.a /usr/lib64/libssl.a

报错:
/usr/lib64/libsasl2.a(gssapi.o): In function `gssapi_client_mech_step':
(.text+0x1263): undefined reference to `GSS_C_NT_HOSTBASED_SERVICE'
于是再查,发现这玩意有关:
libgssapi-0.10-2.i386.rpm
/usr/lib/libgssapi_krb5.so

————————————————yum search libgssapi——————————————————————————
libgssapi.i386 : Generic Security Services Application Programming Interface Library
libgssapi.x86_64 : Generic Security Services Application Programming Interface Library
libgssapi-devel.i386 : Development files for the gssapi library
libgssapi-devel.x86_64 : Development files for the gssapi library

于是64位机器就安装:libgssapi-devel.x86_64 吧 :yum install libgssapi-devel.x86_64

rpm -ql libgssapi-devel.x86_64
/usr/include/gssglue/gssapi/gssapi.h
/usr/lib64/libgssapi.a
/usr/lib64/libgssapi.so
/usr/lib64/pkgconfig/libgssapi.pc

于是有了,上面这个错不报了,有新的错误,如下:

/usr/bin/gcc44 -Wall  -lstdc++  -O0 -g -o multipepollserver  multipepollserver.o memcachedclient.o memorypool.o readconf.o  writeFile.o -lrt -lpthread   /usr/local/lib/libmemcached.a /usr/lib64/libsasl2.a /usr/lib64/libssl.a /usr/lib64/libcrypto.a /usr/lib64/libgssapi.a
/usr/lib64/libcrypto.a(fips.o): In function `FIPSCHECK_verify':
(.text+0x7fa): undefined reference to `dlopen'
/usr/lib64/libcrypto.a(fips.o): In function `FIPSCHECK_verify':
(.text+0x80f): undefined reference to `dlsym'
/usr/lib64/libcrypto.a(fips.o): In function `FIPSCHECK_verify':


编译错误undefined reference to `dlsym' ,今天编译碰到了问题,加了-ldl就ok了。
[c-sharp] view plaincopy
dso_dlfcn.c:(.text+0x325): undefined reference to `dlsym'  
dso_dlfcn.c:(.text+0x408): undefined reference to `dlerror'  就Ok了,From:http://blog.csdn.net/shareyao/article/details/5362642
继续查,这个是glibc库的: rpm -ql glibc-devel-2.5-42  
rpm -ql glibc-devel-2.5-42|grep "libdl.so"
/usr/lib/libdl.so
/usr/lib64/libdl.so
————————————————————————————————————————————————————————————————
ls /usr/lib64/libdl.so
/usr/lib64/libdl.so
ls /usr/lib64/libdl.a
/usr/lib64/libdl.a

只加:/usr/lib64/libdl.a 还是会继续报同样的错误,在这儿看到了,还得加:/usr/lib64/libc.a  
自己折腾了一下,静态链接libdl.a的同时把libc.a也链接过去,就可以解决“undefined reference”的问题,从而得到可执行程序。这里很奇怪,dlopen是在libdl.a里,但是它的实现--__dlopen却是在libc.a里。。。
  http://www.newsmth.net/nForum/#!article/CProgramming/113004


最终大功告成,其中老罗最多的也是动态,对静态也不是太明白,但不管怎么样经过这一个过程或得了静态的经验:
[root@test multepoolserver]# /usr/bin/gcc44 -Wall  -lstdc++  -O0 -g -o multipepollserver  multipepollserver.o memcachedclient.o memorypool.o readconf.o  writeFile.o -lrt -lpthread   /usr/local/lib/libmemcached.a /usr/lib64/libsasl2.a /usr/lib64/libssl.a /usr/lib64/libcrypto.a /usr/lib64/libgssapi.a /usr/lib64/libdl.a /usr/lib64/libc.a
/usr/lib64/libcrypto.a(fips.o): In function `FIPSCHECK_verify':
(.text+0x7fa): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/local/lib/libmemcached.a(libmemcached_libmemcached_la-connect.o): In function `set_hostinfo':
/opt/libmemcached-1.0.18/libmemcached/connect.cc:217: warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

[root@test multepoolserver]# ls multipepollserver
multipepollserver         EOF

glibc --static编译可能会产生下面的warning:warning: Using 'getservbyport_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking这个主要原因是由于getservbyport_r 这样的接口还是需要动态库的支持才可以运行,许多glibc的函数都存在这样的问题, 特别是网络编程的接口中是很常见的.对一些第三方工具不友好,类似valgrind检查内存泄露为了不在一些特殊的情况下误报, 它需要用动态库的方式替换glibc中的函数,如果静态编译那么valgrind就无法替换这些函数,产生误报甚至无法报错.

linux 静态链接 mysql glibc 库的悲催过程 :http://renshuming8231.blog.163.com/blog/static/1294837652012112954619545/


链接已经成功了,只不过不建议用 -static,它说的意思getaddrinfo在动态库中,却用static的方式链接了。没事吧?
/usr/lib64/libc.a
grep getaddrinfo /usr/lib/*.a
Binary file /usr/lib/libc.a matches

当该a.out在本机跑的时候没有问题,因为dlopen和相应的动态库格式是相互了解的,但是如果在一个别的系统上
执行dlopen时,很可能出错
就是说本来static是为了随便拿到别的机器跑,而可能发生错误(甚至莫名奇妙的错误,我现实中遇到过,几乎没法调试,以前还不知道原因)
所以有个警告,如果静态编译的话,忽略这个警告使用中会有问题吗?只是警告你有可能出错而已。

作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:http://jackxiang.com/post/7978/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!


最后编辑: jackxiang 编辑于2017-9-6 10:20
评论列表
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]