1. 十字工具链轮廓
1.什么是交叉工具链? 什么是交叉编译?
2.安装交叉工具链方法,结合环境变量PATH和工具链选项
3.Makefile的用法、Makefile的编写规则
4.嵌入式静态库/动态库制作,如何使用库?
2.什么是交叉工具链? 什么是交叉编译?
回顾一下编译过程
编译
高级语言(xxxx.c)------>目标程序(xxxx)
编译器:GCC
编译过程:预处理、编译、汇编、链接
gec@ubuntu:~$ which gcc --> gcc编译器本身也是一个linux命令
/usr/bin/gcc
gec@ubuntu:~$ man 1 gcc --> 查询gcc编译器选项及参数使用情况
GCC编译器特点: 在主机A上编译,在主机A上运行 --> GCC编译器也称为本地编译器。
乌班图 乌班图
什么是交叉编译?
无论是本地编译还是交叉编译,都是将高级语言变成目标程序的过程!
所谓交叉编译:在主机A上编译,在主机B上运行 --> 对应的编译器就是交叉编译器,也叫交叉工具链。
Ubuntu开发板
什么是交叉工具链?
纯净版的Linux系统没有交叉工具链,需要用户自行配置。
交叉工具链原材料:arm-2009q3.tar.bz2
3、如何配置交叉工具链?
首先将下载的工具链存放在Linux共享目录中,并切换到共享目录创建跨工具链安装包。
sudo mkdir /usr/arm —> 初始权限受超级用户umask影响
sudo chmod 777 /usr/arm 直接将工具链对应的安装包解压到安装路径。
tar jxvf arm-2009q3.tar.bz2 -C /usr/arm
结果:工具链路径为/usr/arm/arm-2009q3/bin/arm-none-linux-gnueabi-gcc
示例:交叉编译helloworld程序
本地编译命令:gcc umask.c -o umask
结果:
文件掩码:
umask: ELF 32位LSB可执行文件,Intel 80386 --> 该程序的运行平台
,版本 1 (SYSV),
交叉编译命令:/usr/arm/arm-2009q3/bin/arm-none-linux-gnueabi-gcc umask.c -o umask
结果:
文件掩码:
umask: ELF 32位LSB可执行文件,ARM --> 该程序的运行平台
,版本 1 (SYSV)交叉编译linux内核源码,
结论: 可执行程序的运行平台由谁来决定? --> 由编译器决定。
练习1:编写一个helloworld程序并交叉编译它!
练习 2:为工具链指定一个新名称“arm-linux-gcc”
sudo ln -s arm-none-linux-gnueabi-gcc arm-linux-gcc
别名arm-linux-gcc='arm-none-linux-gnueabi-gcc'
练习3:可以在任何时间、任何路径使用交叉工具链“arm-linux-gcc”
思路:如果想在任意路径下使用,方法就是将所在目录添加到PATH中。
arm-linux-gcc /usr/arm/arm-2009q3/bin
临时修改:export PATH=$PATH:/usr/arm/arm-2009q3/bin
永久修改:~/.bashrc
4.工具链版本号/位数/参数选项
查看工具链版本号
gec@ubuntu:~$arm-linux-gcc -v
gcc 版本 4.4.1 (Sourcery G++ Lite 2009q3-67) --> 当前版本 4.4.1
要在64位系统(18.04/16.04)上安装32位工具链,还必须安装32位兼容包
命令: sudo apt-get install libc6:i386
安装完成后,工具链即可正常使用。
常用选项
-E:预处理
-S:编译
-c:组装
-v:查看版本号
-o filename:指定编译后的程序名称
-I include_path:告诉编译器指定头文件的路径
-L lib_path:告诉编译器指定库文件的路径
5.Makefile项目管理文件
makefile 的含义是什么?
Makefile 在项目源代码项目中被称为“项目管理文件”。 makefile内部会有一组用户自定义的规则,makefile执行时会按照makefile的规则进行处理。
什么时候使用makefile? 有必要写makefile吗?
当一个工程有很多文件(.c源程序文件、.h头文件、.so库文件)时,编译命令会变得非常复杂,一般使用makefile来提高编译效率。
makefile 不一定存在于项目源代码中!
项目构成
源程序文件main.c --> 包含main函数的.c文件
函数程序文件 fun.c --> 不包含 main 函数的 .c 文件
头文件head.h --> 函数程序文件function的声明文件
库文件libxxxx.so --> 封装功能程序文件的文件
项目管理文件makefile --> 用于编译整个项目代码的文件
程序写好后,用户可以自行编译:gcc main.c fun.c -o main
任务:学习makefile,让makefile帮我们处理“gcc main.c fun.c -o main”
6.Makefile编写规则
makefile的核心:依赖关系和目标
依赖:一般指.c文件main.c fun.c
Target:最终要获取的文件,一般指可执行程序main
Makefile的编写规则
1)确定“依赖”和“目标”是谁?
2)按照以下格式编写makefile:
Target:依赖(如果有多个依赖,各个依赖文件用空格分隔)
编译规则
注意:
1)。 不等于“四个空格”。 编译规则之所以能运行,是因为Tab键。
2)。 常用变量:
$^:代表相当于“main.c fun.c”的所有依赖项
$@:代表相当于“main”的目标
makefile 的 helloworld 版本
target: --> 依赖文件可以不写,但是target一定要写。
echo “helloworld” --> 用户编写的规则。 当执行make时,就会执行这组规则。
结果:
echo “helloworld” --> 默认情况下,会复制编译规则
你好世界
目标:
@echo “helloworld” --> 在规则后面添加@,结果中不会输出编译命令
结果:
你好世界
练习时间: 写一个makefile,实现编译出main
确定“依赖”和“目标”是谁?
依赖项: main.c fun.c
目标:主要
回答:
主要:main.c fun.c
海湾合作委员会 $^ -o $@
再次执行make
gec@ubuntu:/mnt/hgfs/GZ1917/03 交叉工具链/project$ make
make:“main”是最新的。 --> 如果makefile检测到源程序文件与上次相同,则不会编译!
一个makefile可以有多个目标,make时可以指定执行某个目标的规则。
gec@ubuntu:/mnt/hgfs/GZ1917/03 交叉工具链/project$ make main --> 指定main目标对应的规则。
gec@ubuntu:/mnt/hgfs/GZ1917/03 cross tool chain/project$ make --> 默认执行makefile的第一个目标
例子:
主要:main.c fun.c
海湾合作委员会 $^ -o $@
干净的:
rm 主
当执行“make clean”时,只会执行clean的规则,而忽略main的规则。
7. makefile的变量类型
自定义变量—>默认为字符串类型
规则:
1)只能由数字、字母、下划线组成
2) 区分大小写
3)#=不能出现
4)给出变量参数时,等号两边可以有空格,但是shell编程中给出环境变量参数时,等号两边不能有空格!
5)引用变量时交叉编译linux内核源码,只需在变量后面添加$,或者添加括号将变量括起来。 $A $(A)
6) 赋值中的“”可以省略
例子:
A = 你好相当于 A = “你好”
一个=你好
B=世界
C = $A $(B)
例子:
C_SOURCE=main.c fun.c
主要:$(C_SOURCE)
海湾合作委员会 $^ -o $@
干净的:
rm 主
系统预设变量
有些变量已经在系统中定义了,不需要我们用户再次定义。 常用变量
CC:编译器名称,默认为cc cc相当于gcc
RM:删除内容变量,默认为rm -f
例子:
C_SOURCE=main.c fun.c
CC=arm-linux-gcc
主要:$(C_SOURCE)
$(CC) $^ -o $@
干净的:
$(RM) 主要
自动化变量 --> 变量的值不是固定的,而是变化的!
$^:代表所有依赖
$@:代表目标
8.Makefile指令
假设makefile有一个目标规则:clean:
$(RM) 主要
当我们执行make clean时,就会执行这组规则。 如果当前有一个名为 clean 的文件,
然后执行make clean时会提示:make: `clean' is up to date。
解决方案:在指令中添加 clean 关键字
添加代码:
.PHONY:干净
例子:
.PHONY:干净
干净的:
$(RM) 主要
例子:
C_SOURCE=main.c fun.c
CC=arm-linux-gcc
主要:$(C_SOURCE)
$(CC) $^ -o $@
.PHONY:干净
干净的:
$(RM) 主要
=============================================== Makefile ==== =======================================
1.什么是Makefile
什么是 makefile? 也许很多Winodws程序员不知道这个东西,因为这些Windows IDE已经帮你做了这个工作。
但我认为,要成为一名优秀的专业程序员,还是需要了解makefile。 就好像现在有很多 HTML 编辑器一样。
但如果你想成为专业人士,尤其是在Unix下编译软件时,你就必须编写自己的makefile。
会不会写makefile从一个侧面体现了一个人是否有能力完成小项目。 因为makefile关系到整个项目的编译规则。
项目中的源文件不计算在内。 它们根据类型、功能和模块被放置在几个目录中。 makefile 定义了一系列规则来指定哪些文件需要首先编译。
哪些文件需要后编译,哪些文件需要重新编译,甚至是更复杂的功能操作,因为makefile就像一个Shell脚本。
也可以执行操作系统命令。 makefile的好处是——“自动编译”。 一旦写入,只需要一个make命令。
整个项目完全手动编译,大大提高了软件开发的效率。 Make是一个命令工具,它解释makefile中的指令。
一般来说,大多数IDE都有这个命令,比如Delphi的make、Visual C++的nmake、Linux下GNU的make。 可见makefile已经成为工程中的一种编译方法。
2. 关于程序的编译和链接
在这里,我想多谈谈程序编译的一些规范和技巧。 一般来说,无论是C、C++还是pas,首先都要将源文件编译成中间代码文件。
在Windows下是.obj文件,在UNIX下是.o文件,即Object File。 这个动作称为编译。 然后大量的Object Files被合成为可执行文件。 此操作称为链接。
编译时,编译器需要正确的句型以及正确的函数和变量声明。 对于前者,通常需要告诉编译器头文件的位置(头文件应该只是声明,定义应该放在C/C++文件中),
只要所有句型都正确,编译器就可以编译出中间目标文件。 一般来说,每个源文件应该对应一个中间目标文件(O文件或OBJ文件)。
链接时主要链接函数和全局变量,因此我们可以使用这个中间目标文件(O文件或OBJ文件)来链接我们的应用程序。
链接器不关心函数所在的源文件,只关心函数的中间目标文件(Object File)。 很多时候,因为源文件太多,编译生成的中间目标文件也太多,链接时需要明确强调这一点。 中间目标文件名,
3.Makefile的使用
1)规则,格式如下:
目标:依赖性
状况
Target:是目标file.o文件,也可以是可执行文件。 也可以是标签(Label)
依赖:生成该类目标所需的文件或目标。
条件:即make需要执行的命令。 (任意 shell 命令)
示例如下:
目标:main.c
gcc main.c -o 目标
注意:
如果目标文件比依赖文件新,则不会编译。
如果依赖文件比目标文件新,则编译它
如果目标文件不存在也会编译
2)变量—>v4
自定义变量—>不要将其视为C变量
自动变量
cc —>默认为gcc
$< -->依赖列表中的第一个
$^ -->所有依赖项
$@ -->所有目标,但我们最终的希望是:一个目标,多个依赖! ! ! !
% —》自动匹配,相当于Linux下的键值 * *.c
3)功能
通配符
帕特萨斯特
文件名可以写成makefile或者Makefile
也可以写成其他名称,如:abc —> 编译命令:make -f abc