Clang生成动态库需按平台选用参数:macOS/iOS用-dynamiclib和-fPIC,Linux用-shared和-fPIC,Windows用__declspec(dllexport);还需处理符号可见性、iOS签名及架构匹配。

Clang 生成动态库不是“加个 -shared 就完事”,macOS 和 iOS 必须用 -dynamiclib,Linux 才认 -shared;不加 -fPIC 在 macOS/Linux 上会链接失败,Windows 则根本不用这个参数。
macOS/iOS 动态库必须用 -dynamiclib,不是 -shared
Clang 在 macOS 和 iOS 平台不支持 -shared 选项,强行使用会报错:unknown argument: '-shared'。系统只接受 -dynamiclib,且生成的后缀固定为 .dylib。
-
clang -dynamiclib -o libmath.dylib src/math.c -Iinclude是正确写法 - 若源码含 Objective-C,需加
-x objective-c和-fobjc-arc - 目标平台要显式指定,比如 iOS 模拟器:
-target x86_64-apple-ios15.0;真机则用aarch64-apple-ios - 不指定
-isysroot会导致头文件找不到,例如:-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS17.5.sdk
Linux 动态库必须加 -fPIC,且用 -shared
Linux 下动态库要求所有代码是位置无关的(PIC),否则 ld 链接时会拒绝加载:错误信息类似 relocation R_X86_64_32 against ... can not be used when making a shared object。
Clang 22.1.3 Windows 64 位历史版本安装包,适合旧项目兼容、LLVM/Clang 工具链回退、编译行为对比、链接问题复现和 C/C++ 构建环境维护。
- 编译阶段就要加
-fPIC:clang -fPIC -c src/utils.c -o utils.o - 链接阶段用
-shared:clang -shared utils.o -o libutils.so - 不能跳过
.o直接从源码一步生成:clang -fPIC -shared src/utils.c -o libutils.so可行,但不推荐——调试和复用目标文件更灵活 - 如果混用 C++,记得加
extern "C"防名字修饰,否则 C 程序调用会undefined symbol
导出符号默认隐藏,不声明就不可见
Clang 默认把所有符号设为 hidden(尤其在 macOS/Linux),即使你写了函数,外部也看不到——nm -D libxxx.dylib 或 nm -D libxxx.so 查不到你的函数名。
- C 语言头文件中加宏控制可见性:
#define EXPORT __attribute__((visibility("default"))),然后声明EXPORT int add(int, int); - C++ 中要在实现前加
extern "C" { EXPORT int add(...); } - Windows 不需要这个,但要用
__declspec(dllexport);跨平台项目建议统一用宏封装 - 漏掉 visibility 设置,运行时会报
dlsym: symbol not found(动态加载场景)或链接时报undefined reference(静态链接场景)
iOS 动态库不能直接运行,必须签名+嵌入+配置权限
即使 clang -dynamiclib 成功生成了 .dylib,Xcode 项目里拖进去也大概率运行失败:iOS 系统强制要求动态库必须满足三项条件,缺一不可。
- 必须用 Apple Developer 证书签名:
codesign -s "Apple Development: xxx" --force --deep libMyLib.dylib - 必须作为
Embedded Binaries加入 target,不能只放Linked Frameworks and Libraries - App ID 必须开启
App Groups或Associated Domains(取决于用途),否则dlopen返回 NULL - 模拟器生成的 dylib 无法在真机运行,架构不匹配;务必用
-target arm64-apple-ios编译真机版
最容易被忽略的是符号 visibility 和 iOS 签名链——前者让函数“存在但不可见”,后者让 dylib “可见但被系统拒收”。这两步不出错,Clang 生成的动态库才算真正可用。

















