跟我一起学makefile(新)知识点+案例

学习资料

跟我一起学makefile
准备vs code

gcc 参数详解

  • -c

-c”选项我们上面说了,是只编译不链接
他将生成 .o 的 obj 文件
例子用法:

gcc -c hello.c 
  • -S

只激活预处理和编译,就是指把文件编译成为汇编代码。

例子用法:

gcc -S hello.c
他将生成 .s 的汇编代码,你可以用文本编辑器察看。

  • -E

只激活预处理,这个不生成文件, 你需要把它重定向到一个输出文件里面。

例子用法:

gcc -E hello.c > pianoapan.txt
gcc -E hello.c | more
慢慢看吧, 一个 hello word 也要与处理成800行的代码。

  • -o

制定目标名称, 默认的时候, gcc 编译出来的文件是 a.out, 很难听, 如果你和我有同感,改掉它, 哈哈

例子用法:
 
gcc -o hello.asm -S hello.c

gcc编译流程-shell脚本去编译

gcc编译的四个过程
在这里插入图片描述
在这里插入图片描述
案例:hello.c编译一个可执行文件
shell.sh 文件内容如下

#!/bin/bash
# 使用-o 替换名称名称
gcc -E main.c -o main.i
gcc -S main.i -o main.s
gcc -c main.s -o main.o
gcc main.o -o main

在这里插入图片描述
编译完成后生产如上图文件。

makefile 介绍

把源文件编译成中间代码文件UNIX 下是 .o 文件,即 Object File,这个动作叫做编译(compile)。然后再把大量的 Object File 合成执行文件,这个动作叫作链接(link)

makefile 规则介绍

target ... : prerequisites ... 
command
...
...
...
  • target :也就是一个目标文件,可以是 Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性
  • prerequisites: 就是,要生成那个 target 所需要的文件或是目标
  • command 也就是 make 需要执行的命令。(任意的 Shell 命令)

target 这一个或多个的目标文件依赖于prerequisites 中的文件,其生成规则定义在 command 中。

说白一点就是说,prerequisites中如果有一个以上的文件比 target 文件要新的话,command 所定义的命令就会被执行。

这就是 Makefile 的规则。也就是 Makefile 中最核心的内容。

“=”和“:=”的区别

object = yql
curname = $(object)
curname1 := $(object)
object = other
print:
	@echo curname:$(curname)
	@echo curname:$(curname1)

在这里插入图片描述

  • 赋值符“:=”不会使用后面定义的变量,只能使用前面已经定义好的

“?=”和“+=”案例

  • ?=:如果变量 curname 前面没有被赋值,那么此变量 yql
  • +=:变量追加
object = yql
curname ?= $(object)
curname += $(object)
print:
	@echo curname:$(curname)

案例3个.c和2个.- 使用makefile编译

代码如下

main.c

#include <stdio.h> 
#include "input.h"
#include "calcu.h"
int main(int argc, char *argv[])
{  
    int a, b, num; 
    input_int(&a, &b);
    num = calcu(a, b);
    printf("%d + %d = %d\r\n", a, b, num);
}

input.c

#include <stdio.h> 
#include "input.h"
void input_int(int *a, int *b) 
{ 
    printf("input two num:");
    scanf("%d %d", a, b);
    printf("\r\n");
}

calcu.c

#include "calcu.h"
int calcu(int a, int b) 
{ 
    return (a + b);
}

calcu.h

#ifndef _CALCU_H
#define _CALCU_H
int calcu(int a, int b);
#endif

input.h

#ifndef _INPUT_H
#define _INPUT_H
void input_int(int *a, int *b);
#endif

使用shell脚本编译

gcc -c main.c 
gcc -c input.c 
gcc -c calcu.c 
# 只激活预处理,编译,和汇编,也就是他只把程序做成obj文件**他将生成 .o 的 obj 文件**
gcc main.o input.o calcu.o -o main 

在这里插入图片描述

使用makefile 方式编译

main : main.o input.o calcu.o
	gcc -o main main.o input.o calcu.o
main.o: main.c 
	gcc -c main.c 
input.o: input.c 
	gcc -c input.c 
calcu.o: calcu.c 
	gcc -c calcu.c
clean : 
	rm *.o 
	rm main

在第一次编译的时候
由于 main 还不存在,因此第一条规则会执行,第一条规则依赖于文件 main.o、input.o 和 calcu.o这个三个.o 文件
这三个.o 文件目前还都没有,因此必须先更新这三个文件。make 会查找以这三个.o 文件为目标的规则并执行

makefile 变量

  • #使用"$"获取变量object的值为main.o input.o calcu.o
object = main.o input.o calcu.o
main : $(object)
	gcc -o main $(object) #使用"$"获取变量object的值为main.o input.o calcu.o
main.o: main.c 
	gcc -c main.c 
input.o: input.c 
	gcc -c input.c 
calcu.o: calcu.c 
	gcc -c calcu.c
clean : 
	rm *.o 
	rm main

在这里插入图片描述
注意:图片验证了这段话----第一条规则依赖于文件 main.o、input.o 和 calcu.o这个三个.o 文件
这三个.o 文件目前还都没有,因此必须先更新这三个文件。make 会查找以这三个.o 文件为目标的规则并执行

make 自动推导–优化一

GNU 的 make 很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必
要去在每一个[.o]文件后都写上类似的命令,因为,我们的 make 会自动识别,并自己推导
命令。

只要 make 看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果 make找到一个whatever.o,那么whatever.c,就会是 whatever.o 的依赖文件。

并且 cc -c whatever.c 也会被推导出来,于是,我们的 makefile 再不用写得这么复杂。我们的是新
的 makefile 又出炉了。

object = main.o input.o calcu.o
main : $(object)
	gcc -o main $(object) #使用"$"获取变量object的值为main.o input.o calcu.o

main.o: input.h calcu.h
input.o: input.h 
calcu.o: calcu.h 

.PHONY : clean
clean : 
	rm *.o 
	rm main

在这里插入图片描述
在这里插入图片描述

make 自动推导–优化二

object = main.o input.o calcu.o
main : $(object)
	cc -o main $(object) #使用"$"获取变量object的值为main.o input.o calcu.o

$(object): input.h calcu.h

.PHONY : clean
clean : 
	rm *.o 
	rm main

在这里插入图片描述

## make 自动推导–优化三(通配符)%

  • %:表示对文件名的匹配,“%”表示长度任意的非空字符串
  • 举例:比如“%.c”就是所有的以.c 结尾的文件
  • 举例a.%.c 就表示以 a.开头,以.c 结束的所有文件。
object = main.o input.o calcu.o
main : $(object)
	cc -o main $(object) 

%.o : %.c
	gcc -c $< #依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%)定义的,那么“$<”就是符合模式的一系列的文件集合。
.PHONY : clean
clean : 
	rm *.o 
	rm main

在这里插入图片描述

## make 自动推导–优化四(通配符)*

object = main.o input.o calcu.o
main : $(object)
	cc -o main $(object) 

*.o : *.c
	gcc -c $< #依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%)定义的,那么“$<”就是符合模式的一系列的文件集合。
.PHONY : clean
clean : 
	rm *.o 
	rm main

在这里插入图片描述

伪目标 .PHONY :clean

上述规则中并没有创建文件 clean 的命令,因此工作目录下永远都不会存在文件 clean,当我们输入“make clean”以后,后面的“rm *.o”和“rm main”总是会执行。可是如果我们“手贱”,在工作目录下创建一个名为“clean”的文件,那就不一样了,当执行“make clean”的时候,规则因为没有依赖文件,所以目标被认为是最新的,因此后面的 rm 命令也就不会执行

object = main.o input.o calcu.o
main : $(object)
	cc -o main $(object) 

%.o : %.c
	gcc -c $< #依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%)定义的,那么“$<”就是符合模式的一系列的文件集合。
.PHONY : clean
clean : 
	rm *.o 
	rm main

在这里插入图片描述
在这里插入图片描述

判断语句使用

关键字功能
ifeq判断参数是否不相等,相等为 true,不相等为 false。
ifneq判断参数是否不相等,不相等为 true,相等为 false。
ifdef判断是否有值,有值为 true,没有值为 false。
ifndef判断参数是否不相等,相等为 true,不相等为 false。

条件判断的使用方式如下:
ifeq (ARG1, ARG2)
ifeq ‘ARG1’ ‘ARG2’
ifeq “ARG1” “ARG2”
ifeq “ARG1” ‘ARG2’
ifeq ‘ARG1’ “ARG2”
案例说明

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值