make--路径搜索
make中的路径搜索
1、特殊的预定义变量VPATH(全大写)
- VPATH变量的值用于指示make如何查找文件
- 不同文件夹作为VPATH的值同时出现
- 文件夹的名字之间需要使用分隔符进行区分
VPATH := inc src //空格作为分隔符
VPATH := inc;src //分号作为分隔符
VPATH := inc:src //冒号作为分隔符
make对于VPATH值的处理方式
- 当前文件夹找不到需要的文件时,VPATH会被使用
- make会在VAPTH指定的文件夹中依次搜索文件
- 当多个文件夹存在同名文件时,选择第一次搜索到的文件
注意事项:
- VPATH只能决定make的搜索路径,无法决定命令的搜索路径
- 对于特定的编译命令(gcc),需要独立指定编译搜索路径
- VPATH缺陷:
当多个文件夹存在同名文件时,选择第一次搜索到的文件,可能会导致编译错误,选择的文件不一定是目标路径下的文件
gcc -I include-path
/*-I 编译选项,指定gcc的头文件搜索路径;
include-path 路径参数,gcc搜索的路径*/
**示例1–VPATH变量指定文件查找路径与gcc -I 指定头文件路径结合使用 **
./inc/func.h
#ifndef FUNC_H
#define FUNC_H
#define HELLO "hello world"
void foo();
#endif
./src/func.c
#include "func.h"
void foo()
{
printf("void foo():%s\n",HELLO);
}
./src/main.c
#include "stdio.h"
#include "func.h"
extern void foo();
int main()
{
foo();
return 0;
}
./makefile
OBJS := func.o main.o
INC := inc
SRC := src
VPATH := $(SRC) $(INC)
CFLAGS := -I $(INC)
hello.out : $(OBJS)
@gcc -o [email protected] $^
@echo "Target File ==> [email protected]"
$(OBJS) : %.o : %.c func.h
@gcc $(CFLAGS) -o [email protected] -c $<
2、关键字vpath(全小写)
- 为不同类型的文件指定不同的搜索路径
- 语法:
在Directory中搜索符合Pattern规则的文件
vpath Pattern Directory
//例如:
vpath %.h inc
vpath %.c inc
** 示例2 vpath替换VPATH**
将示例1中makefile文件中的以下内容做替换:
VPATH := $(SRC) $(INC)
替换为
vpath %.h $(INC)
vpath %.c $(SRC)
可以解决VPATH变量的缺陷(多个文件夹中出现同名文件),make编译时从指定的文件夹下去找需要的文件,而不是选择第一次搜索到的文件。
- 取消搜索规则
- 取消已经设置的某个搜索规则
vpath Pattern
//例如:
vpath %.h inc //在inc中搜索.h文件
...
vpath %.h //不再到inc中搜索.h文件
- 取消所有已经设置的规则
vpath
示例3–vpath关键字取消搜索规则
将示例1中的makefile增加语句:vpath %.h
,修改后的makefile文件如下:
//makefile
OBJS := func.o main.o
INC := inc
SRC := src
VPATH := $(SRC) $(INC)
CFLAGS := -I $(INC)
hello.out : $(OBJS)
@gcc -o [email protected] $^
@echo "Target File ==> [email protected]"
vpath %.h //不再到inc文件夹下搜索.h文件
$(OBJS) : %.o : %.c func.h
@gcc $(CFLAGS) -o [email protected] -c $<
VPATH变量与vpath关键字小结:
- VPATH变量用于指示make如何查找文件
- make会在VPATH指定的文件夹中依次搜索文件
- vpath关键字可以为不同类型的文件指定不同的搜索路径
- vpath比VPATH更灵活易用,可动态设置/取消搜索路径
- VPATH与vpath同时出现,make的搜索路径:
- make首先在当前文件夹搜索需要的文件
- 如果失败:
- make优先在vpath指定的文件夹中搜索目标文件
- 当vpath搜索失败时,转而搜索VPATH指定的文件夹
示例4–make搜索路径–vpath与VPATH同时出现
//以下代码执行后,make搜索路径为:src2->src1->src3
VPATH := src1 src3
vpath %.c src2
- 当使用vpath对同一个Pattern指定多个文件夹时,make的搜索路径:
- make首先在当前文件夹搜索需要的文件
- 如果失败:
- make以自上而下的顺序搜索vpath指定的文件夹
- 当找到目标文件,搜索结束;找不到则直接报错
//以下代码执行后,make搜索路径为:src3->src1->src2
vpath %.c src3
vpath %.c src1
vpath %.c src2
- 通过VPATH指定搜索路径后,make如何决定目标文件的最终位置
4、路径搜索综合示例
(1)需求:
- 工程项目中不希望源码文件夹在编译时改动(只读文件夹)
- 在编译时自动创建文件夹(build)用于存放编译结果
- 编译过程中能够自动搜索需要的文件 - makefile易于扩展,能够复用于相同类型的项目
- 支持调试版本的编译选项
(2)项目结构
(3)工具原料
- $(wildcard $(DIR)/ _pattern)
- 获取$(DIR)文件夹中满足_pattern的文件
- $(notdir _names)
- 去除_names中每一个文件名的路径前缀
- $(patsubst _pattern,replacement,_text)
- 将_text中符合_pattern的部分替换为replacement
(4) 关键技巧
- 自动获取源文件列表(函数调用)
- SRCS := $(wildcard src/* .c)
- 根据源文件列表生成目标文件列表(变量的值替换)
- OBJS := $(SRCS:.c=.o)
- 替换每一个目标文件的路径前缀(函数调用)
- OBJS := (OBJS))
(5) 编译规则的依赖
makefile
.PHONY : all cleancd ..
DIR_BUILD := build
DIR_INC := inc
DIR_SRC := src
TYPE_INC := .h
TYPE_SRC := .c
TYPE_OBJ := .o
CC := gcc
LFLAGS :=
CFLAGS := -I $(DIR_INC)
ifeq ($(DEBUG),true)
CFLAGS += -g
endif
MKDIR := mkdir
RM := rm -rf
APP := $(DIR_BUILD)/app.out
HDRS := $(wildcard $(DIR_INC)/* $(TYPE_INC))
HDRS := $(notdir $(HDRS))
OBJS := $(wildcard $(DIR_SRC)/* $(TYPE_SRC))
OBJS := $(OBJS:$(TYPE_SRC)=$(TYPE_OBJ))
OBJS := $(patsubst $(DIR_SRC)/%,$(DIR_BUILD)/%,$(OBJS))
vpath %$(TYPE_SRC) $(DIR_SRC)
vpath %$(TYPE_INC) $(DIR_INC)
all : $(DIR_BUILD) $(APP)
@echo "Target File ==> $(APP)"
$(DIR_BUILD) :
$(MKDIR) [email protected]
$(APP) : $(OBJS)
$(CC) -o [email protected] $^
$(DIR_BUILD)/%$(TYPE_OBJ) : %$(TYPE_SRC) $(HDRS)
$(CC) $(CFLAGS) -o [email protected] -c $<
clean :
$(RM) $(DIR_BUILD)