apt源arm gcc交叉编译器注意事项
Contents
做嵌入式 Linux 开发时候都需要使用交叉编译工具,这些一般是方案厂商提供,但我们通常也可以使用那些打包好的通用交叉编译工具,比如 Debian 上 apt 也有打包好的 arm 交叉编译工具: gcc-arm-linux-gnueabi
和 gcc-arm-linux-gnueabihf
,对应 c++ 版本以 g++ 开头,这两类主要区别在于 CPU 对于浮点的处理上,涉及到 armel
和 armhf
架构的区别,详情参照这里,你只需要选择对应开发板的架构工具即可。
由于是 Debian 自己维护更新的包,上述的两个交叉编译工具通常都会更新比较频繁,会支持最新的标准和特性,但是我们的开发板上系统通常都不是最新的,所以在使用时需要注意,否则会出现编译后的程序无法在开发板上运行。
最近在将 mruby 应用到嵌入式环境时就遇到这个问题。
问题和溯因
将静态链接了 mruby
库的测试程序 mirb 放入嵌入式环境上运行时,提示
|
|
嵌入式环境没有 2.16 版本以上的 glibc 库,但是理论上测试程序不需要这么高版本的 glibc 库。在嵌入式命令行上用 ldd
(有些嵌入式环境可能没有附带这个工具)查看一下可执行文件信息:
|
|
可执行程序 mirb 的确引用 2.16 版本的 glibc 库,那就继续查一下引用了 2.16 版本 glibc 库的哪些符号。
在开发主机(不需要在嵌入式主机中)上可以使用 objdump 工具查看可执行程序的符号表(参数 -t
):
|
|
可以看出是 timespec_get
这个函数符号需要 2.16 版本的 glibc 库,那么就得在代码中查一下哪个地方调用了这个函数。
在这里 可以看出 mruby
源码的 time.c
文件中使用了 timespec_get
函数:
|
|
宏定义 TIME_UTC
控制着代码是否调用 timespec_get
函数。
通过搜索了解到,TIME_UTC
和 timespec_get
都是 C11 标准里定义的。由于在编译 mruby
时没有指定编译参数,交叉编译工具使用了默认参数导致 C11 标准也被支持,mruby
库也就使用了最新的 C11 标准,引用了新函数 timespec_get
,产生了 glibc 2.16 版本的依赖。
解决方法
在知晓原因后,解决方法就简单了。就是在交叉编译 mruby
库时,去指定编译标准(c标准),修改 mruby
的编译配置文件 build_config.rb
:
|
|
将编译 c 标准指定为 gnu99(-std=gnu99
),这里也可以使用 c99 标准(-std=c99
)。
然后重新编译测试程序,放到嵌入式环境上运行,OK。
结语
使用编译器尤其是交叉编译器时,最好要指定编译参数,确定编译标准,否则目标平台可能不支持,导致程序无法运行。在向第三方提供开发库而不是源码的情况下, 需要特别注意,尽量使用统一的编译参数标准,推荐 c99 或者 gnu99。
在遇到类似 /lib/libc.so.6: version GLIBC_X.XX not found
问题时,可以借助 ldd
和 objdump
工具来确定依赖的符号源,寻找解决方法。