Makefile简单归纳

官网:https://www.gnu.org/software/make/

文档:https://www.gnu.org/software/make/manual/

参考:

  • https://seisman.github.io/how-to-write-makefile/overview.html
  • https://makefiletutorial.com/

1. 基本使用

# the first is the final target
main: main.c foo.o bar.o
    gcc main.c foo.o bar.o -o main

foo.o: foo.c
    gcc -c foo.c  
    
bar.o: bar.c
    gcc -c bar.c 

解释:最终目标文件main依赖于main.c和func.o,由gcc生成。func.c一样。

phony

phony即伪目标。Makefile的target默认是文件,而phony的目标是执行程序。

下面的demo支持make clearallmake clear指令。


CC = gcc

main: main.o
	$(CC) main.o -o main
main.o: main.s
	$(CC) -c main.s -o main.o
main.s: main.i
	$(CC) -S main.i -o main.s
main.i: main.c
	$(CC) -E main.c -o main.i

.phony: clean cleanall
clean:
	rm main.i main.s main.o
cleanall:
	rm main.i main.s main.o main

利用伪目标也可以生成多个文件:

all : prog1 prog2 prog3
.PHONY : all

prog1 : prog1.o utils.o
    cc -o prog1 prog1.o utils.o

prog2 : prog2.o
    cc -o prog2 prog2.o

prog3 : prog3.o sort.o utils.o
    cc -o prog3 prog3.o sort.o utils.o

默认目标的特性是,总是被执行的,但由于“all”又是一个伪目标,伪目标只是一个标签不会生成文件,所以不会有“all”文件产生

规则

2. 命令

常用的echo命令,需要加@,这样就不会显示echo xxx了。

异常处理

如果有命令出错,make就会停止。但像mkdir这种命令,出错也应该继续,这种情况可以讲个横杠前缀:

-mkdir FOO

或者make -i

分号

场景:第二条命令在第一条指令的基础上运行

cd /home/hchen; pwd

3. 变量

指定编译器

如果某天不用gcc了,上面的脚本就得手动一个个改。所以可以把编译器保存为变量。

赋值:

  • := 普通赋值;
  • = 递归赋值;
  • += 追加赋值;
  • ?= 条件赋值,左边没定义才会赋值;
CC := g++

main: main.c foo.o
    $(CC) main.c foo.o -o main

foo.o: foo.c
    $(CC) -c foo.c  

其它参数,如参数,目标,也常常作为变量。

CC := g++
TARGET := main
CFLAGS = -lm -Wall -g
$(TARGET): main.c 
    $(CC) $(CFLAGS) main.c -o main

内置变量

Makefile有一些非常有用的变量:

  • $@, 目标文件;
  • $^, 所有的依赖文件
  • $<, 第一个依赖文件。
  • $*, 无扩展名的目标文件
  • $?, 时间戳比目标文件晚的依赖文件
CC := gcc

main: main.o
	$(CC) $^ -o $@

%.o: %.c
	$(CC) -c $^ -o $@

通配符

# 所有.c
objects := $(wildcard *.c)

目标变量

可以理解为局部变量,只在目标对应的规则里生效。

prog : CFLAGS = -g
prog : prog.o foo.o bar.o
    $(CC) $(CFLAGS) prog.o foo.o bar.o

prog.o : prog.c
    $(CC) $(CFLAGS) prog.c

foo.o : foo.c
    $(CC) $(CFLAGS) foo.c

bar.o : bar.c
    $(CC) $(CFLAGS) bar.c

4. 语法

条件语句

ifeq, ifneq

ifeq ($(CC),gcc)
    libs=$(libs_for_gcc)
else
    libs=$(normal_libs)
endif

ifdef

bar =
foo = $(bar)
ifdef foo
    frobozz = yes
else
    frobozz = no
endif

函数

demo:

$(subst ee,EE,feet on the street)

5. 其它

一些参数

-f指定makefile

编译子目录Makefile

subsystem1:
    cd subdir && $(MAKE)
    
subsystem2:
    $(MAKE) -C subdir

$(MAKE)是带了参数的命令行

冲突情况

如果有main1.c和main2.c各有一个main,就只编译第一个。

# 执行
main1: main1.c func.o
    gcc main1.c foo.o -o main1

# 不执行
main2: main2.c func.o
    gcc main2.c foo.o -o main2

# 执行
func.o: func.c
    gcc -c func.c  

clean:
    rm *.o main1 main2

使用all就可以生成两个了.

all: main1 main2

main1: main1.c func.o
    gcc main1.c foo.o -o main1

main2: main2.c func.o
    gcc main2.c foo.o -o main2

func.o: func.c
    gcc -c func.c  

clean:
    rm *.o main1 main2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值