Makefile基础

Makefile介绍

Makefile:是一个由 make 工具使用的文件,用于自动化编译和构建过程。它定义了一些规则和目标,指定了如何从源代码文件生成目标文件(如可执行文件或库)。通过合理的配置,Makefile可以帮助开发者高效地管理项目的构建过程。

Makefile基本结构

一个典型的 Makefile 由目标、依赖和命令组成。

target: dependencies
    command

目标:构建的最终目标,通常是可执行文件、对象文件、虚拟目标等。

第一条规则中的第一个目标成为终极目标,只要该目标更新了,那么 Makefile 的工作就完成了

依赖文件:目标需要用到的文件,如果依赖文件更新,目标将重新构建。
命令:用来创建或更新目标,每个目标下面有一个或多个命令,命令必须以TAB开头(不能是空格)。

Makefile执行过程

解析 Makefile:make 读取 Makefile 文件中的内容,解析其中的目标、依赖关系和命令。
确定目标:make 确定终极目标(通常是 Makefile 中的第一个目标,或者指定的目标)。
检查依赖关系:make 检查目标所依赖的文件是否更新。如果依赖文件的时间戳晚于目标文件的时间戳,make会执行相应的命令来重新生成目标文件。
执行命令:如果目标需要更新,make 会执行与该目标相关联的命令。
递归构建:如果目标依赖于其他目标,make 会递归地构建这些依赖目标,直到所有目标都构建完毕。

make 会从目标的依赖关系开始,递归地检查每一个目标及其依赖,直到所有依赖项都已处理完毕。在执行每个目标时,make会确保依赖项按照正确的顺序构建。

make选项:
make -j4:并行执行构建任务
make -n:查看执行过程
make -d:显示make要执行的命令,但不实际执行

Makefile变量

Makefile中的变量都是字符串

注释开头用符号#

变量的引用方法是$(变量名)

在命令前加上@就不会输出命令执行过程.

要输出一串字符使用echo

CC = gcc
CFLAGS = -Wall -g

all:
    @echo "Compiler is $(CC)"
    @echo "Flags are $(CFLAGS)"

赋值符:

=:在每次引用该变量时重新计算其值,即变量的值会在使用时根据当前的环境或上下文进行计算

:=:立即计算右边的表达式并将其值赋给变量

?=:用于在变量尚未定义时进行赋值。如果该变量已经定义,则不会进行赋值操作。这是一种常见的防止覆盖已经设置的变量值的方法。

+=:将新的内容追加到现有的变量值中

Makefile模式规则

模式规则是允许通过使用通配符来定义规则。常见的模式符号是百分号 (%),它代表文件名的通用部分。

%.o: %.c
    gcc -c $< -o $@

Makefile自动化变量

自动化变量在构建规则时会被make自动赋值,它们代表目标和依赖文件、命令执行过程中的其他信息。
在这里插入图片描述

Makefile伪目标

伪目标是一些不代表实际文件的目标。通常用于执行一些非构建操作,如清理中间文件、安装程序、构建文档等。伪目标不依赖于文件系统中的实际文件,因此它们总是会被执行,而不管是否存在同名的文件

为什么使用伪目标?
在 Makefile 中,make会根据目标文件是否存在来决定是否执行规则。如果目标文件已经存在,且依赖文件没有更新,make将跳过该目标的构建过程。因此,如果你创建一个与某个实际文件同名的目标(例如 clean),make 会认为这个目标已经是最新的,而不会执行相应的命令。为了避免这种情况,可以使用伪目标,它们不会受到文件存在与否的影响,每次都会执行

声明方式:.PHONY : clean

.PHONY: clean all install

all: program

program: main.o utils.o
    gcc -o program main.o utils.o

clean:
    rm -f *.o program

install:
    cp program /usr/local/bin

Makefile条件判断

ifeq和ifneq

ifeq和ifneq用于测试两个值是否相等或不相等。

ifeq (value1, value2)
    # 如果 value1 和 value2 相等,执行此块的命令
endif
CC = gcc
CFLAGS = -Wall

ifeq ($(DEBUG), true)
    CFLAGS += -g
    TARGET = debug_program
else
    CFLAGS += -O2
    TARGET = release_program
endif

$(TARGET): main.o utils.o
    $(CC) $(CFLAGS) -o $@ $^

all: $(TARGET)

ifdef 和 ifndef

ifdef 和 ifndef 用于判断一个变量是否已定义。

ifdef VAR_NAME
    # 如果 VAR_NAME 已定义,执行此块的命令
endif

Makefile内建函数

$(wildcard files...)
wildcard 函数用于查找符合通配符模式的文件,通常用来列出目录中的所有源代码文件。

#返回所有以 .c 结尾的文件名
SRCS := $(wildcard *.c)

$(patsubst pattern,replacement,text)
patsubst 函数用于根据给定的模式替换字符串中的部分内容。

#src/main.c 会变成 src/main.o
OBJS := $(patsubst %.c,%.o,$(SRCS))

$(suffix names...)
suffix 用于返回文件的扩展名部分。

#$(suffix $(SRCS)) 会返回所有源文件的扩展名部分
EXTS := $(suffix $(SRCS))

$(basename names...)
basename 用于去掉文件名中的扩展名,只保留文件名的主体部分。

#如果 SRCS 中包含 src/main.c 和 src/utils.c,那么 $(FILES) 会是 src/main 和 src/utils
FILES := $(basename $(SRCS))

$(dir names...)
dir 用于获取文件的目录部分,即去除文件名部分。

#src/main.c 会被替换为 src/,如果文件在根目录,返回空字符串。
DIRS := $(dir $(SRCS))

$(notdir names...)
notdir 用于获取文件的文件名部分,即去除路径。

#src/main.c 会变成 main.c
BASENAMES := $(notdir $(SRCS))

$(join list1,list2)
join 函数用于将两个列表合并成一个列表,返回一个包含所有元素的新列表。

#将 $(DIRS) 和 $(FILES) 两个列表合并为一个列表
LIST := $(join $(DIRS), $(FILES))

$(sort list)
sort 用于对列表进行排序。

#$(sort $(SRCS)) 会对 $(SRCS) 中的文件名进行排序,并返回排序后的列表。
SORTED := $(sort $(SRCS))

$(strip text)
strip 用于去除文本中的多余空格和制表符。

#$(strip -Wall -g ) 会将 CFLAGS 中的多余空格去除,得到 -Wall -g
CFLAGS := $(strip -Wall  -g  )

$(words list)
words 用于返回列表中元素的个数。

#$(words $(SRCS)) 会返回 $(SRCS) 中元素的个数。
NUM_SRCS := $(words $(SRCS))

$(findstring find,text)
findstring 用于在文本中查找子字符串,如果找到则返回子字符串,否则返回空字符串。

#如果 $(SRC_FILES) 中包含 foo,则返回 foo,否则返回空字符串。
FOUND := $(findstring foo, $(SRC_FILES))

$(filter pattern,text)
filter 用于筛选出符合模式的元素。

#$(filter %.o, $(FILES)) 会筛选出 $(FILES) 中所有以 .o 结尾的文件。
OBJECTS := $(filter %.o, $(FILES))

$(filter-out pattern,text)
filter-out 用于从列表中排除匹配的元素。

#$(filter-out %.o, $(FILES)) 会返回 $(FILES) 中所有不以 .o 结尾的文件。
NOT_OBJS := $(filter-out %.o, $(FILES))

$(call function,arguments...)
call 用于调用一个自定义函数,并传递参数。

define myfunc
echo "This is a custom function, argument: $(1)"
endef

all:
    $(call myfunc, test)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hi小瑞同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值