C/C++Makefile

前言

  这里记录的是Makefile的编写,而不是CMakeLists,先学Makefile,然后再去看CMakeLists,或者直接去看CMakeLists。

1. 代码编译基本流程

1、预处理
宏定义展开、引入头文件、去除注释
2、汇编
生成汇编代码
3、编译
生成二进制文件
4、链接
生成可执行文件

gcc -* hello.c -o hello.*

-E :预处理生成.i  gcc -E hello.c -o hello.i
-S :汇编生成.s    gcc -S hello.i -o hello.S
-c :编译生成.o    gcc -c hello.S -o hello.o
其中 -o :指定生成文件名
gcc hello.o -o hello.exe

很多文件时,可以一个一个去编译,且控制生成的文件类型(动态库or动态库或exe),但很麻烦。所以需要Makefile


2. Makefile 5层心法

2.1 显式规则

# '#'号是注释
1. 语法格式:
目标文件:依赖文件
	(TAB)指令
	
hello.i:hello.c
	gcc -E hello.c -o hello.i
hello.S:hello.i
	gcc -s hello.i -o hello.S
hello.o:hello.S
	gcc  -c hello.S -o hello.o
hello.exe:hello.o
	gcc hello.o -o hello.exe
2. 目标文件
#第一个目标文件是Makefile的最终目标,所以要放最前

hello.exe:hello.o
	gcc hello.o -o hello.exe
hello.o:hello.S
	gcc  -c hello.S -o hello.o
hello.S:hello.i
	gcc -s hello.i -o hello.S
hello.i:hello.c
	gcc -E hello.c -o hello.i

  上面的Makefile经过一次编译后hello.o等文件已经存在,当修改hello.c后想再次编译,则无法得到想要的结果,因为hello.o已经存在,所以需要伪目标 .PHONY

3. 伪目标  .PHONY:
hello.exe:hello.o
	gcc hello.o -o hello.exe
hello.o:hello.S
	gcc  -c hello.S -o hello.o
hello.S:hello.i
	gcc -s hello.i -o hello.S
hello.i:hello.c
	gcc -E hello.c -o hello.i

.PHONY:
#删除过程文件
clear:
	rm -rf hello.i hello.S hello.o
#删除所有文件
clearall:
	rm -rf hello.i hello.S hello.o hello

写了上面的伪目标后,经过一次编译后,可以执行make clear清除中间文件.

make clear
make clearall

  但有时我们会有许多文件,许多.cpp,需要怎样编译呢?
下面是一个可行的方法,但看起来还是较为混乱。
在这里插入图片描述

2.2 变量

= (替换赋值)
+= (追加)
:=(常量、立即展开赋值)
?= (询问赋值,若之前赋值过,则不会取后面的值)

TARGET = test.exe #下面所有test.exe都可以用TARGET替换
CC :=gcc

$(TARGET):circle.o cube.o main.o
	$(CC) circle.o cube.o main.o -o $(TARGET)
cube.o:cube.c
	$(CC) -c cube.c -o cube.o
circle.o:circle.c
	$(CC) -c circle.c -o circle.o
main.o:main.c
	$(CC) -c main.c -o main.o
	
.PHONY:
clear:
	rm -rf circle.o cube.o main.o

更进一步的,我们可以使用Obj = .o

TARGET = test.exe #下面所有test.exe都可以用TARGET替换
CC :=gcc
Obj = main.o cube.o circle.o

$(TARGET):$(Obj)
	$(CC) $(Obj) -o $(TARGET)
cube.o:cube.c
	$(CC) -c cube.c -o cube.o
circle.o:circle.c
	$(CC) -c circle.c -o circle.o
main.o:main.c
	$(CC) -c main.c -o main.o
	
.PHONY:
clear:
	rm -rf $(Obj)

2.3 隐含规则

上面编译各个.c文件时,仍要一个一个写,费时费力,所以需要一种新的替换方式来避免每个都写一遍。

%.c 指任意的.c文件
%.o 指任意的.o文件
*.o 所有的.o
TARGET = test.exe #下面所有test.exe都可以用TARGET替换
CC :=gcc
Obj = main.o cube.o circle.o

$(TARGET):$(Obj)
	$(CC) $(Obj) -o $(TARGET)
%.o:%.c
	$(CC) -c %.c -o %.o
	
.PHONY:
clear:
	rm -rf $(Obj)

2.4 通配符

使用通配符来表示一些类似于快捷键的东西

  • $^ 当前依赖文件
  • $@ 当前目标文件
  • $< 当前所有依赖文件的第一个文件
  • $$ 当前进程编号


在C语言中,只有.c文件才会参与编译

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值