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
如果是CMake, 还可以通过指令来引入: include_directories(path/to/include/dir)
1.3 GCC 7.1 编译安装
依赖的安装包有:
- gmp-6.1.2
- mpfr-3.1.5
- mpc-1.0.3
wget http://ftp.gnu.org/gnu/gcc/gcc-7.3.0/gcc-7.3.0.tar.gz
tar -xvf gcc-7.3.0.tar.gz
cd gcc-7.3.0
# 下载依赖
./contrib/download_prerequisites
mkdir build;cd build
../configure --enable-checking=release --enable-languages=c,c++ --disable-multilib
# --disable-multilib: 用于关闭多个多个arch的库, 比如只需要64位的, 不需要32位的库, 那就添加这个配置
make -j 4
make install
cp /usr/local/lib64/libstdc++.so.6.0.24 /usr/lib64/
ln -sf /usr/lib64/libstdc++.so.6.0.24 /usr/lib64/libstdc++.so.6
# 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. Glibc 升级
wget https://mirrors.aliyun.com/gnu/glibc/glibc-2.31.tar.gz
tar -zxf glibc-2.31.tar.gz
cd glibc-2.31/
cat INSTALL | grep -E "newer|later"
The tests (and later installation) use some pre-existing files of the
* GNU 'make' 4.0 or newer
* GCC 6.2 or newer
building the GNU C Library, as newer compilers usually produce
* GNU 'binutils' 2.25 or later
* GNU 'texinfo' 4.7 or later
* GNU 'bison' 2.7 or later
* GNU 'sed' 3.02 or newer
* Python 3.4 or later
* GDB 7.8 or later with support for Python 2.7/3.4 or later
* GNU 'gettext' 0.10.36 or later
# 先升级对应的依赖包
yum install python3 binutils texinfo bison gettext
# 我的GDB 7.6.1 没升级, 依然ok
mkdir build
cd build
../configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin --disable-sanity-checks --disable-werror
make -j6
make localedata/install-locales
make install
reboot
4. CMake
4.1 为单个目标生成编译数据库
cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=1 # 将产生以下 compile-commands.json
5. 问题辅助
5.1 常用工具
- locate: 查看库依赖
- lld: 列出动态依赖
- nm:
- 查看导出函数:
nm -D **.so
- 查看导出函数:
- strace: 对系统调用进行跟踪
- objdump
- 查看导出函数:
objdump -tT **.so
- 查看导出函数:
- ar : 创建和维护静态库
常用选项:
r 替换归档文件中已有的文件或加入新文件
t 示归档文件的内容
d 从归档文件中删除文件
- 生产内容表: ranlib
- ldconfig: 解决共享库问题
- objdumpreadelf
5.2 查看依赖库是否存在
locate libevent-2.1.so.6
结果: 系统已经安装了该模块, 在路径 /usr/local/lib/
查看 memcached 查找依赖库的路径
LD_DEBUG=libs /usr/local/memcached/bin/memcached -v
5.3 踩过的坑
5.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
5.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
5.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
5.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