Iawen's Blog

我喜欢这样自由的随手涂鸦,因为我喜欢风......

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

把它拷到/usr/lib64下

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