文章目录
- Makefile工程管理器
- 第一个makefile:编写两个.c源文件,并且让一个调用另外一个,使用makefile建立依赖,生成可执行文件,并执行。
- 伪目标
- 变量
- 预定义变量和自动变量
- 通配符和模式匹配
- 内置函数
- 循环
- 指定makefile文件
- 综合实例:将所有.c文件编译成.o文件
使用环境:Ubuntu18.04
使用工具:VMWare workstations ,xshell
作者在学习Linux的过程中对常用的命令进行记录,通过思维导图的方式梳理知识点,并且通过xshell连接vmware中ubuntu虚拟机进行操作,并将练习的截图注解,每句话对应相应的命令,读者可以无障碍跟练。第三次练习的重点在于Makefile工程管理器的使用。
需要提前安装make,即执行sudo apt install make。
Makefile工程管理器
使用Makefile的步骤非常简单, 先建立一个名为makefile或者是Makefile的文件,然后在里面写入符合语法规则的编译命令,完成以后只需要在文件所在目录使用make命令就能运行编译命令。
第一个makefile:编写两个.c源文件,并且让一个调用另外一个,使用makefile建立依赖,生成可执行文件,并执行。
写法改进:
这里对上述命令中修改依赖内容做一下解释,首先依赖是自上而下查找,如果没有main.o或者func.o,就会继续向下找执行下面的编译。其次,如果修改了func.c,不会再将main.c再编译一遍。只会再执行gcc -c func.c生成func.o目标文件。其好处在于可以节省编译器编译的时间,有利于增量编译。
伪目标
伪目标更倾向于实现其他功能的命令,例如清理二进制文件,重新生成代码等
伪目标的设计主要是避免中间依赖文件和clean、rebuild重名的情况,执行伪目标的用法和一般目标一样 make [target]
变量
Makefile可以定义变量,在调用的时候需要使用**$()**来引用变量,例如可以这么写Makefile文件:
out = main #out代表了main,在运行的时候会进行字符串替代
$(out):main.o func.o
gcc -0 $(out) main.o func.o
因为 = 定义变量会在执行的时候出现字符串替代,所以出现递归定义的时候,会进行递归展开。但是有些情
况,我们不希望递归展开,只希望进行一次字符串替换,这种情况可以采用 := 来定义变量,这也是工作当中
的主流用法。
out := main #out代表了main,在定义完成的时候会进行字符串替代
$(out):main.o func.o
gcc -o $(out) main.o func.o
预定义变量和自动变量
预定义变量就是内部顶一个好的变量,这些变量的含义是固定的,如下:
自动变量就是某些具有特殊含义的变量,它的含义是当前规则有关,如下:
我们利用预定义变量和自动变量改写原来的Makefile文件,如下:
OBJS:=main.o func.o
CC:=gcc
main:$(OBJS)
$(CC) -o $@ $^
main.o:main.c
$(CC) -c $^ -o $@
func.o:func.c
$(CC) -c $^ -o $@
通配符和模式匹配
因为makefile规则的命令部分是采用bash命令的,所以在这里就可以使用bash的规则来应用通配符
clean:rm-rf*.o
makefile也允许对目标文件名和依赖文件名进行类似正则表达式运算的模式匹配,主要使用的是%匹配符(%
表示在依赖文件列表当中匹配任意字符),例如将上述例子改写成
内置函数
- 使用wildcard函数可以使用通配符,找到所有满足通配符的文件名
srcfiles := $(wildcard src/*.c)
- 使用subst函数来实现文本替换
$(subst from,to,text)
- 使用patsubst函数来实现模式文本替换
$(patsubst pattern,replacement,text)
$(patsubst %.c,%.o,func.c main.c)
- 使用notdir函数可以去除文件路径,只留下文件名
循环
写法类似其他语言,不再赘述。
LIST = one two three
all:
for i in $(LIST); do echo $$i; done
#等价于
all:
for i in one two three; do echo $i; done
指定makefile文件
内置函数的案例中已经演示了如何自己指定makefile的文件$ make -f newMake
综合实例:将所有.c文件编译成.o文件
不使用循环的方法,读者自行尝试。
CC:=gcc
SRCS := $(wildcard *.c)
BINS := $(SRCS:%.c=%)
all: $(BINS)
%: %.c
$(CC) $< -o $@
.PHONY:clean
clean:
rm $(TARGETS)