makefile 学习

 本问旨在从零学习Makefile编写。

        引入Makefile文件是因为工程项目中有很多文件,并且它们相互依赖,一个一个编译会花很多时间,并且一旦某一文件发生修改后就需要重新编译,那么所有相关的文件都需要重新编译。Makefile文件是去判断哪个文件被修改了,然后会重新生成修改后的文件,而且只需要一个make命令,极大简化了编译过程。

一、make及其用法
        Makefile文件是一类工程管理工具的工程描述符文件的默认名称,名称不一定是Makefile,也可以是makefile或GNUmakefile。

        make命令会在执行路径中搜索Makefile文件,如果同时存在以上三个文件,执行顺序是GNUmakefile > makefile > Makefile,如果选择执行一个,其他的就不会再执行了。

        如果想执行某个文件,只需要make -f 文件名就可以指定执行文件,-f也可以用–file=FILE或–makefile=FILE。

        make命令详细参数通过make -h 或者 make --helo来获取。
 

二、Makefile文件编写规则
        首先给出测试代码,测试代码有两个C文件构成,a.p和b.c,其中a.c包含主函数且调用b.c的函数,b.c为加法函数add(int a,int b)。

a.c

#include <stdio.h>
#include "b.c"

int main()
{
int a=1;
int b=2;
printf("%d\n",add(a,b));
return 0;
}

        

b.c

#include <stdio.h>

int add(int a,int b)
{
return a+b;
}

Makefile的核心——规则:

目标 : 依赖1 依赖2 ...
[TAB]命令

Makefile基础版本:

all: test #最后的可执行程序test,无论书写顺序是怎样,最后是生成test
test: a.o #test是结果,a.o是来源
#命令必须开头是tab键 -o后面生成目标
gcc -o test a.o
a.o: a.c #a.o是结果,a.c是来源
#-c表示只编译不链接,生成.o文件
gcc -c -o a.o a.c

在命令行中输入 make 指令:

Leo@Embed_Learn:~/makefile$ make
gcc -o test  a.o
Leo@Embed_Learn:~/makefile$ ls
a.c  a.o  b.c  Makefile  test
Leo@Embed_Learn:~/makefile$ ./test
3

Makefile进阶版本

        问题引入,如果某个文件被多次引用,但是现在需要修改文件名,那么一个一个修改就会很麻烦,所以Makefile文件中允许定义变量,然后后面只需要修改变量的值就可以了,原理就是Makefile文件会展开变量,类似于宏定义。

        变量定义类型规则:变量名 = 命令,使用变量是通过$(变量名)

Bin = test  # 定义变量名Bin
all: $(Bin) # 生成可执行文件test
test: a.o
        gcc -o $(Bin) a.o
a.o: a.c
        gcc -c a.c -o a.o
clean:      # clean需要使用命令make clean才会执行
        rm -f *.o $(Bin)  # 删除生成的.o文件和可执行文件

     如果要修改文件名,只需要修改test就行了。

        一般如果再次make会提示make无需做任何事,但是需要重新生成的话需要把原来的.o可执行文件删除,所以定义一个clean,俗称假目标。

 Makefile终极版

        如果有很多个.o文件需要引用,每次写就会感到很烦,Makefile提出了自动便令的概念,需注意的是自动变量只能用在命令里面。

        下面给出常用的六个自动变量:

$@        目标的文件名

$<        第一个条件的文件名

$?        时间戳在目标之后的所有条件,并以空格隔开这些条件

$^        所有条件的文件名,并以空格隔开,且排除了重复的条件

$+        与$^类似,只是没有排除重复的条件

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

Bin = test
all: $(Bin)
test: a.o
        gcc -o $(Bin) $<  #$<表示第一个条件名,也就是a.o
a.o: a.c
        gcc -c $< -o $@   #$<表示a.c $@表示目标文件名a.o
clean:
        rm -f *.o $(Bin)

Makefile的语法扩展
        有三个文件,分别为:a.c 、b.c、 c.c

         a.c

#include <stdio.h>

int main()
{
        func_b();
        func_c();
        return 0;
}

b.c

#include <stdio.h>

void func_b()
{
        printf("This is B\n");
}

c.c

#include <stdio.h>

void func_c()
{
        printf("This is C\n");
}

 通配符%
         利用Makefile的通配符: %.o进行编写

test: a.o b.o c.o
        gcc -o test $^
%.o: %.c
        gcc -c -o $@ $<
clean:
        rm *.o test

 效果如下:

clean操作+假想目标.PHONY
         根据以上的操作,我们可以知道Makefile里面定义了clean,并且通过make clean进行删除操作,但是如果我们在文件中已经有了clean这个文件然后再次进行make clean操作会怎么样呢?其实会出现“最新”的告警信息。

 因为Makefile的规则是:

当"目标文件"不存在, 
或
某个依赖文件比目标文件"新",
则: 执行"命令"

 为了避免出现make clean无法删除指定文件,我们可以引入Makefile的假想目标.PHONY进行操作

         Makefile:

test: a.o b.o c.o
        gcc -o test $^
%.o: %.c
        gcc -c -o $@ $<
clean:
        rm *.o test
.PHONY: clean

效果如下:

即使变量、延迟变量、export
A := XXX        即时变量,A的值即刻确定,在定义时即确定

B = XXX        延时变量,B的值在使用到时才确定

C ?= XXX        延时变量,如果是第一次定义,这语句才起效,但如果在前面语句中该变量已被

                        定义则忽略这句

D += XXX        附加,它是即时变量还是延时变量取决于前面的定义

先看一个小例子:

Makefile:

A := abc
B = 123

all:
        echo $(A)
        echo $(B)

效果:

如果不希望打印出echo的话可以在echo语句前面加@

A := abc
B = 123

all:
        @echo $(A)
        @echo $(B)

修改:

Makeifle:

A := $(C)
B = $(C)
C = abc
all:
        @echo $(A)
        @echo $(B)

可以看出效果如下:

A为空,B成功打印出C的值,可以看出即使变量:=与延迟变量=的区别

修改二:

A := $(C)
B = $(C)
# C = abc
all:
        @echo $(A)
        @echo $(B)
C = 123

效果:

 从结果看出,变量C放在前面还是后面对变量B是没有影响的,当执行make的时候,程序会整个读进去的,所以变量C放在前后都一样。

修改二pro:

A := $(C)
B = $(C)
C = abc
all:
        @echo $(A)
        @echo $(B)
C = 123

其实结果还是和上面的一样,C的前一个值abc被后面的123覆盖了,所以B的值还是123,

修改三:

A := $(C)
B = $(C)
C = abc
all:
        @echo $(A)
        @echo $(B)
C += 123

效果如下:

+= 为附加,它是即时变量还是延时变量取决于前面的定义

修改四:

D = leo
D ?= LEOmax
all:

        @echo $(D)

效果:

打印出的值为第一次定义的值,所以说?=如果是第一次定义,这语句才起效,但如果在前面语句中该变量已被定义则忽略这句.

修改四pro:通过命令行存入变量D:

D ?= LEOmax
all:

        @echo $(D)

通过命令行make D=123456赋值D为123456覆盖了在Makefile里面leo。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值