0%

周谈(35)-Makefile基础复习

前言

这周使用cmake构建了一个新工程代码,目录结构参照GmSSL3.0进行了划分,新增的代码和测试代码都编译测试运行OK,也增加了相应的README说明。在我看来,初步版本已经是完整的了。使用cmake可以使得构建中间文件跟源代码分离,而且cmake还提供了安装、打包的功能,已经相当的完善了。初期的工作是完成了。

代码提交审核,呵呵,人家不知道cmake是什么东东(兴许是搞驱动搞久了,没看过太多开源代码吧),也不愿意接纳这个新事物,要求让手写Makefile,觉得这样才更符合C项目的编写惯例。虽然cmake很方便,但是会增加组内成员的学习成本,不方便大家使用。WTF,不懂学习一下不就行了,这么多的优点不值得学一下么?好吧,再搞个Makefile版本。有一句话说的是,”你不可能总是得到你想要的, 你想要的并不是别人要的”。

复习复习Makefile的基础吧。

Makefile

Makefile最主要的就是变量和函数了。

变量

变量的赋值跟shell类似,var=value

取值是$(变量名)或者${变量名}

Makefile还提供了一些默认的变量名:

1
2
3
4
5
6
7
8
9
10
CC=gcc
CFLAGS # 编译选项 如 -g -Wall
LDFLAGS #链接选项

# 命令中使用的自动变量
$@ # 表示规则的目标
$< # 表示规则中的第一个条件
$^: # 表示规则中的所有条件,空格分隔


模式规则

1
2
%.o:%.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

模式规则用来说明依赖文件是如何生成目标文件的,一般就是%号加上后缀,上面的例子表示.c文件如何生成.o文件。

函数

最常用的函数是wildcard, 和patsubst:

  • wildcard 用于获取以某个后缀结尾的所有函数。
  • patsubst 把指定后缀替换为新的后缀,如.c –> .o
1
2
3
4
5
6
7
8
SRC=$(wildcard *.c) # 获取所有.c结尾的文件
OBJS=$(patsubst %.c, %.o, $(SRC)) # SRC中.c替换为.o
TARGET=main
$(TARGET):$(OBJS)
$(CC) $(OBJS) -o $(TARGET)
%.o:%.c
$(CC) -c $< -o $@ # 依赖条件第一个$< 编译成目标文件 $@

伪目标

经常使用make clean或者make all命令来清理或者编译目标,这里的clean和all一般都是伪目标,即不是实际存在的文件, 需要使用.PHONY声明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

SRC=$(wildcard *.c)
OBJS=$(patsubst %.c,%.o,$(SRC))
TARGET=main

.PHONY: all


all: $(TARGET)
@echo "make all"

$(TARGET):$(OBJS)
$(CC) $(OBJS) -o $(TARGET)
%.o:%.c
$(CC) -c $< -o $@
.PHONY:clean
clean:
rm -rf $(OBJS) $(TARGET)

Makefile嵌套

Makefile的嵌套,一种是最外层的Makefile需要包含更深层的Makefile内容,才能编译完成。这种需要使用include关键字包含深层次的Makefile,类似于C语言的include,被include的Makefile内容会展开到对应的外层Makefile。

另外一种是,更深层的Makefile本身就可以独立编译,最外层的Makefile可以调用到内层的Makefile完成功能。最外层可以通过make -C path/to/subdir的命令调用深层次的Makefile编译。

更多的是第三种最外层的Makefile直接包含了所有内层目录的源文件,整个工程就一个Makefile。

如果需要在Makefile间传递变量, 可以使用export关键字,这样深层次的Makefile可以获取到对应的变量值。 在深层次Makefile注意使用?=方式给对应的变量设置默认值。

第一种可以参考linux kernel 生成的Makefile。

第二种参考https://gitee.com/mirrors/intel-ipsec-mb 代码的Makefile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.PHONY: all clean style install uninstall help TAGS

all:
$(MAKE) -C lib
$(MAKE) -C test
$(MAKE) -C perf

clean:
$(MAKE) -C lib clean
$(MAKE) -C test clean
$(MAKE) -C perf clean

style:
$(MAKE) -C lib style
$(MAKE) -C test style
$(MAKE) -C perf style

install:
$(MAKE) -C lib install

uninstall:
$(MAKE) -C lib uninstall

help:
$(MAKE) -C lib help

doxy:
$(MAKE) -C lib doxy

README: README.md
pandoc -f markdown -t plain $< -o $@

... # 省略后续内容


第三种参考 git@gitee.com:kunpengcompute/KAE.git代码的Makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# ...

# Src
SRCDIRS := ${WORK_PATH}/
SRCDIRS += ${WORK_PATH}/alg/pkey
SRCDIRS += ${WORK_PATH}/alg/dh
SRCDIRS += ${WORK_PATH}/alg/ciphers
SRCDIRS += ${WORK_PATH}/alg/digests
SRCDIRS += ${WORK_PATH}/async
SRCDIRS += ${WORK_PATH}/wdmngr
SRCDIRS += ${WORK_PATH}/utils

SRCEXTS := .c # C program


# ...

SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))

OBJS = $(foreach x,$(SRCEXTS), \
$(patsubst %$(x), %.o, $(filter %$(x),$(SOURCES))))

更多

Makefile的基础知识差不多是这些,更多的还可以命令调用不同的shell命令执行想要的操作。最基础的就是使用rm命令清理编译文件了。

在码云gitee上面,基本上都有github上众多知名开源库的镜像库,可以提升我们的下载速度。毕竟很多时候github总是连接不上,如果单纯是下载代码学习的话,推荐直接使用gitee查找开源库代码来下载。

不论是在生活,学习还是工作中,你不可能总是得到你想要的。那么就多学习一些知识,提高自身应对需求的能力吧。

近期长沙开启了降温模式,已然进入了秋天,周末早起带我妈去橘子洲景区走了一圈,让她也在长沙旅游一下。我妈从老家来长沙帮忙带娃,平常一个人在陌生的环境中也不容易,周末有时间带她多走走逛逛了!


行动,才不会被动!

欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。

博客地址: https://fishmwei.github.io

掘金主页: https://juejin.cn/user/2084329776486919