【Linux工具-Makefile】整理Makefile笔记

一、Makefile基本语法

1.1 语法规范

目标文件1:依赖文件1
(Tab键)根据依赖文件1生成目标文件1的命令
目标文件2:依赖文件2
	@echo "使用依赖文件2生成目标2,@表示不显示命令本身的执行过程"
	- 表示忽略执行过程中的错误

1.2 伪目标

# 保证每一次执行make clean都是有效的
.PHONY:clean
clean:
	rm *.o *.elf

1.3 预定义变量

CC			:= 编译器名称,默认为gcc
CFLAGS		:= 编译选项
RM			:= 删除文件的命令,默认为rm -f

1.4 自定义变量

OBJ			:= test1.o test2.o

1.5 变量赋值

1.5.1 递归的方式赋值变量(VAR=var)

# 使用该方式定义变量,变量后面改变会影响前面的值的改变
a = var1
b = $(a).c
a = var2
echo:
	@echo $(a) $(b)
# 此时会输出 var2 var2.c

1.5.2 立即赋值的方式赋值变量(VAR:=var)

# 使用该方式定义变量,变量后面改变不会影响前面的值的改变
a := var1
b := $(a).c
a := var2
echo:
	@echo $(a) $(b)
# 此时会输出 var2 var1.c

1.5.3 追加的方式赋值变量(VAR+=var)

a := var1
a += var2
echo:
	@echo $(a)
# 此时会输出 var1 var2

1.5.4 有选择的方式赋值变量(VAR?=var)

# 如果变量在前面没有被赋值,就给它赋值成var
# 如果变量在前面已经赋值了,就使用前面的值
# a := var1
a ?= var2
echo:
	@echo $(a)
# 会根据是否注释前面a的赋值,确定输出的内容

二、Makefile高级语法

2.1 自动变量与通配符

# 自动变量
$@			表示目标文件
$<			表示第一个依赖文件
$^			表示所有的依赖文件(去重)
$+			表示所有的依赖文件(包括重复文件)
$*			表示目标文件去除后缀
# 通配符
%.o			表示所有的以.o结尾的文件
%.c			表示所有的以.c结尾的文件

2.2 Makefile嵌套使用

# 即在根Makefile的子目录下还可以使用子Makefile
OBJ			:= test1.o test2.o
CC			:= gcc

export OBJ CC
# 即在子Makefile中也可以使用 OBJ CC

2.3 Makefile条件指令

ifeq ('arg1', 'arg2')
ifeq 'arg1' 'arg2'
ifeq "arg1" "arg2"
ifeq "arg1" 'arg2'
ifeq 'arg1' "arg2"
# 同理
ifneq ('arg1', 'arg2')
ifdef ('arg1', 'arg2')
ifndef ('arg1', 'arg2')
else
endif
# 举例
ifeq ($(CC), gcc)
	$(CC) -o foo $(OBJS) $(gcc_libs)
else
	$(CC) -o foo $(OBJS) $(normal_libs)

三、Makefile函数

# 函数使用语法
$(FUNCTION_NAME	args)

3.1 wildcard函数

# 函数功能:展开指定目录下的文件
	SRC = $(wildcard ./test/*.c ./src/*.c)
# 说明:
#	变量SRC表示test和src目录下的所有c文件

3.2 notdir函数

# 函数功能:去掉路径
	SRC_FILES = $(notdir $(SRC))
# 说明:
#	变量SRC_FILES表示SRC去掉路径后的文件名

3.3 dir函数

# 函数功能:获取目录
	SRC_DIR = $(dir $(SRC))
# 说明:
#	变量SRC_DIR表示SRC中的目录

3.4 patsubst函数

# 函数功能:替换文件后缀
	$(patsubst %.c, %.o, $(SRC))
# 说明:
#	将变量SRC中的*.c文件名替换成*.o	

3.5 foreach函数

# 函数功能:遍历字符串,并处理每个字符串
	$(foreach item, $(INCLUDE), -I$(item))
# 说明:
#	将变量INCLUDE的所有项都添加一个-I前缀

3.6 strip函数

# 函数功能:去空格函数
	$(strip str)
# 说明:
#	去掉 str字串中开头和结尾的空字符

四、实例

CC              := gcc
CFLAGS          := -g -Wall
LDFLAGS         :=
LIBS_DIR        :=
OUT_DIR         := out
SRC_DIR         := test

INC             := ./inc

SRC             := $(foreach item, $(SRC_DIR), $(wildcard $(item)/*.c))
EXP_SRC         := $(wildcard $(EXP_DIR)/*.c)

OBJS            := $(patsubst %.c, %.o, $(SRC))
OBJS            += $(patsubst %.S, %.o, $(SRC))
CFLAGS          += $(foreach item, $(INC), -I$(item))
LDFLAGS         += $(foreach item, $(LIBS), -L$(item))

all: $(OBJS)
        @echo "compile test files..."

%.o: %.c
        @echo "compile file $^...$(notdir $^)"
        @mkdir -p $(OUT_DIR)
        $(CC) $^ $(CFLAGS) -o $(OUT_DIR)/$(notdir $@)

%.o: %.S
        @echo "compile file $^..."
        @mkdir -p $(OUT_DIR)/$(dir $^)
        $(CC) -c $^ $(CFLAGS) -o $(OUT_DIR)/$@

.PHONY:clean
clean:
        rm -rf $(OUT_DIR)
详细易懂的Linux makefile教程 一、概述 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。 因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。 makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。 现在讲述如何写makefile的文章比较少,这是我想写这篇文章的原因。当然,不同产商的make各不相同,也有不同的语法,但其本质都是在“文件依赖性”上做文章,这里,我仅对GNU的make进行讲述,我的环境是RedHat Linux 8.0,make的版本是3.80。必竟,这个make是应用最为广泛的,也是用得最多的。而且其还是最遵循于IEEE 1003.2-1992 标准的(POSIX.2)。 在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。这里所默认的编译器是UNIX下的GCC和CC。 二、关于程序的编译和链接 —————————— 在此,我想多说关于程序编译的一些规范和方法,一般来说,无论是C、C++、还是pas,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,这个动作叫做编译(compile)。然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。 ...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值