Linux库创建和编译
安装交叉编译环境
更新源
sudo apt-get update
安装32位库
sudo apt-get install lib32ncurses5 lib32z1
准备环境(非必需)
sudo apt-get install bison flex texinfo automake libtool patch curl gawk gperf
其中:
bison和flex是用来生成语法和词法分析器;
texinfo和man类似,用来读取帮助文档;
automake是帮助生成Makefile的工具;
libtool帮助在编译过程中处理库的依赖关系,自动搜索路径;
curl通过给定的网络地址下载源码的工具;
patch是用于给源码打补丁的工具;
gawk是linux下用于文本处理和模式匹配的工具
访问网站http://www.gnu.org获取其他软件
命令行安装交叉编译
sudo apt-get install gcc-arm-linux-gnueabihf
sudo apt-get install gcc-aarch64-linux-gnu
手工安装交叉编译
下载交叉编译工具到Linux系统下
1、从https://www.linaro.org网站中选择gcc-arm-linux-gnueabi
2、从https://www.mentor.com网站中下载gcc-arm-none-linux-gnueabi
3、从ARM官网https://developer.arm.com网站中下载arm-linux-gcc
注意:
- IEEE 754标志规定了计算机程序设计环境中的二进制和十进制的浮点数的交换、算术格式以及方法
- X86的FPU自带一个由8个80位寄存器ST(0) ~ ST(7)构成的循环栈,指令主要有:FLD、FSTP、FDIV、FDIVP、FDIVR、FMUL、FADDP、FCOMP、FXCH、FUCOMPP、FNSTSW
- 在ARM系统里,FPU仿真处理叫做“软浮点/soft float”或者“armel”,而通过硬件实现的FPU指令叫做“硬浮点/hard float”或者“armhf”
- ARM平台有32个64位的D字头寄存器,用于存储(双精度)浮点数,又可以用于单指令多数据流运算SIMD(ARM平台叫做NEON)
- ARM平台还有32个32位的S字头寄存器,用于处理单精度浮点数据
命名规则
交叉编译工具链的命名规则为:arch [-vendor] [-os] [-(gnu)eabi]
arch – 体系架构,如ARM,MIPS
vendor – 工具链提供商
os – 目标操作系统
eabi – 嵌入式应用二进制接口(Embedded Application Binary Interface)
解压
tar xvzf arm-linux-gcc-4.3.2.tgz
设置环境变量
vim /etc/bash.bashrc
在bash.bashrc文件尾添加交叉编译工具bin路径,如:
export PATH=$PATH:/usr/local/arm/arm-linux-gcc-4.3.2/bin
- /etc/profile 此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行,并从/etc/profile.d目录的配置文件中搜集shell的设置
- /etc/bash.bashrc 为每一个运行bash shell的用户执行此文件,当bash shell被打开时,该文件被读取
- ~/.bash_profile 每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次,默认情况下,设置一些环境变量,执行用户的.bashrc文件,是交互式、login 方式进入 bash 运行的
- ~/.bashrc 该文件包含专用于你的bash shell的bash信息,当登录时以及每次打开新的shell时,该文件被读取,是交互式 non-login 方式进入 bash 运行的
- ~/.bash_logout 当每次退出系统(退出bash shell)时,执行该文件。
另外,/etc/profile中设定的变量(全局)的可以作用于任何用户,而~/.bashrc等中设定的变量(局部)只能继承/etc/profile中的变量,他们是"父子"关系
环境生效
source /etc/bash.bashrc
验证交叉环境
命令行安装
arm-linux-gnueabi-gcc -v
手工安装
arm-linux-gcc -v
创建静态库
ar命令
1、在Linux环境中,使用ar命令创建静态库文件,ar命令创建可供编译器读取的函数目标文件的存档文件。
ar命令格式:
ar [-] (dmpqrtx) [abcfilNoPsSuvV] [membername] [count] archive files…
参数archive定义库的名称,files是库文件中包含的目标文件的清单,用空格分隔每个文件。
选项 | 描述 |
---|---|
d | 从存档文件中删除文件 |
m | 把文件移动到存档文件中 |
p | 把存档文件中的指定的文件输出到标准输出 |
q | 快速地把文件追加到存档文件中 |
r | 把文件插入(替换)到存档文件中 |
t | 显示存档文件中文件的列表 |
x | 从存档文件提取文件 |
2、可以使用一个或多个修饰符修改基本选项,如表所示:
修饰符 | 描述 |
---|---|
a | 把新的文件添加到存档文件中现有的文件之后 |
b | 把新的文件添加到存档文件中现有的文件之前 |
c | 创建新的存档文件 |
f | 截短存档文件中的名称 |
i | 在存档文件中现有文件之前插入新的文件 |
P | 在存档文件中使用文件的完整路径名称 |
s | 编写存档文件的索引 |
u | 更新存档文件中的文件(使用新文件替换旧的) |
v | 使用详细模式 |
创建静态库文件
1、Linux操作系统使用如下约定:
libxxx.a
其中xxx是库的名称,扩展名a标识这个文件是静态库文件。
2、使用ar命令之前,必须具有包含到库中的每个函数的目标文件。
案例:
$ ar -r libchap14.a square.o cpuidfunc.o areafunc.o greater.o fpmathfunc.o
3、ar命令没有输出结果,只是创建库文件,可以使用命令行选项t显示包含在库中的文件
$ar t libchap14.a
cpuid.o
square.o
area.o
cpuidfunc.0
areafunc.0
greater.o
fpmathfunc.o
4、如果希望得到库文件更加详细的清单,可以使用v选项
$ar tv libchap14.a
5、创建库文件之后,可以创建库的索引提高与库链接的其他程序的编译速度。使用ranlib程序创建库的索引,索引存放在库文件内部。
$ranlib libchap14.a
6、使用nm程序显示库文件的索引,nm程序用于显示目标文件的符号
$nm -s libchap14.a | more
编译静态库
创建好静态库文件之后,可以使用它编译需要库中包含任何函数的C程序
$gcc -o stringtest stringtest.c libchap14.a
创建共享库
包含函数目标代码的单独文件被加载到操作系统的通用区域中,当应用程序需要访问共享库中的函数时,操作系统自动把函数代码加载到内存中,并且允许应用程序访问它;如果另一个应用程序也需要使用此函数代码,操作系统允许它访问已经被加载到内存中的相同的函数代码,只有函数代码的一个拷贝被加载到内存中,并且使用此函数代码的每个独立程序不需要把它加载到它们的内存空间中,或者它们的可执行文件中。
gcc命令
1、在创建共享库之前,必须使用as对汇编语言函数进行汇编,Linux具有用于共享库的命名约定:
libxxx.so
其中xxx时库的名称,扩展名so表明时共享库
2、用于创建共享库的gcc命令行选项时-shared选项
案例:
$gcc -shared -o libchap14.so square.o cpuidfunc.o areafunc.o greater.o fpmathfunc.o
文件libchap14.so包含被导入的汇编函数的所有目标代码,为了标识版本信息,通常文件名追加版本号,rulibchap14.so.1,与静态库不同,共享库中的目标代码不被编译到可执行程序中。
编译共享库
1、使用-l选项加上共享库的名称(减去lib部分和.so扩展名),在编译器命令行上导入共享库;使用-L选项通知编译器在哪里可以查找共享库,如果共享库位于和程序文件相同的目录中,可以使用句号表示相同的目录。
$gcc -o inttest -L. -lchap14 intest.c
2、在对链接共享库的可执行文件进行反汇编后,在反汇编文件中的任何位置都找不到共享库函数的代码,被调用的时Linux动态加载器,动态加载器用于在运行时加载必须的共享库以便提供所需的函数。
3、查看可执行文件依赖共享库,使用ldd命令
$ldd inttest
运行使用共享库的程序
1、动态加载器必须知道如何访问共享库,其中两种方式如下:
- LD_LIBRARY_PATH环境变量
- /ets/ld.so.conf文件
(1)LD_LIBRARY_PATH环境变量时系统上的任何用户为当前进程的动态加载器添加路径的简单方式,包含一个路径清单(以冒号:分隔),动态加载器应该在ld.so.conf文件中列出的路径之外的这些位置查找库文件。使用LD_LIBRARY_PATH环境变量不需要任何专门权限:
$export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:."
(2)文件ld.so.conf位于/etc目录下,保存动态加载器查找库的目录清单。
$cat /etc/ld.so.conf
为了不把系统库和应用程序库混合,可以把应用程序共享库存储在/usr/local/lib目录下,也可以在/usr/local/lib创建单独的子目录,并且把必须的应用程序库文件存储其中。把新的目录添加到文件ld.so.conf之后,必须(以root用户身份)运行ldconfig命令,以便更新文件ld.so.cache。
$ldconfig
$ldd inttest