编译器与目标¶
支持矩阵¶
compiler |
编译命令 | 静态库 | 共享库 | 可执行程序 |
|---|---|---|---|---|
gxx |
gcc(.c)/ g++(其余) |
ar |
g++ -shared |
g++ -s |
llvm |
clang |
ar |
clang++ -shared(未验证) |
clang++ -s(未验证) |
msvc |
cl |
ar |
未实现,直接报错退出 | 未实现,直接报错退出 |
编译命令按源文件后缀选择:.c 走 C 编译器,.cc / .cpp 走 C++ 编译器。
为什么共享库与可执行程序要经编译器驱动链接
早期版本直接调用 ld -shared,这样生成的共享库不会带上 libstdc++ 等运行时依赖,用 dlopen 或纯 C 宿主加载时会因为未定义的 C++ 符号失败。现在统一走编译器驱动,由它带上 crt 与调用方的运行库。
目标类型¶
target_type |
生成物 | 链接命令要点 |
|---|---|---|
static |
lib<项目名>.a |
ar csr,构建后自动 strip --strip-unneeded |
shared |
lib<项目名>.so |
-shared -o,并显式链 -lm |
exe |
<项目名> |
-s,并带上 compile_args 与你配置的链接参数 |
共享库注意事项¶
编译参数里需要 -fPIC,否则目标文件不能进共享库。antel init 生成的模板已经包含这一项,工具不会再自动追加:
链接参数里以 -l 开头的项(如 -lpthread)会被识别为系统库:
版本化共享库¶
给共享库一个版本号,antel 会产出 libX.so.<版本>(如 libX.so.1.0.0)并自动生成软链 libX.so.1 与 libX.so,链接命令带上 -Wl,-soname:
{
"target_type": "shared",
"version": "1.0.0",
"soname": "libX.so.1", // 可选,缺省由 version 主版本推导
"rpath": ["$ORIGIN/lib"] // 可选,消费端运行期到哪找库
}
消费端按 SONAME 链接与加载(rpath 的 $ORIGIN 运行期展开为可执行文件目录,拷走整个输出目录树也能跑):
验证:readelf -d 显示 SONAME、ldd 按 SONAME 而非文件名解析即可。完整示例见示例与效果图的 antelstats。
换编译器¶
同一个项目想用不同编译器构建,用不同的配置文件即可,两者输出目录互不干扰:
antel rebuild -f gcc # 读取 gcc.json,输出到 <项目名>_gcc/
antel rebuild -f clang # 读取 clang.json,输出到 <项目名>_clang/
常见问题¶
报错 命令执行失败(退出码 127) ... 命令不存在或不可执行:cl
说明用到了 msvc,但当前环境没有 cl(或该编译器的链接路径尚未实现)。在 Linux 上用 gxx 或 llvm。
链接时报未定义符号
先看 log/linkInfor,那里有链接器的完整输出。C++ 项目常见原因是源文件被当成 C 编译(后缀写成了 .c),或者缺少 -l 形式的链接参数。
生成的可执行程序体积不对
exe 目标链接时带 -s,会去掉符号表;静态库构建后会 strip --strip-unneeded。需要保留调试符号时,把 -g 加进 compile_args 并自行去掉这些裁剪手段。