C语言开发项目往往需要标准c库的支持,它是一组一般用户常用的程序集。C库函数极大地方便了用户,同时也补充了c语言本身的不足,使用库函数,既可以提高程序的运行效率,也可以提高编程的质量。
作为一个C语言编译器,是需要支持C标准库的。同时,C库的实现也是与操作系统相关的,不同的操作系统,其实现是有差异的。笔者此处就arm交叉编译工具裸机newlib的构建作一个简单的介绍,使之既能支持Linux应用开发,又能支持标准裸机开发

1、newlib概述

newlib是一个面向嵌入式系统的C库,目前由Red Hat维护。newlib相对常用于Linux的C库glibc,其实现了大部分的功能函数,但体积却小很多。尤其是newlib独特的体系结构,具体实现与操作系统分层,使之能够很好地进行配置,满足深度嵌入式系统的要求。由于专为嵌入式系统设计,newlib具有可移植性强、轻量级、速度快、功能完备等特点,已广泛应用于各种嵌入式系统中。

2、newlib构建

笔者的arm交叉编译工具链已经带有glibc,用于Linux的应用开发,但这个c库是无法用在裸机开发的,因为裸机没有Linux的实现。因此,主要是构建基于裸机的newlib,使工具链既能支持Linux应用开发,又能支持标准裸机开发。

newlib已经对arm有很好地支持了,因此不需要移植,直接进行编译即可。不同的配置选项,可以实现生成更小的c库,用于资源极度紧张的mcu应用。在编译裸机newlib时,必须已构架好交叉编译工具链,通常裸机newlib用arm-none-eabi裸机交叉编译工具链编译,可直接通过Linux应用交叉编译工具链的软链接来编译裸机。
在工具链目录下,执行如下的链接脚本即可(实现将arm-2014.05/bin目录下的各个工具生成一个对应的arm-none-eabi-开头的,实际上在第一节已经生成过了^_^):

#!/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目录。

SofTool.CN Notes:
newlib下载地址: https://sourceware.org/ftp/newlib/index.html

2.2 配置

newlib 必须先进行配置才能生成 makefile ,主要是配置目标应用、安装目录、编译选项等。
此处以配置s3c2416的裸机c库为例进行说明:

//配置:
./configure --targe=arm-none-eabi --prefix=/home/arm/SoftWareBackUp/newlib-2.2.0.20150924/build --with-newlib --enable-newlib-io-long-long --enable-newlib-register-fini --disable-newlib-supplied-syscalls --disable-nls --disable-multilib CFLAGS_FOR_TARGET='-Os -march=armv5t -mfloat-abi=soft -marm -mabi=aapcs-linux -ffunction-sections -fdata-sections'

SofTool.CN Notes:
--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 编译

配置完后,在当前目录将生成makefile文件,在该目录make,即可进行编译newlib,因为各个版本交叉编译工具链编译选项等的差异,可能编译出错,根据出错信息进行更正即可

SofTool.CN Notes:我遇到的错误
1、make时出错
make时出错:
make[3]: 正在进入目录 `/home/arm/SoftWareBackUp/newlib-2.2.0.20150924/etc'
/home/arm/SoftWareBackUp/newlib-2.2.0.20150924/missing makeinfo --split-size=5000000 --split-size=5000000 --no-split -I. -o standards.info ./standards.texi
WARNING: `makeinfo' is missing on your system.  You should only need it if
         you modified a `.texi' or `.texinfo' file, or any other file
         indirectly affecting the aspect of the manual.  The spurious
         call might also be the consequence of using a buggy `make' (AIX,
         DU, IRIX).  You might want to install the `Texinfo' package or
         the `GNU make' package.  Grab either from any GNU archive site.
make[3]: *** [standards.info] 错误 1
make[3]:正在离开目录 `/home/arm/SoftWareBackUp/newlib-2.2.0.20150924/etc'
make[2]: *** [info] 错误 1
make[2]:正在离开目录 `/home/arm/SoftWareBackUp/newlib-2.2.0.20150924/etc'
make[1]: *** [all-etc] 错误 2
make[1]:正在离开目录 `/home/arm/SoftWareBackUp/newlib-2.2.0.20150924'
make: *** [all] 错误 2
root@EU:/home/arm/SoftWareBackUp/newlib-2.2.0.20150924# apt-get install makeinfo正在读取软件包列表... 完成
正在分析软件包的依赖关系树       
正在读取状态信息... 完成       
E: 未发现软件包 makeinfo

解决办法:安装texinfo

root@EU:/home/arm/SoftWareBackUp/newlib-2.2.0.20150924# apt-get install texinfo
正在读取软件包列表... 完成
正在分析软件包的依赖关系树       
正在读取状态信息... 完成       
下列软件包是自动安装的并且现在不需要了:
  python-support language-pack-kde-en ipython language-pack-kde-zh-hans
  language-pack-kde-en-base kde-l10n-engb kde-l10n-zhcn python-simplegeneric
  python-decorator language-pack-kde-zh-hans-base
使用'apt-get autoremove'来卸载它们
建议安装的软件包:
  texlive-base texlive-latex-base texlive-generic-recommended
  texinfo-doc-nonfree
下列【新】软件包将被安装:
  texinfo
升级了 0 个软件包,新安装了 1 个软件包,要卸载 0 个软件包,有 324 个软件包未被升级。
需要下载 447 kB 的软件包。
解压缩后会消耗掉 1,192 kB 的额外空间。
获取:1 http://cn.archive.ubuntu.com/ubuntu/ precise/main texinfo i386 4.13a.dfsg.1-8ubuntu2 [447 kB]
下载 447 kB,耗时 5秒 (87.6 kB/s)
Selecting previously unselected package texinfo.
(正在读取数据库 ... 系统当前共安装有 167619 个文件和目录。)
正在解压缩 texinfo (从 .../texinfo_4.13a.dfsg.1-8ubuntu2_i386.deb) ...
正在处理用于 man-db 的触发器...
正在设置 texinfo (4.13a.dfsg.1-8ubuntu2) ...
root@EU:/home/arm/SoftWareBackUp/newlib-2.2.0.20150924# 

然后make clean,再重新configure,make 即可。

make clean

./configure --targe=arm-none-eabi --prefix=/home/arm/SoftWareBackUp/newlib-2.2.0.20150924/build --with-newlib --enable-newlib-io-long-long --enable-newlib-register-fini --disable-newlib-supplied-syscalls --disable-nls --disable-multilib CFLAGS_FOR_TARGET='-Os -march=armv5t -mfloat-abi=soft -marm -mabi=aapcs-linux -ffunction-sections -fdata-sections'

make

2.4 安装

编译完成后,执行make install,即可把编译好的newlib安装在build目录,build目录中包括include头文件目录以及lib目录。

make install

Eastar Notes:
我安装之后就可以在build目录看到以下2个文件夹了:

02_构建标准C库newlib - 图1


其中 arm-none-eabi 是我们需要重点关注的。

3、newlib使用

newlib安装后,会生成一个库对应的头文件目录和相应的静态库,其中库头文件声明对于标准c库均是一致的,可以直接使用交叉编译工具链默认的c库头文件。

SofTool.CN Notes:
头文件目录 指 arm-none-eabi/include
静态库 指 arm-none-eabi/lib

我们主要从newlib中提取出libc.a、libm.a、libnosys.a这三个库以供我们使用^_^。
在开发项目时,修改默认的C库路径,使之链接newlib即可
libnosys.a由源码目录下\libgloss\libnosys源代码实现,为newlib操作系统接口层,基本为空实现,避免使用一些C库函数时的链接失败。在实现一些io操作、文件操作、内存分配、时间产生等需要操作系统调用。如果应用程序中未访问这些与系统调用相关的C库函数,无需libnosys.a。

4、结语

newlib可移植性强,在嵌入式中,各种架构交叉编译工具链也往往选newlib作为裸机开发的C库。作为开源的c库,可以实现在c库中进行跟踪调试,这是其它编译器(如MDK、IAR等)所不及的。