makefile详解(四)

PS:直接从WORD拷贝,未对格式进行仔细整理

5 宏(Macro)

在makefile中可以定义和使用宏。宏的定义的语法是:

define 宏名称

宏值

endef

宏的使用方法和变量的使用方法是一样的。另外我们可以使用ifdef预处理指令判断一个宏是否定义。

例1     宏的使用

MKDIR = mkdir

CP =cp

USRBINDIR=c:/1/2

define installtarget

@echo Installing $@ in $(USRBINDIR) ... ;\

$(MKDIR) -m 7700 $(USRBINDIR)           ;\

$(CP) $@ $(USRBINDIR)/                  ;\

@echo ... done.

endef

 
circle: $(OBJ) $(LIB)
          $(CC) $(LDFLAGS) -o $@ $^
ifdef installtarget
          $(installtarget)
endif

 

在例15中,目标circle的规则的命令会先生成可执行程序circle,然后判断宏installtarget是否存在,如果存在,则将circle拷贝到变量USRBINDIR定义的目录中去。

 

6 预处理指令

在C语言中,我们知道在编译源代码前会进行预处理:基本的操作是分析预处理指令和宏,并展开成“真正意义上的C代码”。

 

Makefile的处理与此类似,在执行makefile之前,make会分析makefile中的预处理指令,宏和变量,并最终在内存中展开成最终的makefile脚本,然后执行它。变量和宏,前提我们都已经介绍过了,这里我们要介绍makefile中的预处理指令。

 

6.1 包含(include)

可以使用include预处理指令在一个makefile文件中包含另外一个makefile文件

例2     使用inlude预处理指令

default.mk文件:

CC := gcc

CFLAGS := -Wall –g –std=c99

LDFLAGS := -lm

 

circle.mk文件:

include default.mk

circle : circle.o circulararea.o

         $(CC) $(LDFLGAS) –o $@  $^

 

%.o :%.c

         $(CC) $(CFLAGS) –o $@ –c $<

 

在例16中,有两个makefle文件:default.mk和circle.mk。其中circle.mk使用include指令包含了default.mk文件。circle.mk文件最终展开的效果与例14是等同的。

 

include指令的存在使得makefiel脚本的共用和模块化成为可能。

 

可以使用include一次包含多个makefile脚本。也可以使用SHELL通配符*和?。例如:

include $(HMOEDINDIR)/myutils.mk  $(SRCDIR)/*.mk

 

还可以使用-include预处理指令,它的效果与include预处理指令是一致的,唯一的区别是:使用-include时,如果找不到要包含的文件,make程序会忽略错误,继续执行。

 

6.2 条件(conditional)

ifdef和ifndef预处理指令,来判断变量或宏是否定义或未定义。需要注意的是,“没有定义的变量”和“值被定义成空的变量”含义是一样的。

例3     使用ifdef预处理指令

OBJ := circle.o

LIB :=-lm

 

ifdef SHAREDLIB

LIB += circulararea.so

else

OBJ += circulararea.o

endif

 

circle: $(OBJ) $(LIB)

     $(CC) –o $@ $^

%.so : %.o

      $(CC) –shared –o $@ $^

 

在本例中,如果SHAREDLIB被定义,则circle将依赖于一个共享链接库circulararea.so,否则则是依赖于circulararea.o

 

ifeq和ifneq预处理指令,用来测试某个条件是否成立。

使用方法如下:

ifeq ($MATCHLIB), /usr/lib/libm.so)

     # do something here

#endif                                                                            

或:

ifeq “$MATCHLIB)”  “/usr/lib/libm.so”

     # do something here

#endif

 

6.3 vpath预处理指令

CC := gcc

CFLAGS := -Wall –g –std=c99

LDFLAGS :=-lm

 

circle : circle.o circulararea.o

         $(CC) $(LDFLGAS) –o $@  $^

 

%.o :%.c

         $(CC) $(CFLAGS) –o $@ –c $<

在上面的makfile脚本中,会编译两个源文件:circle.c和circulararea.c。这里需要提出一个问题,那就是make会到那里去找这两个源文件?默认情况下,make会到当前目录下去寻找源代码文件。但是,如果源代码文件不在当前目录下呢?当然我们可以指定一个相对路径或绝对路径,如下:

CC := gcc

CFLAGS := -Wall –g –std=c99

LDFLAGS :=-lm

SRCDIR := project/src

circle : circle.o circulararea.o

         $(CC) $(LDFLGAS) –o $@  $^

 

%.o :$(SRCDIR)/%.c

         $(CC) $(CFLAGS) –o $@ –c $<

这样make就会到当前路径下的project/src目录下去寻找源文件。但是问题是往往一个项目会有多个目录存放源代码,用上面的方式很明显无法用一个模式规则,处理所有的源代码文件。

好在可以使用vpath预处理指令,它指定与某个特定模式匹配的一类文件名的查找目录。

例4     使用vpath预处理指令

CC := gcc

CFLAGS := -Wall –g –std=c99

LDFLAGS :=-lm

SRCDIR1 := project/src1

SRCDIR2 := project/src2

 

vpath %.c $( SRCDIR1) $( SRCDIR2)

 

circle : circle.o circulararea.o

         $(CC) $(LDFLGAS) –o $@  $^

 

circle.o circulararea.o:%.o : %.c

         $(CC) $(CFLAGS) –o $@ –c $<

 

在例18中,如果make在当前路径下找不到要处理的源代码文件,就会到project/src1和project/src2中去寻找。

 

当然,我们还可以使用vpath去处理其他类型的文件,例如:

vpath %.o $( OBJDIR1) $( OBJDIR2) ……

vpath %.h $( INCDIR1) $(INCDIR2) ……

 

我们还可以使用VPATH内置变量[LU1] 来设置前提文件的查找目录。它与vpath指令的区别是,vpath指令是指定特定类型的前提文件查找目录,而VPATH内置变量则指定了所有类型的前提文件的查找目录。

例5     使用VPATH内置变量

CC := gcc

CFLAGS := -Wall –g –std=c99

LDFLAGS :=-lm

SRCDIR1 := project/src1

SRCDIR2 := project/src2

OBJDIR := project/obj

VPATH= $(SRCDIR1): $(SRCDIR2): $(OBJDIR)

circle : circle.o circulararea.o

         $(CC) $(LDFLGAS) –o $@  $^

 

circle.o circulararea.o:%.o : %.c

         $(CC) $(CFLAGS) –o $@ –c $<

 

VPATH中指定的目录名之间用:分割。

 

在make中,还有一些其他的预处理指令,例如override,export,unexport,由于不经常使用,这里就不一一介绍了。


 [LU1]关于内置变量,除了VPATH外,其他的个人感觉一般都很少会用到,本文档就不做介绍了,读者只需知道内置变量是makefile中固有的变量即可了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值