从头开始写项目Makefile(九):目录搜索

【版权声明:转载请保留出处:blog.csdn.net/gentleliu。Mail:shallnew at 163 dot com】

在一个较大的工程中,一般会将源代码和二进制文件(.o 文件和可执行文件)安排在不同的目录来进行区分管理。这种情况下,我们可以使用 make 提供的目录搜索依赖文件功能(在指定的若干个目录下自动搜索依赖文件)。在Makefile中,使用依赖文件的目录搜索功能。当工程的目录结构发生变化后,就可以做到不更改 Makefile的规则,只更改依赖文件的搜索目录。

在我们上一节出现的问题当中,我们将.c文件统一放在src目录下,没有和Makefile目录在同一目录下,因此没有办法寻找到.o文件的依赖文件。make程序有一个特殊的变量VPATH,该变量可以指定依赖文件的搜索路径,当规则的依赖文件在当前目录不存在时,make 会在此变量所指定的目录下去寻找这些依赖文件。通常我们都是用此变量来指定规则的依赖文件的搜索路径。

定义变量 “VPATH”时,使用空格或者冒号(:)将多个需要搜索的目录分开。make搜索目录的顺序是按照变量“VPATH”定义中的目录顺序进行的,当前目录永远是第一搜索目录。例如如下定义

VPATH += ./src

指定了依赖搜索目录为当前目录下的src目录,我们可以在Makefile.rules里面添加给VPATH变量赋值,而在包含该Makefile.rules之前给出当前模块.c文件所在目录。

其实我们也可以直接指定依赖文件的路径,这样也是可以的,如下:

$(SRC_OBJ) : $(OBJDIR)/%.o : $(MOD_SRC_DIR)/%.c
>---$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o [email protected]

但是这样在我们更改了工程目录结构之后,对应的依赖文件没有在同一目录下,又变得麻烦了,所以还不如直接给VPATH变量赋值,我们只需要指定源码所在的目录即可。

其实我们还有另外一种搜索文件路径方法:使用vpath关键字(注意不是VPATH变量), 它和VPATH类似,但是它可以为不同类型的文件(由文件名区分)指定不同的搜索目录。使用方法有三种:

1、vpath PATTERN DIRECTORIES

为所有符合模式“PATTERN”的文件指定搜索目录“DIRECTORIES” 。多个目录使用空格或者冒号(:)分开。

2、vpath PATTERN

清除之前为符合模式“PATTERN”的文件设置的搜索路径。

3、vpath

清除所有已被设置的文件搜索路径。

vapth 使用方法中的“PATTERN”需要包含模式字符“%”;例如上面的定义:

VPATH += ./src

可以写为:

vpath %.c ./src

现在给一个我们的Makefile.rules:

# Copyright (C) 2014 shallnew \at 163 \dot com                                                                                                                           

# if without a platform defined, give value "unknow" to PLATFORM
ifndef PLATFORM
>---PLATFORM = unknow
endif

# define a root build directory base on the platform
# if without a SRC_BASE defined, just use local src directory
ifeq ($(SRC_BASE),)
>---BUILDDIR = $(MOD_SRC_DIR)
>---OBJDIR = $(MOD_SRC_DIR)
>---LIBDIR = $(MOD_SRC_DIR)
>---BINDIR = $(MOD_SRC_DIR)
else
>---ifeq ($(DEBUG_SYMBOLS), TRUE)
>--->---BUILDDIR = $(SRC_BASE)/build/$(PLATFORM)_dbg
>---else
>--->---BUILDDIR = $(SRC_BASE)/build/$(PLATFORM)
>---endif
>---OBJDIR = $(BUILDDIR)/obj/$(MODULE)
>---LIBDIR = $(BUILDDIR)/lib
>---BINDIR = $(BUILDDIR)/bin
endif

# update compilation flags base on "DEBUG_SYMBOLS"
ifeq ($(DEBUG_SYMBOLS), TRUE)
>---CFLAGS += -g -Wall -Werror -O0
else
>---CFLAGS += -Wall -Werror -O2
endif

VPATH += $(MOD_SRC_DIR)

SRC_OBJ = $(patsubst %.c, $(OBJDIR)/%.o, $(notdir $(SRC_FILES)))

ifeq ($(MAKELEVEL), 0)
all : msg
else
all : lib bin
endif

lib : $(OBJDIR) $(LIBDIR)/$(SRC_LIB)

bin : $(OBJDIR) $(BINDIR)/$(SRC_BIN)

$(OBJDIR) :
>---mkdir -p [email protected]

ifneq ($(SRC_BIN),)
$(BINDIR)/$(SRC_BIN) : $(SRC_OBJ)
>---$(CC) -o [email protected] $^ $(LDFLAGS)
endif

ifneq ($(SRC_LIB),)
$(LIBDIR)/$(SRC_LIB) : $(SRC_OBJ)
>---$(AR) rcs [email protected] $^
>---cp [email protected] $(SRC_BASE)/libs
endif

$(SRC_OBJ) : $(OBJDIR)/%.o : %.c
>---$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o [email protected]

msg:
>[email protected] "You cannot directily execute this Makefile! This Makefile should called by toplevel Makefile."

# clean target
clean:
ifneq ($(SRC_LIB),)
>--->---$(RM) $(SRC_OBJ) $(LIBDIR)/$(SRC_LIB)
endif
ifneq ($(SRC_BIN),)
>--->---$(RM) $(SRC_OBJ) $(BINDIR)/$(SRC_BIN)
endif

.PHONY : all clean

从头开始写项目Makefile(九):目录搜索

时间: 2024-09-30 11:10:45

从头开始写项目Makefile(九):目录搜索的相关文章

从头开始写项目Makefile(十):make内嵌函数及make命令显示

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 这一节我们讲一下make的函数,在之前的章节已经讲到了几个函数:wildcard.patsubst.notdir.shell等.一般函数的调用格式如下: $(funcname arguments) 或 $(funcname arguments) 其中funcname是需要调用函数的函数名称,应该是make内嵌函数:arguments是函数参数,参数和函数名之间使

从头开始写项目Makefile(六):参数传递、条件判断、include

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 在多个Makefile嵌套调用时,有时我们需要传递一些参数给下一层Makefile.比如我们在顶层Makefile里面定义的打开调试信息变量DEBUG_SYMBOLS,我们希望在进入子目录执行子Makefile时该变量仍然有效,这是需要将该变量传递给子Makefile,那怎么传递呢?这里有两种方法: 1.     在上层Makefile中使用"export&qu

从头开始写项目Makefile(四):伪目标

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 一般情况下,Makefile都会有一个clean目标,用于清除编译过程中产生的二进制文件.我们在第一节的Makefile就用到了这个 clean目标,该目标没有任何依赖文件,并且该目标对应的命令执行后不会生产clean文件. 像这种特点目标,它的规则所定义的命令不是去创建文件,而仅仅通过make指定目标来执行一些特定系统命令或其依赖为目标的规则(如all),称为

从头开始写项目Makefile(五):嵌套执行

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 在大一些的项目里面,所有源代码不会只放在同一个目录,一般各个功能模块的源代码都是分开的,各自放在各自目录下,并且头文件和.c源文件也会有各自的目录,这样便于项目代码的维护.这样我们可以在每个功能模块目录下都写一个Makefile,各自Makefile处理各自功能的编译链接工作,这样我们就不必把所有功能的编译链接都放在同一个Makefile里面,这可使得我们的Ma

从头开始写项目Makefile(三):变量的使用

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 仔细研究我们的之前Makefile发现,我们还有改进的地方,就是此处: target_bin : main.o debug.o ipc.o timer.o tools.o >---gcc -o target_bin main.o debug.o ipc.o timer.o tools.o 如果增加一个源文件xx.c的话,需要在两处或多处增加xx.o文件.我们可以

从头开始写项目Makefile(一):基本规则

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 一般一个稍大的linux项目会有很多个源文件组成,最终的可执行程序也是由这许多个源文件编译链接而成的.编译是把一个.c或.cpp文件编译成中间代码.o文件,链接是就使用这些中间代码文件生成可执行文件.比如在当前项目目录下有如下源文件: # ls common.h debug.c debug.h ipc.c ipc.h main.c tags timer.c ti

从头开始写项目Makefile(零):前言

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 一不小心工作三年了,也就是写了三年代码了,码农生活过的真快.最近发现我们项目的Makefile不够好,于是着手改了一下,以前Makefile写好后就很少动它了,直接在项目之间拷来拷去直接拿来用,这次重新修改项目Makefile,发现自己又学到不少东西,于是乎决定总结一下记录下来与各位苦逼的程序猿一道分享一下. 其实各大论坛博客已经有很多关于Makefile的文章

从头开始写项目Makefile(二):自动推导

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 上一节的Makefile勉强可用,但还写的比较繁琐,不够简洁.对每一个.c源文件,都需要写一个生成其对应的.o目标文件的规则,如果有几百个或上千个源文件,都手动来写,还不是很麻烦,这也不够自动化啊. 这样,我们把生成.o目标文件的规则全部删除掉,就是这样一个Makefile文件: target_bin : main.o debug.o ipc.o timer.o

从头开始写项目Makefile(七):统一目标输出目录

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com] 上一节我们把规则单独提取出来,方便了Makefile的维护,每个模块只需要给出关于自己的一些变量,然后再使用统一的规则Makefile.这一节我们继续改进我们的Makefile,到目前为止我们的Makefile编译链接输出的目标都在源文件同目录下或模块Makefile同一目录下,当一个项目大了之后,这样会显得很乱,寻找编译输出的文件也比较困难.既然Makefil