1. 系统设置
1.1 在 /etc/ld.so.conf 中添加路径,然后重新加载
include ld.so.conf.d/*.conf
/usr/local/lib64
/usr/local/lib
/usr/lib
/usr/lib64
/usr/local/boost/lib
ldconfig -v
1.2 环境变量中导出
# gcc找到头文件的路径
C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/local/boost/include
export C_INCLUDE_PATH
# g++找到头文件的路径
CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/local/boost/include
export CPLUS_INCLUDE_PATH
# 找到动态链接库的路径
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/boost/lib
export LD_LIBRARY_PATH
# 找到静态库的路径
LIBRARY_PATH=$LIBRARY_PATH:/usr/local/boost/lib
export LIBRARY_PATH
1.3 GCC 7.1 编译安装
依赖的安装包有:
- gmp-6.1.2
- mpfr-3.1.5
- mpc-1.0.3
export LIBRARY_PATH=/lib64
./configure --prefix=/usr/local --enable-checking=release --enable-languages=c,c++ --disable-multilib
make
make install
2. gcc 编译
2.1 生成目标模块
gcc -c bill.c fred.c
# 直接使用目标模块:
gcc -o program program.c bill.o fred.o #或者源文件
gcc -o program program.c bill.c fred.c
# 都会带入不需要的模块
2.2 归档生成静态库文件
ar crv libfoo.a bill.o fred.o
ranlib libfoo.a
归档之后:
gcc -o program program.c libfoo.a
或者:
gcc -o program program.c -L. -lfoo
则会根据需要加载对应模块
2.3 在x64位Linux上生成动态链接库必须使用编译选项-fPIC的问题
2.3.1 在 Linux 下制作动态链接库,“标准” 的做法是编译成位置无关代码(Position Independent Code,PIC)
- 通常的建议是始终加上-fPIC 生成位置无关代码;
- AMD64 下,必须使用位置无关代码,否则连接失败: relocation R_X86_64_32S against `a local symbol’ can not be used when making ashared object; recompile with -fPIC
- IA32 下,连接成功,但有警告: warning: creating a DT_TEXTREL in object. 这样的 .so 文件可以完全正常工作。
2.3.2 PIC vs. relocatable
- PIC 的缺点主要就是代码有可能长一些。例如 IA32,由于不能直接使用[EIP+constant] 这样的寻址方式,甚至不能直接将 EIP 的值交给其他寄存器,要用到GOT(global offsettable)来定位全局变量和函数。这样导致代码的效率略低。
- PIC 的加载速度稍快,因为不需要做重定位。
- 多个进程引用同一个 PIC 动态库时,可以共用内存。这一个库在不同进程中的虚拟地址不同,但操作系统显然会把它们映射到同一块物理内存上。对于可重定位代码,则必须为每个库都在物理内存中复制一份副本,因为需要修改其中的地址。当然,主流现代操作系统都启用了分页内存机制,这使得重定位时可以使用 COW(copy on write)来节省内存(32 位 Windows 就是这样做的);然而,页面的粒度还是比较大的(例如 IA32 上是 4KiB),至少对于代码段来说能节省的相当有限。
3. 问题辅助
3.1 常用工具
- locate:查看库依赖
- lld:列出动态依赖
- nm:
- 查看导出函数:
nm -D **.so
- 查看导出函数:
- strace:对系统调用进行跟踪
- objdump
- 查看导出函数:
objdump -tT **.so
- 查看导出函数:
- ar :创建和维护静态库
常用选项:
r 替换归档文件中已有的文件或加入新文件
t 示归档文件的内容
d 从归档文件中删除文件
- 生产内容表:ranlib
- ldconfig:解决共享库问题
- objdumpreadelf
3.2 查看依赖库是否存在
locate libevent-2.1.so.6
结果: 系统已经安装了该模块,在路径 /usr/local/lib/ 查看 memcached 查找依赖库的路径 LD_DEBUG=libs /usr/local/memcached/bin/memcached -v
3.3 踩过的坑
3.3.1 安装时出现: configure.ac:17: error: possibly undefined macro: AC_PROG_LIBTOOL
configure.ac:17: error: possibly undefined macro: AC_PROG_LIBTOOL
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
autoreconf: /usr/bin/autoconf failed with exit status: 1
出现之后那叫一个郁闷啊,在网上搜索,最终得到解决办法,泪流满面啊··
原来缺少一个工具:sudo apt-get install libtool
3.3.2 version `GLIBCXX_3.4.14’ not found
两者是一个问题导致的:c++标准库太老了.没有更新。找到源码安装gcc的目录(gcc编译器最好还是源码安装:/usr/local/lib64/) 先find出libstdc++.so.6.0.22(我的是22) 如果不是源码安装就从根目录找:
find / -name "libstdc++.so*"
rm -rf libstdc++.so.6
ln -s libstdc++.so.6.0.22 libstdc++.so.6
ldconfig
strings /usr/lib64/libstdc++.so.6 | grep GLIBC
3.3.3 collect2: 错误:ld 返回 1
gcc -static atexit.c -o atexit
/usr/bin/ld: cannot find -lc
collect2: 错误:ld 返回 1
解决方案: 需要安装glibc-static.xxx.rpm,如glibc-static-2.12-1.107.el6_4.2.i686.rpm,或是yum install glibc-static
3.3.4 Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.4.x86_64
需要先修改“/etc/yum.repos.d/CentOS-Debuginfo.repo”文件的enable=1;
yum install glibc glibc-debuginfo debuginfo-install glibc-2.17-106.el7_2.4.x86_64