makefile 学习总结

    xiaoxiao2021-03-25  121

    makefile学习过程 /*************************************************************************************/ 函数使用方法 1、wildcard : 扩展通配符 2、notdir : 去除路径 3、patsubst :替换通配符 4、foreach 例子: 建立一个测试目录,在测试目录下建立一个名为sub的子目录 $ mkdir test $ cd test $ mkdir sub 在test下,建立a.c和b.c2个文件,在sub目录下,建立sa.c和sb.c2 个文件 建立一个简单的Makefile src=$(wildcard *.c ./sub/*.c) dir=$(notdir $(src)) obj=$(patsubst %.c,%.o,$(dir) ) all:  @echo $(src)  @echo $(dir)  @echo $(obj)  @echo "end"   执行结果分析: 第一行输出: a.c b.c ./sub/sa.c ./sub/sb.c wildcard把 指定目录 ./ 和 ./sub/ 下的所有后缀是c的文件全部展开。 第二行输出: a.c b.c sa.c sb.c notdir把展开的文件去除掉路径信息 第三行输出: a.o b.o sa.o sb.o 在$(patsubst %.c,%.o,$(dir) )中,patsubst把$(dir)中的变量符合后缀是.c的全部替换成.o, 任何输出。 或者可以使用 obj=$(dir:%.c=%.o) 效果也是一样的。 这里用到makefile里的替换引用规则,即用您指定的变量替换另一个变量。 它的标准格式是 $(var:a=b) 或 ${var:a=b} 它的含义是把变量var中的每一个值结尾用b替换掉a $(foreach <var>,<list>,<text>) 这个函数的意思是,把参数<list>;中的单词逐一取出放到参数<var>;所指定的变量中,然后再执行< text>;所包含的表达式。每一次<text>;会返回一个字符串,循环过程中,<text>;的所返回的每个字符串会以空格分隔,最后当整个循环结束时,<text>;所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。 所以,<var>;最好是一个变量名,<list>;可以是一个表达式,而<text>;中一般会使用<var>;这个参数来依次枚举<list>;中的单词。举个例子:     names := a b c d     files := $(foreach n,$(names),$(n).o) 上面的例子中,$(name)中的单词会被挨个取出,并存到变量“n”中,“$(n).o”每次根据“$(n)”计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以,$(files)的值是“a.o b.o c.o d.o”。 注意,foreach中的<var>;参数是一个临时的局部变量,foreach函数执行完后,参数<var>;的变量将不在作用,其作用域只在foreach函数当中。 /*************************************************************************************/ 在一个目录下面有两个子目录,每个子目录下面有.c文件 例如:目录Test Test.c 下面有子目录Sub0和Sub1   子目录Sub0下面有Sub0.c ;子目录Sub1下面有Sub1.c       makefile 里面可以用wildcard函数       src=$(wildcard *.c) $(wildcard ./Sub0/*.c) $(wildcard ./Sub1/*.c)       src里面包含 Test.c Sub0.c Sub1.c .c文件 /*************************************************************************************/ 在Makefile中我们经常看到 = := ?= +=这几个赋值运算符,那么他们有什么区别呢?我们来做个简单的实验 新建一个Makefile,内容为: ifdef DEFINE_VRE     VRE = “Hello World!” else endif ifeq ($(OPT),define)     VRE ?= “Hello World! First!” endif ifeq ($(OPT),add)     VRE += “Kelly!” endif ifeq ($(OPT),recover)     VRE := “Hello World! Again!” endif all:     @echo $(VRE) 敲入以下make命令: make DEFINE_VRE=true OPT=define 输出:Hello World! make DEFINE_VRE=true OPT=add 输出:Hello World! Kelly! make DEFINE_VRE=true OPT=recover  输出:Hello World! Again! make DEFINE_VRE= OPT=define 输出:Hello World! First! make DEFINE_VRE= OPT=add 输出:Kelly! make DEFINE_VRE= OPT=recover 输出:Hello World! Again! 从上面的结果中我们可以清楚的看到他们的区别了 = 是最基本的赋值 := 是覆盖之前的值 ?= 是如果没有被赋值过就赋予等号后面的值 += 是添加等号后面的值 之前一直纠结makefile中“=”和“:=”的区别到底有什么区别,因为给变量赋值时,两个符号都在使用。网上搜了一下,有人给出了解答,但是本人愚钝,看不懂什么意思。几寻无果之下,也就放下了。今天看一篇博客,无意中发现作者对于这个问题做了很好的解答。解决问题之余不免感叹,有时候给个例子不就清楚了吗?为什么非要说得那么学术呢。^_^       1、“=”       make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:             x = foo             y = $(x) bar             x = xyz       在上例中,y的值将会是 xyz bar ,而不是 foo bar 。       2、“:=”       “:=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。             x := foo             y := $(x) bar             x := xyz       在上例中,y的值将会是 foo bar ,而不是 xyz bar 了 /************************************************************************/ ##################################################################### ## file        : test makefile for build current dir .c            ## ## author      : jernymy                                           ## ## date-time   : 05/06/2010                                        ## ##################################################################### CC      = gcc CPP     = g++ RM      = rm -rf ## debug flag DBG_ENABLE   = 1 ## source file path SRC_PATH   := . ## target exec file name TARGET     := test ## get all source files SRCS         += $(wildcard $(SRC_PATH)/*.c) ## all .o based on all .c OBJS        := $(SRCS:.c=.o) ## need libs, add at here LIBS := ## used headers  file path INCLUDE_PATH := . ## used include librarys file path LIBRARY_PATH := /lib ## debug for debug info, when use gdb to debug ifeq (1, ${DBG_ENABLE})     CFLAGS += -D_DEBUG -O0 -g -DDEBUG=1 endif ## get all include path CFLAGS  += $(foreach dir, $(INCLUDE_PATH), -I$(dir)) ## get all library path LDFLAGS += $(foreach lib, $(LIBRARY_PATH), -L$(lib)) ## get all librarys LDFLAGS += $(foreach lib, $(LIBS), -l$(lib)) all: clean build build:     $(CC) -c $(CFLAGS) $(SRCS)     $(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS)     $(RM) $(OBJS) clean:     $(RM) $(OBJS) $(TARGET)
    转载请注明原文地址: https://ju.6miu.com/read-9264.html

    最新回复(0)