GNU/Linux - GCC编译的静态库

使用gcc编译出的静态库文件,后缀名是".a"。

使用二进制格式打开的话,开头内容是:

二进制:

21 3C 61 72 63 68 3E 0A 2F 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20

31 37 36 30 35 39 36 39 39 34 20 20 30 20 20 20 20 20 30 20 20 20 20 20

字符:

!<arch>

/               1760596994  0     0    

!<arch>是 Unix/Linux 下的归档文件(archive file)的魔数(magic number),表示该文件是一个 ar(archive)格式的文件。

*静态库文件(如 .a文件)本质上就是一种 ar 归档文件,它里面打包了一个或多个目标文件(.o文件)。

*所以当你使用 ar工具去创建或查看 .a文件时,它遵循 ar 格式规范。

*文件开头固定为字符串:!<arch>\n(注意后面有一个换行符),用来标识这是一个 ar 格式的归档文件。

第二行是一个时间戳。在其他地方,尤其是 .o 文件名后面,也会有一个时间戳,表明文件的更新时间。

开头的时间是最新的,表示此ar文件的创建时间。其他的 .o 文件,就应该是编译时的时间。

所以,即使代码都是一样,编译的.o文件一样,但打包成.a文件后,由于时间戳不一样,生成的库文件二进制比较还是不同。

要查看这个时间戳对应的具体时间,可以在Linux终端中输入:

date -d @1760596994

Thu Oct 16 14:43:14 CST 2025

date -d @0

Thu Jan  1 08:00:00 CST 1970

你遇到的错误是典型的 **链接器(linker)错误**,发生在使用 **交叉编译工具链**(`aarch64-none-linux-gnu-gcc`)编译 C 程序时: ``` undefined reference to `fmod' undefined reference to `round' ``` 这表示:你的代码调用了数学函数 `fmod()` 和 `round()`,但链接器找不到它们的实现。 --- ### 🔍 错误原因分析 在大多数标准 GCC 工具链中,数学函数(如 `sin`, `cos`, `fmod`, `round` 等)位于独立的数学库 `libm.a` 或 `libm.so` 中,**不会自动链接**。即使你在代码中包含了 `<math.h>`,你也必须**显式地告诉链接器要链接数学库 `-lm`**。 而你使用的交叉编译器: ``` aarch64-none-linux-gnu-gcc ``` 虽然语法兼容 GNU GCC,但它仍然遵循“不自动链接 libm”的规则。 --- ### ✅ 解决方案:添加 `-lm` 链接选项 你需要在编译命令中 **显式加上 `-lm`**,将数学库链接进来。 #### ✅ 正确的编译命令: ```bash /opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc \ main.c -o main -lcjson -lm ``` > ⚠️ 注意:`-lm` 必须放在源文件 **之后**,且通常放在最后。顺序很重要! --- ### 📌 为什么 `-lm` 能解决? - `-lm` 告诉链接器去链接目标平台的数学库(`libm`)。 - `fmod(x, y)` → 浮点取模函数,定义在 `libm` - `round(x)` → 四舍五入到整数,也定义在 `libm` 这些函数不是 C 标准库(libc)的一部分,而是 **数学库(libm)** 的一部分。 --- ### 💡 补充建议:确保 `libcjson` 也已正确交叉编译 你现在能链接 `-lcjson`,说明你已经为 `aarch64` 平台编译好了 cJSON 库,并安装到了交叉编译环境的库路径中。 如果没有,请自行交叉编译 cJSON: #### 示例步骤(简略): ```bash git clone https://github.com/DaveGamble/cJSON.git cd cJSON mkdir build && cd build # 使用你的交叉编译器 cmake .. \ -DCMAKE_C_COMPILER=/opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc \ -DCMAKE_INSTALL_PREFIX=./install \ -DBUILD_SHARED_LIBS=OFF make && make install ``` 然后编译主程序时指定头文件和库路径: ```bash /opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc \ main.c \ -I./cJSON/install/include \ -L./cJSON/install/lib \ -lcjson -lm -o main ``` --- ### ✅ 修改后的 `wrap_double` 和 `round` 使用技巧(可选优化) 如果你担心某些嵌入式系统 `libm` 不完整,可以用替代方式避免 `round` 和 `fmod`: #### 替代版本(适用于简单场景): ```c // 替代 fmod(a, b),仅支持正数范围 double my_fmod(double a, double b) { while (a >= b) a -= b; while (a < 0) a += b; return a; } // 替代 round() double my_round(double x) { return x >= 0 ? (long)(x + 0.5) : (long)(x - 0.5); } ``` 然后替换原函数调用: ```c // 替换: // fmod(value - min, range) // 改为: // my_fmod(value - min, range) // 替换: // round(x * 1e6) / 1e6 // 改为: // my_round(x * 1e6) / 1e6 ``` 这样可以做到 **不依赖 libm**,适合资源受限的嵌入式系统。 --- ### ✅ 总结:解决问题的关键 | 问题 | 解决方法 | |------|----------| | `undefined reference to 'fmod'` | 添加 `-lm` | | `undefined reference to 'round'` | 添加 `-lm` | | 编译通过但运行出错? | 确保目标设备也有对应库(静态链接更安全) | | 想去掉对 libm 的依赖? | 使用自定义 `my_fmod` / `my_round` | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜流冰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值