管理项目
一、条件编译
作用:包含头文件时,防止重复定义
#ifndef _MOD_1_H__
#define
#endif
二、Make和Makefile
2.1 make和Makefile关系
make工具:找出修改过的文件,根据依赖关系,找出受影响的相关文件,最后按照规则单独编译这些文件。
Makefile文件:记录依赖关系和编译规则。
2.2 Makefile三要素
目标、依赖、命令
2.2.1 三要素的关系
目标:依赖的文件或者是其他目标
<tab>命令1
<tab>命令2
<tab>...
target:targeta targetb
echo "target"
targeta:
echo "targeta"
targetb:
echo "targetb"
实验演示:
三、Makefile管理项目
3.1 创建一个mp3.c文件
vim mp3.c
3.2 mp3.c内部代码
#include<stdio.h>
void play()
{
printf("play music!\r\n");
}
void end()
{
printf("end music!\r\n");
}
3.3 创建一个main.c文件
vim main.c
3.4 main.c内部代码
#include<stdio.h>
int main()
{
play();
end();
return 0;
}
3.5 用gcc编译器编译两个vi文件并整合到新文件mp3中
gcc main.c mp3.c -o mp3
程序演示
3.6 创建一个makefile文件
vim makefile
3.7 makefile内部代码
mp3:mp3.o main.o //目标:依赖的文件1 依赖的文件2
gcc -c main.o mp3.o -o mp3 //将main.o和mp3.o文件编译成新的文件并重命名为mp3
mp3.o:
gcc -c mp3.c -o mp3.o //将mp3.c文件编译成mp3.o可执行文件
main.o:
gcc -c main.c -o main.o //将main.c文件编译成main.o可执行文件
.PHONY:clean //伪目标:告诉make工具,当前文件系统不需要目标文件 每次都会执行
clean:
rm mp3
程序演示
四、Makefile的变量、模式匹配
4.1 变量
系统变量 | 含义 |
---|---|
OBJS | 依赖工程 |
CFLAGS | -g -Wall |
CC | gcc |
自定义变量 | 含义 |
---|---|
= | 延迟赋值 |
:= | 立即赋值 |
?= | 空赋值 |
+= | 追加赋值 |
自动化变量 | 含义 |
---|---|
$< | 第一个依赖文件 |
$^ | 全部的依赖文件 |
$@ | 目标 |
模式匹配 | 含义 |
---|---|
% | 匹配任意多个非空字符 |
* | 通配符 |
4.1.1 系统变量
4.1.2 自定义变量
=,延迟赋值
:=, 立即赋值
?=,空赋值
+=,追加赋值
4.1.3 自动化变量
$<:第一个依赖文件
$^:全部的依赖文件
$@:目标
4.2 模式匹配
%:匹配任意多个非空字符
shell:*通配符
4.2.1 用自动化变量更改原makefile文件
程序代码:
CC=gcc
TARGET=mp3
OBJS=main.o mp3.o
$(TARGET):$(OBJS)
$(CC) $^ -o $@
%.o:%.c
$(CC) -c $< -o $@
.PHONY:clean
clean:
rm mp3
4.3 默认规则
.o文件默认使用.c文件来进行编译
程序代码:
CC=gcc
TARGET=mp3
OBJS=main.o mp3.o
$(TARGET):$(OBJS)
$(CC) $^ -o $@
.PHONY:clean
clean:
rm mp3
五、Makefile条件分支
5.1 条件分支
ifeq (var1,var2)
...
else
...
endif
ifneq (var1,var2)
...
else
...
endif
六、Makefile的常用函数
Makefie官方手册:
https://www.gnu.org/software/make/manual
6.1 patsubst:模式替换函数
$ (patsubst,PATTERN,REPLACEMENT,TEXT)
将TEXT内符合PATTERN(模式一)的内容格式替换为REPLACEMENT(模式二)的内容格式
6.2 notdir:取文件名函数
$ (notdir src/foo.c hacks)
6.3 wildcard:获取匹配模式文件名函数
$ (wildcard *.c)
6.4 foreach:循环函数
$ (foreach dir, $(dir),TEXT)
七、Makefile解决头文件依赖
写一个头文件,并把头文件添加到编译器的头文件路径中。
gcc -I +“头文件路径”
实时检查头文件的更新情况,一旦头文件发生变化,应该要重新编译所有相关文件。
gcc -MM
ARCH ?= x68
ifneq ($(ARCH),x86)
CC=gcc
else
CC=arm-linux-gnueabihf-gcc
endif
TARGET=mp3
BUILD_DIR=build
SRC_DIR=module1 module2
INC_DIR=include
CFLAGS=$(patsubst %,-I%,$(INC_DIR))//-I include
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))//获取include目录下mp3.h文件
SOURCES=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))//获取module1,2目录下的mp3.c main.c
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES))) //mp3.o main.o
VPATH=$(SRC_DIR)
$(BUILD_DIR)/$(TARGET):$(OBJS)
$(CC) $^ -o $@
$(BUILD_DIR)/%.o:%.c $(INCLUDES) | create_build
$(CC) -c $< -o $@ $(CFLAGS)
.PHONY:clean create_build
clean:
rm -r $(BUILD_DIR)
create_build:
mkdir -p $(BUILD_DIR)
build——存放最后的生成文件
include——mp3.h
module1——mp3.c
module2——main.c
拓展:
.PHONY:可以指定伪目标
告诉make工具,当前文件系统里不需要targetb目标文件,每次都会执行