嵌入式系统及应用Linux学习笔记(四)—Linux基础之Makfile文件

Linux基础之Makfile文件

编译流程

  • 编译流程: 预处理->编译->汇编->链接
  • 每个编译的环节都会产生不同类型的文件,对于C程序:
    • 预处理 -> .i文件
    • 编译 -> .s文件
    • 汇编 -> .o文件
    • 链接 -> 可执行文件
  • 每个环节都有自己的依赖,即若想生成.o文件,那么需要.s、.i、.c文件。

Makefile的介绍

  • 认识Makefile和make。
  • Makfile是一种纯文本的编译脚本,在其中可以指定需要编译哪些文件,哪些先编译,哪些后编译,哪些需要重新编译,最终需要生成怎么样的应用程序。
  • make是一种命令,它用来解释Makefile脚本,并根据脚本中的指定内容,进行操作。
  • 使用make命令执行Makefile文件。
  • 在默认情况下,make会执行当前目录下的Makefile文件。若当前目录下找不到相关的Makefile文件,则会出现错误:
make: *** No targets specified and no makefile found.  Stop.
  • Makefile文件的命名可以为“Makefile"或"makefile"。
  • 如果使用非标准命名的makefile,必须用命令开关"-f" 或 “-file”。参数 “-f ” 或 “–file
    ”告诉make 读入name 作为makefile文件。
  • 如果需要make不去查找当前目录,而是查找另外一个目录下的makefile,则使用-C 参数
make -C /home/hxy

表示去找查找 /home/hxy下的makefile

  • Makefile带来的好处——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

  • 另一个好处,某工程有10万个源文件,如果其中某一个源文件发生改变,不需要重新编译整个工程,但是我们生成应用程序前需要将所有的源文件生成.o文件。makefile会根据文件更新时间而判断,是否需要重新编译源文件成.o文件,在生成应用程序时,只需要将所有的.o文件做链接即可。

Makefile简单的练习

#sample makefile script
CC=gcc
SRCS=fun1.c fun2.c main.c
EXEC=test

all:
       $(CC) $(SRCS) -o $(EXEC)

编写完后,保存,在当前目录下执行make命令,生成可执行程序test
在这里插入图片描述

Makefile的组成

  • Makefile里主要包含了五种类型的语句:

    显式规则、隐式规则、变量定义、文件指示、注释

    注:Makefile中可以直接调用shell命令。

  • 显式规则:
    显式规则说明了如何生成一个或多个的目标文件。这是由Makefile 的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令

  • 隐式规则:
    由于make有自动推导的功能,所以隐式的规则可以让程序员比较简略地书写Makefile,这是由make所支持,例如,makefile发现.o文件,程序就会自动去找.c文件,并编译成.o文件。

  • 变量的定义:
    在Makefile中可定义一系列的变量,变量一般都是字符串,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上

  • 文件指示: 包括了三个部分。

    • 在一个Makefile中引用另一个Makefile
    • 根据某些情况指定执行Makefile中的有效部分
    • 定义一个多行的命令。
  • 注释: Makefile注释使用"#",若Makefile需要用到“#”,则需要做转义“#”。

Makefile的组成

#sample makefile script	#注释
include other.make	#文件指示,包含其他文件,其他文件中的变量会被包含进来

CC=gcc	#CC,SRCS,EXEC为变量,都是字符串,使用时会完全被替换。
SRCS=fun1.c fun2.c main.c
EXEC=test

all:
       $(CC) $(SRCS) -o $(EXEC) 	#makefile命令部分,变量在被引用时需要加上$()或者${}

Makefile与程序或其它脚执行顺序一样,都是自上到下。
引用未定义的变量时,不会出错,但其值为空,即什么都没有。

Makefile的规则(命令)

  • 规则解释如何编译文件,make根据依赖关系执行产生或更新目标;规则也说明如何和何时执行动作。有的规则看起来很复杂,但都符合下述模式。
<target>:<depend>
 <tab>  command1
 <tab>  command2
	……
  • target是一个目标文件,可以是可执行文件或.o文件,也可以是执行动作。
  • depend目标的依赖,目标若需要成立,必须有依赖。一个target可以拥有多个depend 。
  • command是make执行动作,一个目标依赖关系中可以包含多个命令,但是每个command不能是空格或者其它的字符,只可以一个制表符Tab键。
  • 注:若target缺少depend ,那么command会直接被执行。

Makefile的工作原理

#sample makefile script
CC=gcc
SRCS=fun1.c fun2.c main.c
EXEC=test
all:
       $(CC) $(SRCS) -o $(EXEC)
clean:
       rm -rf $(EXEC)
  • 当执行make的时候,make程序从当前目录读入makefile开始处理第一个非"."的规则,这称作缺省目标。
  • 上述的makefile中,缺省目标是all,由于目标all缺少depend,所以这个规则中的命令会被直接执行。
  • 在执行make的时候,也可以指定目标执行,如make clean,那么make会直接读入执行目标clean,跳过all。
  • 若执行make all,那么与make 功能相同。

Makefile自动检测更新

  • 工程若干个源文件中,某一个文件发生了改变,我们希望只重新编译被修改的那一个文件,其它的文件不重新编译。
  • make在执行时,会确认所有target是否都是最新的,若target的某一个depend的时间比target新,那么make会重新根据依赖关系来执行相应的命令。
  • 对于例子中的Makefile,all没有依赖所以命令总是会执行。 这里需要修改Makefile
#sample makefile script
CC=gcc
OBJS=fun1.o fun2.o main.o
EXEC=test

all:$(OBJS)
	$(CC) $(OBJS) -o $(EXEC)
fun1.o:fun1.c
	$(CC) -c fun1.c
fun2.o:fun2.c	
	$(CC) -c fun2.c
main.o:main.c
	$(CC) -c main.c
clean:
       rm -rf $(EXEC)

Makefile隐式规则

  • 由于make有自动推导的功能,所以隐式的规则可以让程序员比较简略地书写Makefile。
  • make在解释Makefile时,若目标是.o文件,那么他会自动的去寻找相应的.c文件, 并隐式的进行编译。

Makefile隐式规则 - 简化2

#sample makefile script
CC=gcc
OBJS=fun1.o fun2.o main.o
EXEC=test

all:$(OBJS)
	$(CC) $(OBJS) -o $(EXEC)
fun1.o:
fun2.o:	
main.o:

clean:
       rm -rf $(EXEC)

简化2: 使用隐式规则,目标文件为.o文件,make自动推导搜索.c文件,并编译。

Makefile隐式声明 - 简化3

#sample makefile script
CC=gcc
OBJS=fun1.o fun2.o main.o
EXEC=test

all:$(OBJS)
	$(CC) $(OBJS) -o $(EXEC)
clean:
       rm -rf $(EXEC)

简化3: 使用隐式规则,目标的依赖为三个.o文件,fun1.o, fun2.o,main.o, make自动推导,找到相应.c文件生成找到.o文件。

Makefile的变量替换

  • 在Makefile中通常指定需要编译的.c文件,我们可以将多个.c文件名保存在变量SRCS中,再定义另一个变量OBJS使其保存.o文件名。
  • 我们可以直接使用变量的替换方式,将SRCS中的".c"字符串替换成".o",赋值OBJS变量。
  • 其格式为:foo = $(var:a=b),将var变量中的a替换成b,并返回给foo。

例:

SRCS = fun1.c fun2.c main.cOBJS = $(SRCS:.c=.o)

那么变量OBJS值为fun1.o fun2.o main.o

Makefile优化

#sample makefile script
CC=gcc
SRCS=fun1.c fun2.c main.c
OBJS=(SRCS:.c=.o)

EXEC=test

all:$(OBJS)
	$(CC) $(OBJS) -o $(EXEC)
clean:
       rm -rf $(EXEC)

Makefile的变量追加

在定义一个变量之后,我们可以继续在变量后面加上新的值。追加的语法与C语言中复合运算的“+=”类似。

如:
CFLAGS = -Wall
CFLAGS += -O2
那么最终CFLAGS的值为 -Wall -O2

Makefile预定义变量

  • 不管是显式规则还是隐式规则,makefile都有一些预定义的变量,这些变量有些会在隐式规则中自动带入,有些则是约定俗成的具有特殊意义的变量。

部份预定义变量:

CC			:	编译器类型
CFLAGS		:	编译选项, 通常为-O2 -Wall -I -L
LDFLAGS		:	额外链接库
EXEC或APP   :  	应用程序名
SRCS		:	源代码
OBJS		:	目标文件

Makefile通用版(基本版)

# makefile example
CC=gcc
CFLAGS = -Wall -O2 
CFLAGS += -I./  -L./
LFLAGS = -lpthread -lm 

SRCS = fun1.c \
	fun2.c  \
	main.c

OBJS=$(SRCS:.c=.o)

EXEC=test

all:$(OBJS)
        $(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LFLAGS)

clean:
        rm -rf $(EXEC) $(OBJS)

猜你喜欢

转载自blog.csdn.net/qq_40700822/article/details/106219951