Linux基础.交叉编译工具链,makefile

一. 交叉工具链大纲
1. 什么是交叉工具链?什么是交叉编译?
2. 安装交叉工具链方法,结合环境变量PATH,工具链选项
3. Makefile使用,Makefile书写规则
4. 嵌入式静态库/动态库制作,库是如何使用?

二. 什么是交叉工具链?什么是交叉编译?

  1. 回顾编译过程
    编译
    高级语言(xxxx.c) ------> 目标程序(xxxx)

编译器:GCC
编译过程: 预处理,编译,汇编,链接

gec@ubuntu:~$ which gcc --> gcc编译器本身也是一个linux命令
/usr/bin/gcc

gec@ubuntu:~$ man 1 gcc --> 查询gcc编译器选项以及参数用法

GCC编译器特点: 在主机A编译,在主机A运行 --> GCC编译器也叫本地编译器。
Ubuntu Ubuntu

  1. 什么是交叉编译?
    无论是本地编译,还是交叉编译,都是属于把高级语言变成目标程序过程!

所谓交叉编译: 在主机A编译,在主机B运行 --> 对应的编译器就是交叉编译器,也叫交叉工具链。
Ubuntu 开发板

  1. 什么是交叉工具链?
    一个纯净版linux系统没有交叉工具链,需要用户自己进行配置。
    交叉工具链原材料: arm-2009q3.tar.bz2

三. 如何配置交叉工具链?

  1. 先把下载好的工具链存放在linux共享目录下
  2. 切换到共享目录下
  3. 创建一个交叉工具链安装包
    sudo mkdir /usr/arm —> 起始权限受到超级用户umask的影响
    sudo chmod 777 /usr/arm
  4. 直接把工具链对应的安装包解压到安装路径下就可以
    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
结果:
file umask:
umask: ELF 32-bit LSB executable, Intel 80386 --> 该程序的运行平台
, version 1 (SYSV),

交叉编译命令: /usr/arm/arm-2009q3/bin/arm-none-linux-gnueabi-gcc umask.c -o umask

结果:
file umask:
umask: ELF 32-bit LSB executable, ARM --> 该程序的运行平台
, version 1 (SYSV),

结论: 可执行程序的运行平台由谁来决定?  --> 由编译器决定。

练习1: 写一个helloworld程序,交叉编译它!
练习2: 为工具链取新的名字 “arm-linux-gcc”
sudo ln -s arm-none-linux-gnueabi-gcc arm-linux-gcc
alias 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

四. 工具链版本号/位数/参数选项

  1. 查看工具链版本号
    gec@ubuntu:~$ arm-linux-gcc -v
    gcc version 4.4.1 (Sourcery G++ Lite 2009q3-67) --> 当前版本4.4.1

  2. 64位系统(18.04/16.04)安装32位工具链,还得安装32位兼容包
    命令: sudo apt-get install libc6:i386
    安装之后,工具链正常使用

  3. 常用选项
    -E: 预处理
    -S: 编译
    -c: 汇编
    -v: 查看版本号
    -o filename: 指定编译后的程序名字
    -I include_path: 告诉编译器,指定头文件的路径
    -L lib_path: 告诉编译器,指定库文件的路径

五. Makefile工程管理文件

  1. makefile的意义?
    makefile在一个项目源码工程中被称之为"工程管理文件"。makefile内部会有一套用户自己定义的规则,makefile在执行时就会按照makefile的规则进行处理。

  2. 什么时候使用到makefile?makefile是一定要写的吗?
    当工程的文件(.c源程序文件,.h头文件,.so库文件)较多时,就会导致编译命令非常复杂,一般都会选择使用makefile提高编译效率。
    makefile在一个项目源码中不一定是存在的!

  3. 工程组成
    源程序文件 main.c --> 包含main函数在内的.c文件
    功能程序文件 fun.c --> 不包含main函数在内的.c文件
    头文件 head.h --> 对功能程序文件函数的声明文件
    库文件 libxxxx.so --> 将功能程序文件进行封装之后的文件
    工程管理文件 makefile --> 用于编译整个项目代码的文件

程序写好了,用户自己进行编译:gcc main.c fun.c -o main
任务: 学习makefile,让makefile帮我们处理"gcc main.c fun.c -o main"

六. makefile的书写规则

  1. makefile的核心: 依赖 和 目标
    依赖:一般指的是.c文件 main.c fun.c
    目标:你最终想得到的文件,一般指的是可执行程序 main

  2. makefile的书写规则

1)确定好"依赖"与"目标"是谁?
2)按照以下的格式写makefile:

目标:依赖(如果有多个依赖,则每一个依赖文件之间使用空格隔开)
编译规则

注意:
1). 不等于"四个空格",编译规则之所以能运行,就是因为这个Tab键
2). 常见变量:
$^: 代表所有依赖 等价于 “main.c fun.c”
$@: 代表目标 等价于 “main”

  1. makefile的helloworld版本

target: --> 依赖文件不是必须要写,但是目标一定要写。
echo “helloworld” --> 用户书写的规则,当执行make时,就会执行这套规则

结果:
echo “helloworld” --> 默认会打印出来编译规则
helloworld

target:
@echo “helloworld” --> 在规则前面加@,结果中就不会输出编译命令

结果:
helloworld

练习时间: 写一个makefile,实现编译出main

确定好"依赖"与"目标"是谁?
依赖: main.c fun.c
目标: main

答案:
main:main.c fun.c
gcc $^ -o $@

再次执行make
gec@ubuntu:/mnt/hgfs/GZ1917/03 交叉工具链/project$ make
make: `main’ is up to date. --> makefile检测到源程序的文件与上一次一致,就不会进行编译!

  1. makefile可以有多个目标,make时可以指定执行某个目标的规则

gec@ubuntu:/mnt/hgfs/GZ1917/03 交叉工具链/project$ make main --> 指定执行main这个目标对应的规则
gec@ubuntu:/mnt/hgfs/GZ1917/03 交叉工具链/project$ make --> 默认执行makefile的第一个目标

例子:
main:main.c fun.c
gcc $^ -o $@

clean:
rm main

执行"make clean"时,就只会执行clean的规则,不会理会main的规则

七. makefile的变量种类

  1. 自定义变量 —> 默认是字符串类型
    规则:
    1)只能用数字,字母,下划线组成
    2)大小写敏感
    3)不能出现 # =
    4)给变量赋值时,等号两边可以有空格,但是shell编程中的环境变量赋值时,等号两边不能有空格!
    5)引用变量时,只需要在变量的前面加$就可以了,加个括号括住变量也可以。 $A $(A)
    6)赋的值的""可以省略

    例子:
    A = Hello 等价于 A = “Hello”
    a = Hello
    B=world
    C = $A $(B)

例子:
C_SOURCE=main.c fun.c

main:$(C_SOURCE)
gcc $^ -o $@

clean:
rm main

  1. 系统预设定变量
    有些变量是系统中已经定义好的,不需要我们用户再次定义,常用变量
    CC: 编译器名字,默认是cc cc等价于gcc
    RM: 删除内容变量,默认是rm -f

例子:
C_SOURCE=main.c fun.c

CC=arm-linux-gcc

main:$(C_SOURCE)
$(CC) $^ -o $@

clean:
$(RM) main

  1. 自动化变量 --> 变量的值不是固定的,而是会变化!

    $^: 代表所有依赖
    $@: 代表目标

八. makefile伪指令

假设makefile有一目标规则:

clean:
$(RM) main

当我们执行make clean时就会执行这套规则,如果当前有一个文件名字也叫clean
那么在执行make clean时,就会提示:make: `clean’ is up to date.

解决方案:将clean关键词添加到伪指令中

添加代码:
.PHONY:clean

例子:

.PHONY:clean

clean:
$(RM) main

实例:
C_SOURCE=main.c fun.c

CC=arm-linux-gcc

main:$(C_SOURCE)
$(CC) $^ -o $@

.PHONY:clean

clean:
$(RM) main

============================================= Makefile ==========================================
一、什么是 Makefile
什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的 IDE 都为你做了这个工作,
但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,
但如果你想成为一个专业人士,特别在Unix下的软件编译,你就不能不自己写makefile了,
会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。因为,makefile关系到了整个工程的编译规则。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,
哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,
其中也可以执行操作系统的命令。makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,
整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,
一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。

二 关于程序的编译和链接

在此,我想多说关于程序编译的一些规范和方法,一般来说,无论是C、C++、还是pas,首先要把源文件编译成中间代码文件,

在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,这个动作叫做编译(compile)。然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。
编译时,编译器需要的是语法的正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C++文件中),

只要所有的语法正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。

链接时,主要是链接函数和全局变量,所以,我们可以使用这些中间目标文件(O文件或是OBJ文件)来链接我们的应用程序。

链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,

三、 Makefile的使用
1)规则,格式如下:
目标:依赖
条件

目标:也就是一个目标文件.o文件,也可以是执行文件。还可以是一个标签(Label)

依赖:就是要生成那个 目标 所需要的文件或是目标。

条件:也就是make需要执行的命令。(任意的Shell命令)

举例如下:
target:main.c
gcc main.c -o target

注意:
如果目标文件比依赖文件新,就不编译
如果依赖文件比目标文件新,就 编译
如果目标文件没有也会编译

2)变量 —>v4
自定义变量 —>不要想成 C 的那种变量

自动变量
cc —》默认是gcc
$< -->依赖列表中最前面的一个
$^ -->所有依赖
$@ -->所有目标,但是我们最终希望是:一个目标,多个依赖!!!!
% —》自动匹配,相当于linux下的通配符* *.c

3)函数
wildcard
patsubst

文件名可以写 makefile 或者 Makefile
也可以写成别的名字,比如:abc —>编译命令:make -f abc

Linux基础.交叉编译工具链,makefile_第1张图片

你可能感兴趣的:(Linux学习)