Linux进阶-Makefile

目录

Makefile

Makefile格式

例程

Makefile变量:系统变量、自定义变量、自动化变量。

Makefile模式匹配

例程改进

Makefile条件分支

Makefile常用函数

patsubst:模式替换函数。pattern:模式,substitute:替换。

notdir:去目录取文件名函数。

wildcard:获取匹配模式文件名函数。

foreach:循环函数

Makefile解决头文件依赖


Makefile

Linux中使用make工具来编译程序(特别是大程序),而make工具所执行的动作依赖于Makefile文件。

当工程复杂度再上一个高度时,会觉得手写Makefile很麻烦时就需要用CMake、autotools等工具生成Makefile,实际上Windows系统下很多IDE工具内部也是使用类似Makefile的方式组织工程文件的,只不过被封装成图形界面,对用户不可见。

make命令根据文件更新的时间戳来决定哪些文件需要重新编译,这使得可以避免编译已经编译过的、没有变化的程序,可以大大提高编译效率。

注意:要想完整地了解Makefile的规则,请参考《GNU Make使用手册》。

Makefile本质:无论多么复杂的语法,都是为了更好地解决项目文件之间的依赖关系。

Makefile格式

Makefile三要素:目标、依赖、命令。 格式如下:

目标:依赖

<tab>命令

目标通常是要生成的文件名称,可以是可执行文件或OBJ文件,也可以是一个执行的动作名称(伪目标,比如clean)。

依赖是用来产生目标的材料(比如源文件),一个目标经常有几个依赖。

命令是生成目标时所执行的动作。一个规则可以含有几个命令,每个命令占一行。 

注意:每个命令行前面必须是一个Tab字符。

命令被执行的条件依赖文件比目标文件新 或 目标文件还没生成

通常,如果一个依赖发生了变化,就需要规则调用命令以更新或创建目标。但是并非所有的目标都有依赖,例如目标clean的作用只是清除文件,并没有依赖。

targeta:targetb targetc
        echo "targeta"
targetb:
        echo "targetb"
targetc:
        echo "targetc"

例程

main.c

#include <stdio.h>
int main()
{
	play();
	stop();
	return 0;
}

mp3.c

#include <stdio.h>
void play()
{
	printf("play music!\r\n");
}
void stop()
{
	printf("stop music!\r\n");
}

 

Makefile变量:系统变量、自定义变量、自动化变量。

注意:=延迟赋值是指在调用时才会被赋值。 即图中的echo "$(B)"时才把A的值赋给B。

Makefile模式匹配

%:匹配任意多个非空字符,相当于shell的*通配符。

.o文件默认使用.c文件进行编译。

例程改进

学习了Makefile变量,对先前的mp3进行加深。 

Makefile条件分支

ifeq (var1,var2)
    ...    //如果var1和var2相等,执行条件
else
    ...    //如果var1和var2不相等,执行条件
endif
ifneq (var1,var2)
    ...    //如果var1和var2不相等,执行条件
else
    ...    //如果var1和var2相等,执行条件
endif

Makefile常用函数

Makefile官方手册:https://www.gnu.org/software/make/manual

patsubst:模式替换函数。pattern:模式,substitute:替换。

格式:$(patsubst PATTERN,REPLACEMENT,TEXT)。PATTERN为模式,REPLACEMENT为新模式,TEXT为文本。

示例:$(patsubst %.c,%.o,x.c.c bar.c)

TEXT中有两个单词,分别为x.c.c和bar.c,将单词去匹配模式,即%.c。

可知,x.c.c和bar.c都是.c结尾,所以能匹配模式。能匹配模式的话,就把单词去匹配新模式,即x.c.o和bar.o。

简单来说,把字符串“x.c.c bar.c”中以.c结尾的单词替换成以.o结尾的字符。函数的返回结果是“x.c.o bar.o”。

notdir:去目录取文件名函数。

格式:$(notdir NAMES...)

示例:$(notdir src/foo.c hacks),返回值为“foo.c hacks”。

wildcard:获取匹配模式文件名函数。

格式:$(wildcard PATTERN)

示例:$(wildcard *.c),返回值为当前目录下所有.c源文件列表。

foreach:循环函数

格式:$(foreach VAR,LIST,TEXT)

示例:

dirs:=a b c d

$(foreach dir,$(dirs),$(wildcard $(dir)/*))

首先dir=a,执行$(wildcard $(dir)/*)),即找a目录下的所有文件。然后dir=b,执行$(wildcard $(dir)/*)),即找b目录下的所有文件。

以此类推,等同于files:=$(wildcard a/* b/* c/* d/*)        

Makefile解决头文件依赖

写一个头文件,并把头文件添加到编译器的头文件路径中。gcc -l +"头文件"。

实时检查头文件的更新情况,一旦头文件发生变化,应该要重新编译所有相关文件。

ARCH?=x86
ifeq ($(ARCH),x86)
        CC=gcc
else
        CC=arm-linux-guneabihf-gcc
endif


TARGET=shm
BUILD_DIR=build
SRC_DIR=module
INC_DIR=include
CFLAGS=$(patsubst %,-I %,$(INC_DIR))
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))

SOURCE=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCE)))
VPATH=$(SRC_DIR)

$(BUILD_DIR)/$(TARGET):$(OBJS)
        $(CC) $(^) -o $(@)
$(BUILD_DIR)/%.o:%.c $(INCLUDE) | create_build
        $(CC) -c $< -o $@ $(CFLAGS)

.PHONY:clean create_build
clean:
        rm -r $(BUILD_DIR)
create_build:
        mkdir -p $(BUILD_DIR)

注意:Makefile的内容OBJS中SOURCES少了个S

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值