Makefile用法及变量
  Linux

Makefile用法及变量

 次点击
23 分钟阅读

Makefile概述

Makefile重要性

会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力

Makefile概述

  • Makefile 文件描述了整个工程的编译、连接等规则。其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建哪些库文件以及如何创建这些库文件、如何最后产生我们想要的可执行文件

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

  • 提升编译效率:再次编译,只编译修改的文件

Makefile的基本语法

target... : prerequisites ...

       command

  • target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。

  • prerequisites就是,要生成那个target所需要的文件或是目标。

  • command也就是make需要执行的命令。(任意的Shell命令)

以该项目为例

https://040216.xyz/archives/fen-wen-jian-bian-cheng
#一步编译.c -> exe
#test:fun.c main.c
#	gcc fun.c main.c -o test

#两步编译.c -> .o -> exe

test:main.o fun.o
	gcc main.o fun.o -o test
fun.o:fun.c
	gcc -c fun.c -o fun.o

main.o:main.c
	gcc -c main.c -o main.o

.PHONY:clean
	
clean:
	rm *.o test

Makefile和make的关系

make是一个命令工具,它解释Makefile 中的指令。

Makefile的变量

Makefile定义变量的目的

用来代替一个文本字符串:

  1. 系列文件的名字

  2. 传递给编译器的参数

  3. 需要运行的程序

  4. 需要查找源代码的目录

  5. 你需要输出信息的目录

  6. 你想做的其它事情。

自定义变量

x = a 变量在声明时需要给予初值

$(x)或${x} 取值

如果你要使用真实的 $ 字符,那么你需要用 $$ 来表示。

变量的赋值

符号

作用

是最基本的赋值方式,与在文中位置无关,系统自动推导将最终的赋值作为该变量的值。

?=   

作用是当某变量前面已经定义赋值过,则不执行本次定义赋值,否则执行本次赋值

:=  

是覆盖式赋值,假如某变量在前面已经定义赋值过,则将本次赋值作为最新的变量值

+=   

追加赋值,旧值保持不变,将新值黏贴到旧值后面

#自定义变量
#X = a
# '='取最后一次X的值赋值给Y
#Y = $(X)
# := 覆盖式赋值
#Y := $(X)
# += 追加式赋值
#Y += c
# ?= 先判读之前是否定义赋值过
#Y ?= d
#X = b

#SRC = main.o fun.o
SRC = main.o
SRC += fun.o
#all伪目标,一般用来指定最终要生成的文件,尤其是多个目的的时候
all:test
	#echo $(X)
	#echo ${Y}
#两步编译.c -> .o -> exe
test:$(SRC)
	gcc $(SRC) -o test
	# @是为了隐藏命令的打印,直接输出命令的结果
	#@echo $(X)
	#@echo ${X}
fun.o:fun.c
	gcc -c fun.c -o fun.o

main.o:main.c
	gcc -c main.c -o main.o

.PHONY:clean
	
clean:
	rm *.o test
star@star-HP13-Ubuntu:~/Codes/day10/code/Makefile1$ make
gcc -c main.c -o main.o
gcc -c fun.c -o fun.o
gcc main.o fun.o -o test
# @是为了隐藏命令的打印,直接输出命令的结果
#@echo 
#@echo 
#echo 
#echo 

自动变量

$* 不包含扩展名的目标文件名称

$+ 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件

$< 第一个依赖文件的名称

$? 所有时间戳比目标文件晚的的依赖文件,并以空格分开

$@ 目标文件的完整名称

$^ 所有不重复的目标依赖文件,以空格分开

#自动变量
SRC = main.o fun.o
all:test

#两步编译.c -> .o -> exe
test:$(SRC) main.o
	gcc $^ -o $@
	# $^ 不包含重复文件的所有依赖文件
	echo $^
	# $+ 包含重复文件的所有依赖文件
	echo $+
	# $< 第一个依赖文件
	echo $<
	# $? 更新的依赖文件
	echo $?
#fun.o:fun.c
%.o:%.c
	#gcc -c fun.c -o fun.o
	gcc -c $< -o $@
	# $*不包含后缀名的目标文件名
	echo $*
	# $@ 包含后缀名的目标文件名
	echo $@

#main.o:main.c
#	gcc -c $< -o $@

.PHONY:clean
	
clean:
	rm *.o test
star@star-HP13-Ubuntu:~/Codes/day10/code/Makefile2$ make
#gcc -c fun.c -o fun.o
gcc -c main.c -o main.o
# main不包含后缀名的目标文件名
echo main
main
# main.o 包含后缀名的目标文件名
echo main.o
main.o
#gcc -c fun.c -o fun.o
gcc -c fun.c -o fun.o
# fun不包含后缀名的目标文件名
echo fun
fun
# fun.o 包含后缀名的目标文件名
echo fun.o
fun.o
gcc main.o fun.o -o test
# main.o fun.o 不包含重复文件的所有依赖文件
echo main.o fun.o
main.o fun.o
# main.o fun.o main.o 包含重复文件的所有依赖文件
echo main.o fun.o main.o
main.o fun.o main.o
# main.o 第一个依赖文件
echo main.o
main.o
# main.o fun.o 更新的依赖文件
echo main.o fun.o
main.o fun.o

隐含变量

AR 库文件维护程序的名称,默认值为ar。

AS 汇编程序的名称,默认值为as。

CC C编译器的名称,默认值为cc。

CPP C预编译器的名称,默认值为$(CC) –E。

CXX C++ 编译器的名称,默认值为g++。

RM 文件删除程序的名称,默认值为rm -f

ARFLAGS 库文件维护程序的选项,无默认值。

ASFLAGS 汇编程序的选项,无默认值。

CFLAGS C编译器的选项,无默认值。

LDFLAGS 链接器的选项,无默认值

CPPFLAGS C预编译的选项,无默认值。

CXXFLAGS C++编译器的选项,无默认值。

#自动变量
SRC = main.o fun.o

CFLAGS = -c -Wall -I /home/star/Codes/day10/code/Makefile3/include

LDFLAGS = -lm

all:test
	echo $(CC)
	echo $(CPP)
	echo $(CXX)
	echo $(CFLAGS)
	echo $(LDFLAGS)

#两步编译.c -> .o -> exe
test:$(SRC) main.o
	$(CC) $(LDFLAGS) $^ -o $@
%.o:%.c
	$(CC) $(CFLAGS) $< -o $@

.PHONY:clean
	
clean:
	$(RM) *.o test
star@star-HP13-Ubuntu:~/Codes/day10/code/Makefile3$ make
cc -c -Wall -I /home/star/Codes/day10/code/Makefile3/include main.c -o main.o
cc -lm main.o fun.o -o test
echo cc
cc
echo cc -E
cc -E
echo g++
g++
echo -c -Wall -I /home/star/Codes/day10/code/Makefile3/include
-c -Wall -I /home/star/Codes/day10/code/Makefile3/include
echo -lm
-lm

© 本文著作权归作者所有,未经许可不得转载使用。