Linux系统编程6-Makefile

序号内容链接
1多进程点我访问
2进程间通信点我访问
3多线程点我访问
4网络编程点我访问
5shell点我访问
6Makefile点我访问
7串口通信点我访问
8I2C通信点我访问

1 Makefile

1.1 什么是Makefile

Makefile叫做工程管理器;

它的作用是用来管理多数的文件的编译关系的,例如相互依赖关系…
总之一句话,它是用来帮我们自动编译代码的,然后呢它会自动去按照我们的指示搜索库和头文件然后根据我们自定义的规则编译出执行文件或者其他东东;

有同学说,编译代码不久一个gcc hello.c -o hello 就完了吗,为什么还要Makefile呢?
(1) 因为假如代码用到的库非常多,达到上百个,假如这样你还一个一个敲就非常的麻烦;
(2) 我突然加了几个新功能,多加了几个.c和.h,假如手敲又要重新加进去;
(3) 假如客户忽然又不要这个功能了,又删了几个.c和.h,这样手敲就很麻烦了;

所以Makefile最大的特点是可以自动化处理;

Makefile在Linux下是用途是非常广的,不管是uboot源码,或者Linux源码,或者其他的第三方工具,都是使用Makefile进行编译到;

Makefile的文件名必须是Makefile,不能是aaa,bbb之类的东西;
而且Makefile的M一定要大写,不要小写,因为有些时候会出问题;
Makefile一般和源码放在同一目录;

外部知识:
在这里插入图片描述

argc是外部参数的意思,最小是1;
argv是外部传进来的参数,类型是char *;

注意: 不要在windows下写Makefile,因为windows的tab键的机制和linux不一样;

1.2 语法介绍

Makefile是由一个一个规则组成的,所谓的规则的格式如下:

目标:依赖 
<Tab>命令1 <Tab>命令2  
注意: tab是命令前必须要加的东西,否则会出问题;

目标: 规则的目标,就是你想要用这个规则编译出什么东西;
依赖: 编译出这个目标依赖哪些东西;
命令n: 执行的命令,自定义;

例子:

明确目标:我们的目标是编译出执行文件hello 
目标的依赖: hello.c 
命令: 我们怎么样用hello.c编译出hello?     
	gcc hello.c -o hello

如何执行Makefile?

make  
#你在输入make的时候,系统会自动在你当前的目录搜寻Makefile,然后根据它里边的规则进行编译东西; 
#必须在有Makefile的目录下make,不能在任意目录make

在这里插入图片描述

Makefile它有一个时间检测机制,假如hello的依赖文件hello.c自从上次编译之后没有进行过更改,那么假如你重新make一次,它就不会重新编译,这样的好处是提高编译的效率;
假如我就是想让他从新编译,怎么办?
(1) 删除最终的目标;
(2) 改依赖文件;

在Makefile中,标准情况下都会有一个clean选项,作用是清除编译产物;

clean:     
	rm -rf hello

调用clean选项的方法:

make clean
hello:hello.c     
	gcc hello.c -o hello  
xixixi:
	echo xixixi is call  
hahaha:     
	echo hahaha is call  
clean:     
	rm -rf hello

调用xixixi的方法:

make xixixi

调用hahaha的方法:

make hahaha

指针数组和数组指针有什么区别;

牛奶 -> 首先它是奶,它是牛的奶;
奶牛 -> 首先它是牛,是产奶的牛;

指针数组 -> 数组 -> 装的是指针;
数组指针 -> 指针 -> 指向的是一个数组;

小总结:
(1) 一个Makefile只有一个最终规则,哪个规则写在Makefile的最前面,哪个就是最终规则
(2) Makefile在寻找依赖的时候,它会自动去搜寻本文件里的所有规则看是否有对应的规则是处理自己的依赖的;

2 高级Makefile

之前说的只是让大家了解一下Makefile的基本语法,在实际写Makefile的时候我们不会这样写的,当源码比较多的时候,我们就会用变量进行编写,达到事半功倍的效果;

变量有如下类型:
(1) 用户自定义变量;
(2) 自动变量;
(3) 预定义变量;

2.1 用户自定义变量

这个是用户自己定一个变量,值可以是任意值,名字也任意;

注意,变量的值的类型是字符串,当它被改变的时候,现实对应的文件不会;

格式:

定义变量: SRC=main.c 
引用变量: $(SRC)   
叠加变量: SRC+=libballoon.a

举例:

SRC=main.c libballoon.a 
ELF=main  
$(ELF):$(SRC)      
	gcc $(SRC) -o main  
libballoon.a:balloon.o      
	ar -r libballoon.a balloon.o  
balloon.o:balloon.c  
	gcc -c balloon.c -o balloon.o  
clean:  
	rm -rf balloon.o libballoon.a main

2.2 自动变量

自动变量的值会根据它所在的规则的目标和依赖进行自动变化;

常用的自动变量:

变量说明
$@当前规则的目标
$<当前规则的第一个依赖文件
$^当前规则的所有依赖文件,以逗号分隔
$?规则中日期新于目标文件的所有相关文件列表,逗号分隔
$(@D)目标文件的目录名部分,若 @ 为 ” s u m / a d d . c , 则 @为”sum/add.c,则 @sum/add.c(@D)为sum
$(@F)目标文件的文件名部分,若 @ 为 ” s u m / a d d . c , 则 @为”sum/add.c,则 @sum/add.c(@F)为add.c

2.3 预定义变量

预定义变量是系统事先定义好的变量;
它们有些有一个默认值,当然,你也可以修改它;

变量描述
AS汇编程序,默认为 as
CCc 编译器默认为gcc
CPPc 预编译器,默认为$(CC) -E
CXXc++编译器,默认为 g++
RM删除,默认为 rm -f
ARFLAGS库选项,无默认
ASFLAGS汇编选项,无默认
CFLAGSc 编译器选项,无默认
CPPFLAGSc 预编译器选项,无默认
CXXFLAGSc++编译器选项,无默认

3 Makefile规则

之前我们编译代码的方法是直接把.c文件编译成执行文件:
在这里插入图片描述

但是在大型的项目代码中,也就是代码非常多的时候,例如Linux内核源码,或者uboot的源码,它并不是这样子直接简单编译的,它们的方法是:

在这里插入图片描述

当你源文件非常少的时候,没必要像上述一样编译;

3.1 隐式规则

隐式规则的意思是Makefile默认有这个规则;

例如:
.o文件会自动去找相对应名字的.c或者.cc文件,然后自动把它们编译成.o文件,就算我们没写,它也会自动去做;

在这里插入图片描述

3.2 模式规则

有些时候,某些文件的后缀都是一样的,但是不一样,我们相用一些特殊的符号来代表这一类后缀的文件,我们就可以使用模式规则,也就是我们的%号,%的在Makefile的意思是通配符的意思,它可以代表一个或者多个字符;
例如:

%.c -> 所有的.c文件,只要你是.c结尾的,我不管你前面是多少个字符,都会被他匹配到 
%.cpp -> 所有的.cpp结尾的文件

在这里,我们假装没学过隐式规则;

SRC=func.o main.o 
ELF=main  

$(ELF):$(SRC)     
	$(CC) $^ -o $@    
#这里的意思是所有的.o都依赖所有的.c,会自动编译成相应的.o 
#当然,这句话和隐式规则是一样的,但是有些时候我们想指定是哪个.o,隐式规则就不适用的,日后你们会懂的   
%.o:%.c      
	$(CC) -c -o $@ $^

4 Makefile函数

在Makefile中,它给我们提供了一些方便的函数,可以协助我们进行设计Makefile;

4.1 wildcard函数

功能:
自动搜索某种后缀结尾的文件,然后返回到用户的自定义变量中;

语法:

wildcard *.后缀

例子:

假设当前目录有:     1.c    2.cpp   3.S    4.c   5.bmp    6.png   7.jpg      
执行了:   SRC=$(wildcard *.c) 
SRC的值 -> 1.c 4.c   
执行了:   SRC=$(wildcard *.bmp) 
SRC的值 -> 5.bmp

4.2 patsubst函数

它的作用是指定字符串替换;

注意,它的作用仅仅是文本替换,并不会改变现实文件的东西;

例如main.c被改成了main.o,实际中的main.c是没有被改动的,也没有main.o生成,因为patsubst只是简单的字符串替换;

$(patsubst 要替换的字符串, 替换的字符串, 源字符串)  
例如:     SRC=main.c func.c     
OBJ=$(patsubst %.c, %.o, $(SRC))         
 把SRC字符串里的所有.c替换成.o,结果是:         
 OBJ=main.o func.o
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值