编写makefile文件

源文件首先要编译成中间目标文件(Object File),windows下生成.obj文件,linux环境下生成.o文件;再把大量的Object File链接成执行文件(exe)。当中间目标文件太多时,可以将其打包,windows下称之为库文件(Library File).lib文件,lunix下称Archive File,.a文件。

makefile定义一系列规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译等。使用makefile自动化编译极大提高软件开发的效率。

编译和链接某个工程中多个文件的规则是:

  1. 如果工程没有编译过,那么所有源文件(.c/.cpp等)都要编译并被链接;
  2. 如果工程的某几个源文件被修改,那么只编译被修改的源文件并链接目标程序;
  3. 如果工程的头文件被修改,那么需要编译引用了这几个头文件的源文件,并链接目标程序。

编写makefile文件语法格式:

目标:依赖

        命令

  • 目标:通常是要生成的文件名称,也可以是要执行的动作名称,如“clean”。
  • 依赖:生成目标所需要的文件或中间过程生成的目标。
  • 命令:通过依赖,执行命令生成目标。命令前必须是一个Tab,不能是空格。

makefile工作原理

  1. 检查依赖:在生成目标之前,make会检查规则中的依赖是否存在。如果不存在则寻找是否有规则用来生成该依赖文件。
  2. 检查更新:如果依赖存在,make会检查依赖的时间是否比目标的时间新。如果依赖的时间更新,或无目标文件,则执行命令更新/生成目标。否则不需执行命令。
  3. 执行命令:如果目标需要更新/生成,则按规则中的命令执行操作。

编写makefile文件步骤

1、在bash下创建makefile文件

vi makefile

2、根据语法格式编写相应文件

all:
    gcc hello.c -o hello

目标:all

依赖:空

命令:gcc hello.c -o hello

 C++代码示例:

hello:hello.cc
    g++ hello.cc -o hello

目标:hello

依赖:hello.cc

命令:g++ hello.cc -o hello

注:在linux中.cpp等价于.cc等价于.cxx;g++编译C++,gcc编译C语言。

若想保存中间文件,则可以替换成

all:hello.o
    gcc hello.o -o hello
hello.o:hello.c
    gcc -c hello.c

或者

all:hello.o
    gcc hello.c -o hello
hello.o:hello.c
    gcc -c hello.c -o hello.o

执行顺序是从下而上,先生成hello.o,再生成hello.exe

3、执行makefile脚本

命令:make 目标文件/make all。若不指定目标,默认执行makefile/Makefile文件中第一个没有通配符的目标所对应的命令。例如:

all:hello.o
    gcc hello.o -o hello
hello.o:hello.c
    gcc -c hello.c -o hello.o
clear:
    rm -rf *.o hello

这里,makemake all功能一致。 

此时执行make clear,就会执行 rm -rf *.o hello命令。

此时若目录下存在与clear同名的文件,则在执行make clear时会报错。

 make -f filename:指定makefile文件名称,可以指定多个文件名称。

make -C dir:执行指定路径的makefile文件。

make -n:打印makefile文件中的命令但不执行。-f指定文件名。

make -s:执行makefile文件中的命令但不打印。-f指定文件名。

伪目标

解决方法:使用伪目标

伪目标格式:

.PHONY:目标

all:hello.o
    gcc hello.o -o hello
hello.o:hello.c
    gcc -c hello.c -o hello.o
.PYONY:claer
clear:
    rm -rf *.o hello

执行make clear可以成功。伪目标写在clear规则下面也可以!

 Makefile变量

变量可以用在目标、依赖、命令中;

变量赋值方式有:“:= , = , ?= , += ”,分别代表立即赋值,延迟赋值,判断赋值,追加赋值。

变量的引用是通过 $(变量名) 来实现的。

1、:=立即赋值示例:

var1:=hello
var2:=$(var1) world
var1:=hi
all:
    echo $(var2)

运行结果:

echo hello world

hello world

2、=延迟赋值示例:

var1=hello
var2=$(var1) world
var1=hi
all:
    echo $(var2)

运行结果:

echo hi world

hi world

3、?=判断赋值示例:

var1:=hello
var2=$(var1) world
var1?=hi
all:
    echo $(var2)

判断赋值首先判断变量是否已经赋值,若有则使用之前赋值结果;若无则使用本次赋值结果。示例运行结果:

echo hello world

hello world

将示例中的立即赋值注释掉,判断赋值就会生效

#var1:=hello
var2:=$(var1) world
var1?=hi
all:
    echo $(var2)

运行结果:

echo hi world

hi world

4、 +=追加赋值示例:

var1:=hello
var2=$(var1) world
var1+=hi
var1+=hello
all:
    echo $(var2)

+=追加赋值时在追加处用空格隔开,运行结果:

echo hello hi hello world

hello hi hello world

若赋值很长,可以用换行符‘\’

var1:=hello\
    hi\
    hello
var2=$(var1) world
all:
    echo $(var2)

运行结果与上面相同,在换行符处用空格隔开:

echo hello hi hello world

hello hi hello world

makefile自动化变量

为了简化代码,使用一组特殊变量来表示文件名,在执行规则时自动替换成相应的值。

$@:当前规则的目标文件名

$<:当前规则的第一个依赖文件名

$^:当前规则的所有依赖文件名(去重)

$+:当前规则的所有依赖文件名

$*:当前规则的目标文件名去除后缀

例如:

all:hello.o main.o
    gcc hello.o main.o -o hello
hello.o:hello.c
    gcc -c hello.c -o hello.o
main.o:main.c
    gcc -c main.c -o main.o
.PYONY:claer
clear:
    rm -rf *.o hello

使用变量var替换hello.o和main.o,添加依赖文件时可通过仅修改变量var即可实现。

使用$^替换所有依赖文件名;

使用替换符%和特殊变量$<、$@替换目标和依赖,简化代码;

var:=hello.o main.o
all:$(var)
    gcc $^ -o hello
%.o:%.c
    gcc -c $< -o $@

.PYONY:claer
clear:
    rm -rf *.o hello

注意:%是带着寻找hello.o和main.o的目的去执行的。

makefile函数

假设当前路径下存在一个a.c文件和一个test文件夹,test文件夹中存在一个b.c文件。

1、wildcard函数

格式:$(wildcard 文件路径)

显示指定文件路径

var:=$(wildcard ./*.c ./test/*.c)
all:
    @echo $(var)

运行结果:

./a.c ./test/b.c

2、notdir函数

格式:$(notdir 文件路径)

显示指定文件名(去掉路径)

var:=$(wildcard ./*.c ./test/*.c)
var1=$(notdir &(var))
all:
    @echo $(var1)

运行结果:

a.c b.c

 3、dir函数

格式:$(dir 文件路径)

显示指定文件路径

var:=$(wildcard ./*.c ./test/*.c)
var2=$(dir $(var))
all:
    @echo $(var2)

运行结果:

./ ./test/

 4、patsubst函数

格式:$(patsubst 源文件,目标文件,文件列表)

替换文件名后缀

var:=$(wildcard ./*.c ./test/*.c)
var1=$(notdir &(var))
var3=$(patsubst %.c,%.s,$(var1))
all:
    @echo $(var3)

运行结果:

a.s b.s

5、foreach函数

格式:$(foreach 变量,参数列表,表达式)

将参数列表中的参数作为变量,放到表达式中执行。

var:=$(wildcard ./*.c ./test/*.c)
var1=$(notdir &(var))
var2=$(dir $(var))
var4=$(foreach n,$(var2),$(wildcard $(n)*.c))
all:
    @echo $(var4)

运行结果:

./a.c ./test/b.c

参考Makefile 教程及详细示例解析(跟我一起写 Makefile)_makefile示例-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值