Clang生成动态库必须预先加-fPIC编译目标文件,否则链接时因位置重定位失败而报错;Linux/Android用-shared,macOS用-dynamiclib;C++需extern "C"和visibility("default")导出符号。

clang 生成动态库必须加 -fPIC
不加 -fPIC 编译目标文件,后续链接一定会失败,错误通常是:relocation R_X86_64_PC32 against symbol 或类似位置重定位失败。因为动态库在加载时地址不确定,所有代码必须是位置无关的。
正确做法是:编译源码为 .o 时就加上 -fPIC,不是链接时补救。
clang -fPIC -c func.c -o func.o- 多个源文件就分别编译,每个都带
-fPIC - C++ 同理,用
clang++ -fPIC -c xxx.cpp -o xxx.o
链接时用 -shared,不是 -dynamiclib(macOS 除外)
Linux 和 Android 上统一用 -shared;macOS 默认用 -dynamiclib(-shared 也能工作,但 Apple 官方推荐 -dynamiclib)。
常见错误:在 Linux 上误用 -dynamiclib,clang 会报错不支持该选项。
Clang 22.1.3 Windows 64 位历史版本安装包,适合旧项目兼容、LLVM/Clang 工具链回退、编译行为对比、链接问题复现和 C/C++ 构建环境维护。
- Linux/Android:
clang -shared func.o -o libfunc.so - macOS:
clang -dynamiclib func.o -o libfunc.dylib - iOS/macOS 跨平台构建需注意
-target和-isysroot,否则可能链接失败或符号缺失
导出符号要显式声明,尤其 C++
C++ 默认名字修饰(name mangling),直接导出函数会导致 Java/JNI 或其他语言无法调用。不加处理,dlsym 找不到符号是常态。
解决方式是用 extern "C" 包裹声明,并配合 visibility 控制:
- 头文件中写:
extern "C" __attribute__((visibility("default"))) void my_func(); - Windows 下对应的是
__declspec(dllexport),但 clang/macOS 不认这个 - 避免全局暴露:默认设
-fvisibility=hidden,只对真正需要导出的符号加visibility("default")
验证动态库是否可用,别只看文件生成成功
生成 .so 或 .dylib 文件只是第一步。很多问题在运行时才暴露,比如符号没导出、依赖路径不对、架构不匹配。
快速验证建议:
- Linux:
nm -D libfunc.so看是否有你期望的未定义符号(带T或U标记) - macOS:
nm -DY libfunc.dylib或otool -L libfunc.dylib查依赖 - 检查架构:
file libfunc.so确认是x86_64还是aarch64,和目标平台一致 - 运行时加载失败?先确认
LD_LIBRARY_PATH(Linux)或DYLD_LIBRARY_PATH(macOS)是否包含库路径
-fPIC 的强制前置性,以及 C++ 符号导出的双重包裹(extern "C" + visibility)。这两点漏掉一个,库就只能自己用,没法被外部安全调用。

















