必须加 -fPIC,否则报 relocation 错误;动态库命名须为 libxxx.so 格式,运行时需通过 LD_LIBRARY_PATH 或 ldconfig 配置路径,否则提示 “cannot open shared object file”。

gcc -shared 编译动态库必须加 -fPIC
不加 -fPIC 会报错:relocation R_X86_64_32 against `.rodata' can not be used when making a shared object。因为动态库在运行时可能被加载到任意内存地址,代码必须是位置无关的。-fPIC 让编译器生成位置无关的目标文件,这是 -shared 的硬性前提。
- 直接一步到位(推荐初学者):
gcc -fPIC -shared -o libfoo.so foo.c - 分两步更可控:
gcc -c -fPIC foo.c -o foo.o,再gcc -shared -o libfoo.so foo.o - 多个源文件同理:
gcc -fPIC -shared -o libfoo.so foo1.c foo2.c bar.c
动态库命名必须是 libxxx.so 格式
Linux 下链接器只认 lib<name>.so</name> 这种命名。如果你生成了 foo.so,后续用 -lfoo 是找不到的——链接器会去找 libfoo.so,而不是 foo.so。
- 正确命名:
gcc -fPIC -shared -o libmath.so add.c sub.c - 错误命名(但能生成):
gcc -fPIC -shared -o math.so add.c→ 后续-lmath失败 - 临时绕过命名限制:不用
-l,直接把libmath.so当普通文件传给gcc:gcc main.c ./libmath.so -o app
使用动态库时程序能跑起来但报 “cannot open shared object file”
这说明链接阶段成功了(gcc -L. -lmath 没报错),但运行时找不到 libmath.so。Linux 不默认搜索当前目录,LD_LIBRARY_PATH 是最常用的临时解决方式。
- 运行前设置:
LD_LIBRARY_PATH=. ./app - 永久生效(不推荐开发阶段):
sudo sh -c 'echo "/path/to/your/lib" > /etc/ld.so.conf.d/mylib.conf' && sudo ldconfig - 检查是否识别:
ldd app | grep math—— 如果显示not found,就是路径问题;如果显示路径但权限 denied,注意.so文件是否可读
静态库和动态库同名时 gcc 默认选动态库
当你同时有 libmath.a 和 libmath.so 在同一目录,并执行 gcc main.c -L. -lmath -o app,链接器会优先选择 .so。这不是 bug,是设计行为。
- 强制用静态库:
gcc main.c -L. -static -lmath -o app(但需确保系统装了静态 libc,否则报cannot find -lc) - 更稳妥的静态链接写法:
gcc main.c ./libmath.a -o app(绕过-l查找逻辑) - 混合链接(部分静态、部分动态)不可靠,
-static-libgcc等参数易引发符号冲突,建议避免
gcc -fPIC -shared 写得再标准,./app 一执行就挂,八成是 LD_LIBRARY_PATH 没设对,或者忘了 ldconfig 刷新缓存。


















