初步学习Makefile
我对Makefile的了解,就是使用make工具对文件进行编译时,使用的编译规则文件。
下面就只介绍在不同文件夹下的文件如何通过Makefile编译文件,更复杂的就不说了,想深入多看看《跟我一起写Makefile》。
使用的平台为ubuntu,gcc编译器(一般安装系统后都自带的),参考了野火《i.MX Linux 开发实战指南》的makefile和大佬的《跟我一起写Makefile》。
1.建立一个文件夹,并进入
mkdir learn_makefile
cd learn_makefile
2.建立相关的文件夹,放头文件的文件夹,放源文件的文件夹,和Makefile
mkdir inc
mkdir src
touch Makefile
3.根据自己的想要的编写的程序写好,放在不同的文件夹下,文件内容我就不贴了,自己想写什么写什么,光打印也可以,反正是C语言的。
├── Makefile
├── inc
│ ├── hello.h
│ └── input.h
└── src
├── hello.c
├── input.c
└── main.c
4.编写Makefile
首先记住在Makefile里,每行行首,必须用Tab键或者不留位置。
然后是关于赋值的相关操作
= 延时赋值,调用的时候才会被赋值
:= 直接赋值,定义的时候就确定,类似C语言的初始化定义。
?= 如果变量值为空,则赋值,一般用于默认赋值
+= 追加赋值,就是增加的新的内容
这四个赋值操作是Makefile必须掌握的。
使用变量的语法:
$(变量名)
这个变量不像C语言的的变量,在Makefile里使用变量,必须要在变量名加这个,变量主要用于不同名字的文件,文件夹的代指。
模式规则:
%.c %表示对文件名的匹配,表示任意长度的非空字符串
其他自动化变量:
$@ 匹配目标文件
$% 与$@类似,但$%仅匹配“库”类型的目标文件
$< 依赖中的第一个目标文件
$^ 所有的依赖目标,如果依赖中的有重复的,只保留一份
$+ 所有的依赖目标,即使依赖有重复的也原样保留
$? 所有比目标要新的依赖文件
使用的函数
$(函数名 参数) 或者 ${函数名 参数}
wildcard 获取文件列表,并使用空格分隔 $(notdir 文件名)
notdir 去除文件路径的目录部分 $(wildcard 匹配规则)
patsubst 模式字符的替换 $(patsubst 匹配规则, 替换规则, 输入的字符串)
根据以上的规则,我们就可以编写简单的Makefile文件
TARGET = main #将要编译的目标,就是编译后需要运行的文件
BUILD_DIR = build #这个编译的文件夹,使用的时候自动赋值给这个了
SRC_DIR = src #存放源文件的文件夹夹
INC_DIR = inc #存放头文件的文件夹
SRCS = $(wildcard $(SRC_DIR)/*.c) #使用函数wildcard 获取所有的源文件名字
INCS = $(wildcard $(INC_DIR)/*.h) #使用函数wildcard 获取所有的头文件名字
OBJS = $(patsbust %.c $(BUILD_DIR)/%.o $(notdir $(SRCS))) #用于OBJS存储所有生成的.o文件,把所有的.c文件替换为同名的.o文件,包括文件目录
CFLAGS = $(patsbust %, -I%, $(INC_DIR)) #获取头文件里的所有文件名,并加上-I,使其在编译的链接到头文件
$(BUILD_DIR)/$(TARGET): $(OBJS)
gcc -o $@ $^ $(CFLAGS) #从.o文件,生成目标文件,但.o文件没有的话,先编译生成.o文件
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
mkdir -p build
gcc -c -o $@ $< $(CFLAGS) #新建build文件夹,从.c生成.o文件
.PHONY: clean
clean:
rm -rf $(BUILD_DIR) #清除build文件夹和里面的文件
我觉得了解到这就行了,我还是去学cmake吧,这个更方便,省事.