构建标准c库newlib象棋小子 1048272975
C语言开发项目往往需要标准c库的支持,它是一组一般用户常用的程序集。C库函数极大地方便了用户,同时也补充了c语言本身的不足,使用库函数,既可以提高程序的运行效率,也可以提高编程的质量。作为一个c编译器,是需要支持c标准库的,同时,c库的实现也是与操作系统相关的,不同的操作系统,其实现是有差异的。笔者此处就arm交叉编译工具裸机newlib的构建作一个简单的介绍,使之既能支持linux应用开发,又能支持标准裸机开发。
1. newlib概述newlib是一个面向嵌入式系统的c库,目前由Red Hat维护。相对常用于linux的c库glibc,其实现了大部分的功能函数,但体积却小很多。尤其是newlib独特的体系结构,具体实现与操作系统分层,使之能够很好地进行配置,满足深度嵌入式系统的要求。由于专为嵌入式系统设计,newlib具有可移植性强、轻量级、速度快、功能完备等特点,已广泛应用于各种嵌入式系统中。
2. newlib构建笔者的arm交叉编译工具链已经带有glibc,用于linux的应用开发,但这个c库是无法用在裸机开发的,因为裸机未有linux的实现。因此,主要是构建基于裸机的newlib,使工具链既能支持linux应用开发,又能支持标准裸机开发。
newlib已经对arm有很好地支持了,因此不需要移植,直接进行编译即可。不同的配置选项,可以实现生成更小的c库,用于资源极度紧张的mcu应用。在编译裸机newlib时,必须已构架好交叉编译工具链,通常裸机newlib用arm-none-eabi裸机交叉编译工具链编译,可直接通过linux应用交叉编译工具链的软链接来编译裸机。在工具链目录下,执行如下的链接脚本即可。
#!/bin/bash
for file in $(ls arm-none-linux-gnueabi*)
do
ln -s $file arm-none-eabi${file#arm-none-linux-gnueabi}
done
2.1. 下载源码从newlib官网下载最新的源码并解压,笔者此处以newlib-2.2.0.20150924为例,在newlib源码目录下创建build目录,这个目录用来存放newlib配置文件以及作为安装路径。打开shell终端,cd进入到build目录。
2.2. 配置newlib必须先进行配置才能生成makefile,主要是配置目标应用、安装目录、编译选项等。此处以配置s3c2416的裸机c库为例进行说明。
../configure--targe=arm-none-eabi --prefix=/root/桌面/newlib-2.2.0.20150924/build --with-newlib--enable-newlib-io-long-long --enable-newlib-register-fini--disable-newlib-supplied-syscalls --disable-nls --disable-mul
tilibCFLAGS_FOR_TARGET='-Os -march=armv5t -mfloat-abi=soft -marm -mabi=aapcs-linux -ffunction-sections-fdata-sections'
--targe=arm-none-eabi,newlib从targe选项解析出目标配置为arm架构,无操作系统,加入相应的newlib编译目录。
--prefix,为newlib的配置安装目录
其中比较重要的编译选项变量CFLAGS_FOR_TARGET,采用Os优化,s3c2416为armv5t指令集,并且没有硬件除法、浮点,必须采用软浮点,如果配置s5pv210的库,应配置成armv7-a指令,采用硬浮点。库采用arm模式编译,二进制接口采用aapcs-linux。
可加入其它的配置参数,使生成的newlib库更微小,适应于cortex-m0等
单片机应用方案中,相关的配置选项,请查阅相关的newlib资料。
2.3. 编译配置完后,在build目录将生成makefile文件,在该目录make,即可进行编译newlib,因为各个版本交叉编译工具链编译选项等的差异,可能编译出错,根据出错信息进行更正即可。
2.4. 安装编译完成后,执行make install,即可把编译好的newlib安装在build目录,包括include头文件目录以及lib目录。
3. newlib使用newlib安装后,会生成一个库头文件目录以及相应的静态库,其中库头文件声明对于标准c库均是一致的,可以直接使用交叉编译工具链默认的c库头文件。主要从newlib中提取出libc.a、libm.a、libnosys.a这三个库。在开发项目时,修改默认的c库路径,使之链接newlib即可。libnosys.a由源码目录下libglosslibnosys源代码实现,为newlib操作系统接口层,基本为空实现,避免使用一些c库函数时的链接失败。在实现一些io操作、文件操作、内存分配、时间产生等需要操作系统调用。如果应用程序中未访问这些与系统调用相关的c库函数,无需libnosys.a。
4. 结语newlib可移植性强,在嵌入式中,各种架构交叉编译工具链也往往选newlib作为裸机开发的c库。作为开源的c库,可以实现在c库中进行跟踪调试,这是其它编译器(如mdk、iar等)所不及的。