BSP Day46

Linux入门,Makefile编写

简介

在Linux下使用GNU的make工具能够比较容易的构建一个属于自己的工程,整个工程的编译只需一个命令(make)就可以完成编译,链接。这依赖于Makefile文件。

Makefile 是和 make 命令一起配合使用的,很多大型项目的编译都是通过 Makefile 来组织的,。

make是一个命令工具,当运行make命令时,会在当前目录下寻找名为“GNUmakefile”、“Makefile”、“makefile”的文件。Makefile文件说明了组成程序的各模块间的相互关系以及更新模块时必须进行的动作,make按照说明自动的维护这些模块。

Makefile文件描述了整个工程的编译、链接等规则。其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建哪些库文件以及如何创建这些库文件、如何在最好产生我们想要的可执行文件。尽管看起来可能是很复杂的事情,但是为工程编写Makefile的好处是能够使用一行命令来完成“自动化编译”,一旦提供一个(通常对于一个工程来说会是多个)正确的Makefile。编译整个工程所要做的事就是在shell提示符下输入make命令。整个工程完全自动编译,极大提高了效率。

用途:

1.项目代码编译管理

2.节省编译项目时间

3.一次编写终生受益

Makefile规则说明

<target1 > <target2>.... : <prerequisites1> <prerequisites2>...
[TAB] <command1>
[TAB] <command2>
...

target可以是一个object file(目标文件),也可以是一个执行文件,还可以是一个标签(label)。对于标签这种特性,在后续的“伪目标”中会有叙述。

<prerequisites>就是,要生成那个target所需要的文件或是目标。

<command>也就是make需要执行的命令。(任意的shell命令)

这是一个文件的依赖关系,也就是说,<target>这一个或多个的目标文件依赖于<prerequisites>中的文件,其生成规则定义在 <command>中。说白一点就是说,<prerequisites>中如果有一个以上的文件比<target>文件要新的话,<command>所定义的命令就会被执行。这就是makefile的规则。也就是makefile中最核心的内容。

下面我们用main.c这个文件编译成一个可执行文件为例来看看Makefile的编写。以下是文件的代码(测试用)

main.c

int main()
{
        int a = 10;
        int b = 20;
        printf("和为:%d\n",a+b);
        return 0;
}

将.c 文件放在Makefile同级目录,如图。 

以下是Makefile原文:

main:main.c
        gcc -c main.c -o main.o
        gcc main.o -o main

逐行解释:

main:main.c    意思是:main这个可执行文件是依靠main.c生成的

gcc -c main.c -o main.o    意思是:把这个.c文件编译成.o文件

gcc main.o -o main        意思是:编译这个.o文件为可执行文件main

然后在命令行执行make就生成了一个可执行的二进制文件main,如图:

 

 工作原理:

1.若想生成目标发,检查规则中的依赖条件是否存在,如果不存在,则寻找是否有规则用来生成该依赖文件。

2.检查规则中的目标是否需要更新,必须先检查它的所有依赖,依赖中有任何一个被更新,则目标必须更新。

#依赖不存在,寻找依赖条件

main:main.o

gcc main.o -o main

main.o:main.c

gcc -c main.c

 #只要一个文件更新,则只会单独更新对应文件

#只要一个文件更新,则最终目标就会进行更新

#Makefile文件写的时候,倒着来

test:add.o sub.o mul.o div.o

        gcc add.o sub.o mul.o div.o -o test

add.o:add.c

        gcc -c add.c

sub.o:sub.c

        gcc -c sub.c

mul.o:mul.c

        gcc -c mul.c

div.o:div.c

        gcc -c div.c

 如果没有ALL指定终极目标,只执行一个就结束。

当用ALL指定终极目标后,书写顺序就可以不受限制。

ALL:test

add.o:add.c

        gcc -c add.c

sub.o:sub.c

        gcc -c sub.c

mul.o:mul.c

        gcc -c mul.c

div.o:div.c

        gcc -c div.c

test:add.o sub.o mul.o div.o

        gcc add.o sub.o mul.o div.o -o test

   所以我们可以总结出:

1.目标的时间必须晚于依赖条件的时间,否则,更新目录

2.依赖条件如果不存在,找寻新的规则去产生依赖。

3.ALL可以指定终极目标,打破书写顺序

接下来看戏下Makefile中的俩个函数(wildcard和patsubst)

src = $(wildcard *.c) // 等价于src = $(wildcard ./*.c)

意思就是:找到当前路径下所有后缀为.c的文件,赋值给src

obj = $(patsubst %.c,%.o,$(src))

这个意思是把src变量里后缀为.c的文件替换成.o

 所以在Makefile里我们就可以这样写:

ALL:test

src = $(wildcard *.c)

obj = $(patsubst %.c,%.o,$(src))

test:$(obj)

        gcc $(obj) -o test

然后我们再来看一下clean的用法

.PHONY:clean

clean:

        -rm -rf $(obj)

逐行解释:

.PHONY:clean的意思就是clean它不是一个目标文件

clean:没有依赖

-rm -rf $(obj)     “-”的作用是,删除不存在文件时,不报错,顺序执行结束。

接下来介绍几个自动化变量

简单说一下其中的变量:

$@
这个表示当前被执行的target的名字
$<
表示第一个依赖的名字
$^
表示所有的依赖文件列表,每个依赖项之间以空格隔开 

 所以我们在Makefile里也可以这么写

ALL:test

src = $(wildcard *.c)

obj = $(patsubst %.c,%.o,$(src))

test:$(obj)

        gcc $^ -o $@

add.o:add.c

        gcc -c $< -o $@

sub.o:sub.c

        gcc -c $< -o $@

mul.o:mul.c

        gcc -c $< -o $@

div.o:div.c

        gcc -c $< -o $@

 

 

 
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

weixiaxiao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值