目录
一、安装make
sudo apt install make
二、介绍
工程管理器,顾名思义,是指管理较多的文件
目的:编译整个工程文件
Make工程管理器也就是个“自动编译管理器”,这里的“自动”是指它能构根据文件时间戳自动发现更新过的文件而减少编译的工作量如何编译:
make通过读入Makefile文件的内容来执行大量的编译工作
make运行过程
三、 Makefile文件
Makefile是make的读入唯一配置文件。
规则如下:
目标体:依赖文件列表
<tab>命令集合(Linux的命令格式)
例如:file:hello.c
gcc -o hello.c hello
将编译过程分成两个阶段:编译和链接:
最终文件:依赖1 依赖2 依赖3
命令行
依赖1:依赖1->依赖1的依赖
命令行
依赖2:依赖2的依赖
命令行
依赖3:依赖3的依赖
命令行
简单建立一个.c,Makefile文件
make直接运行
四、makefile文件中的变量
在Makefile中可以使用变量,这些变量都是字符串类型,可以表示:
1>一系列文件的名字
2>传递给编译器的参数
3>需要运行的程序名字
4>需要查找的源代码目录
5>需要输出信息的目录
6>其他事件
在Makefile中,变量有三种类型(引用变量$(CC))
1.自定义变量
OBJS = fun1.o fun2.o test.o //也可以 :=(只向上查找依赖 )。//?= 是否有值,无值则赋值。
test : gcc -o test $(OBS)
2.预定于变量(关于C比较常用)
CC C编译器的名称,默认值为cc。
CPP C预编译器的名称,默认值为$(CC) –E。
CFLAGS C编译器的选项,无默认值。
CPPFLAGS C预编译的选项,无默认值。
AR 库文件维护程序的名称,默认值为ar。
AS 汇编程序的名称,默认值为as。
CXX C++编译器的名称,默认值为g++。
FC FORTRAN编译器的名称,默认值为f77
RM 文件删除程序的名称,默认值为rm -f
ARFLAGS 库文件维护程序的选项,无默认值。
ASFLAGS 汇编程序的选项,无默认值。
CXXFLAGS C++编译器的选项,无默认值。
FFLAGS FORTRAN编译器的选项,无默认值。
例如: (-wall表示提示警告)
CC = gcc
CFLAGS = -Wall -g -O0
#自定义变量
OBJS = fun1.o fun2.o test.o
test : $(OBJS)
$(CC) $(CFLAGS) -o test $(OBJS)
fun1.o : fun1.c
$(CC) $(CFLAGS) -c -o fun1.o fun1.c
fun2.o : fun2.c
$(CC) $(CFLAGS) -c -o fun2.o fun2.c
test.o : test.c
$(CC) $(CFLAGS) -c -o test.o test.c
3.自动变量-------makefile中,用一些特殊符号表示,可以直接使用。
自动变量在规则中使用
$^ 所有不重复的目标依赖文件,以空格分开
$@ 目标文件的完整名称
$< 第一个依赖文件名称
$? 所有时间戳比目标文件晚的的依赖文件,并以空格分开
$+ 所有的依赖文件以空格分开,并以出现先后为序,可能包含重复依赖文件
$* 不包含扩展名的目标文件
$% 如果目标是归档成员,则该变量表示目标的归档成员名称
例如:
CC = gcc
CFLAGS = -Wall -g -O0
#自定义变量
OBJS = fun1.o fun2.o test.o
test : $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
fun1.o : fun1.c
$(CC) $(CFLAGS) -c -o $@ $<
fun2.o : fun2.c
$(CC) $(CFLAGS) -c -o $@ $<
test.o : test.c
$(CC) $(CFLAGS) -c -o $@ $<
五、模式规则(规则模板)
使用模板规则可以生成很多相似的规则
用 % 表示具体的文件名称
例如:
下面三个相似的规则:
# CC :C语言编译器
# CFLAGS = -Wall -g -O0
#$@ :完整的任务名
#$< :第一个文件名
fun1.o:fun1.c
$(CC) $(CFLAGS) -C -O $@ $<
fun2.o:fun2.c
$(CC) $(CFLAGS) -C -O $@ $<
test1.o:test.c
$(CC) $(CFLAGS) -C -O $@ $<
可以写成一下模板
%.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
六、makefile中的函数
在makefile中也有一些函数用于对字符串进行处理
例如:
#预定义变量
CC=gcc
CFLAGS =-Wall -g -o
#自定义变量
#BOJS =fun1.o fun2.o fun3.o
BIN =test
#调用在make中的函数
#获取当前目录中所有的.c文件名
SRC = ${wildcard *.c}
#将SRC中对应的.c文件后缀名改为.o,并保存在OBJS中
OBJS = ${patsubst %.c,%.o,$(SRC)}
$(BIN):$(OBJS)
$(CC) $(CFLAGS) -o $@ $^
%.o:%.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
$(RM) $(OBJS) $(BIN)
七、make的选项
-C dir 读取指定目标下的makefile
-f file 读取当前目录下的file文件做为makefile文件
-i 忽略当前所有错误
-I dir 指定被包含的Makefile所在的目录
-n 只打印要执行的命令,但不执行命令
-s 只执行不打印命令
-w 如果make在执行过程中改变目录,打印当前目录名
简单编写三个文件hello.c hello.h,Makefile文件
make运行结果如下:
八、编写整个项目思路
1.以树结构显示Linux的文件
sudo apt install tree
整体思路可以参考总结中的文件。
步骤
1,首先创建好顶层项目makefileTest的文件夹
2,创建需要用到的文件夹
mkdir f1 f2 main obj include
3,在创建相应文件内容
3.1 顶层的Makefile文件如下
CC = gcc
SUBDIRS = f1 \
f2 \
main \
obj
OBJS = f1.o f2.o main.o
BIN = myapp
OBJS_DIR = obj
BIN_DIR = bin
export CC OBJS BIN OBJS_DIR BIN_DIR
all : CHECK_DIR $(SUBDIRS)
CHECK_DIR :
mkdir -p $(BIN_DIR)
$(SUBDIRS) : ECHO
make -C $@
ECHO:
@echo $(SUBDIRS)
@echo begin compile
CLEAN :
@$(RM) $(OBJS_DIR)/*.o
@rm -rf $(BIN_DIR)
3.2 f1下的文件如下:
Makefile文件:将目标文件编译在上一级目录的obj文件中
3.3 f2下的文件也是一样的
3.4include.h文件只放了一个头文件被引用
3.5 main 函数
4,编写各个文件的Makefile文件,将需要用到的文件编译成.o文件放在顶层目录中。
测试:先make CLEAN一下全部文件,此处没有创建任何东西。
5.将顶层目录的的文件同一通过顶层的Makefile文件进行编译。
obj文件的Makefile负责将传递的中间文件全部链接编译成myapp可执行文件放在bin目录下
6.通过终端检测编译结果。
make一下,运行检测。
7. 最后运行可执行文件
成功打印出main函数内容。
九、总结
在文末提供一些关于make的学习文件
http://链接:https://pan.baidu.com/s/1pHnW5vTbwTuxMNPt7FXBsQ 提取码:sv5c