Makefile函数

1.Makefile函数
1.1Makefile规则:

目标(target)…: 依赖(prerequiries)…
     <tab>命令(command)

如果“依赖文件”比“目标文件”更加新,那么执行“命令”来重新生成“目标文件”。
  命令被执行的2个条件:依赖文件比目标文件新,或是 目标文件还没生成。
**** @ − − 目 标 文 件 , @--目标文件, @^–所有的依赖文件, < − − 第 一 个 依 赖 文 件 ∗ ∗ ∗ ∗     执 行 m a k e 命 令 时 , 它 会 去 当 前 目 录 下 查 找 名 为 “ M a k e f i l e ” 的 文 件 , 并 根 据 它 的 指 示 去 执 行 操 作 , 生 成 第 一 个 目 标 。     我 们 可 以 使 用 “ − f ” 选 项 指 定 文 件 , 不 再 使 用 名 为 “ M a k e f i l e ” 的 文 件 , 比 如 :     m a k e − f M a k e f i l e . b u i l d     我 们 可 以 使 用 “ − C ” 选 项 指 定 目 录 , 切 换 到 其 他 目 录 里 去 , 比 如 : m a k e − C a / − f M a k e f i l e . b u i l d         我 们 可 以 指 定 目 标 , 不 再 默 认 生 成 第 一 个 目 标 : m a k e − C a / − f M a k e f i l e . b u i l d o t h e r t a r g e t 1.2 即 时 变 量 、 延 时 变 量 变 量 的 定 义 语 法 形 式 如 下 A = x x x / / 延 时 变 量 B ? = x x x / / 延 时 变 量 , 只 有 第 一 次 定 义 时 赋 值 才 成 功 ; 如 果 曾 定 义 过 , 此 赋 值 无 效 C : = x x x / / 立 即 变 量 D + = y y y / / 如 果 D 在 前 面 是 延 时 变 量 , 那 么 现 在 它 还 是 延 时 变 量 ; / / 如 果 D 在 前 面 是 立 即 变 量 , 那 么 现 在 它 还 是 立 即 变 量     在 G N U m a k e 中 对 变 量 的 赋 值 有 两 种 方 式 : 延 时 变 量 、 立 即 变 量     m a k e f i l e 中 以 “ <--第一个依赖文件****   执行make命令时,它会去当前目录下查找名为“Makefile”的文件,并根据它的指示去执行操作,生成第一个目标。   我们可以使用“-f”选项指定文件,不再使用名为“Makefile”的文件,比如:   make -f Makefile.build   我们可以使用“-C”选项指定目录,切换到其他目录里去,比如: make -C a/ -f Makefile.build     我们可以指定目标,不再默认生成第一个目标: make -C a/ -f Makefile.build other_target 1.2即时变量、延时变量 变量的定义语法形式如下 A = xxx // 延时变量 B ?= xxx // 延时变量,只有第一次定义时赋值才成功;如果曾定义过,此赋值无效 C := xxx // 立即变量 D += yyy // 如果D在前面是延时变量,那么现在它还是延时变量; // 如果D在前面是立即变量,那么现在它还是立即变量   在GNU make中对变量的赋值有两种方式:延时变量、立即变量   makefile中以“ <  makeMakefile  使f使Makefile  makefMakefile.build  使CmakeCa/fMakefile.build    makeCa/fMakefile.buildothertarget1.2A=xxx//B?=xxx//C:=xxx//D+=yyy//D//D  GNUmake  makefile(objects)”的方式来使用这个变量了。
1.3 变量的导出(export)
  在编译程序时,我们会不断地使用“make -C dir”切换到其他目录,执行其他目录里的Makefile。如果想让某个变量的值在所有目录中都可见,要把它export出来。
  比如“CC = $(CROSS_COMPILE)gcc”,这个CC变量表示编译器,在整个过程中都是一样的。定义它之后,要使用“export CC”把它导出来。
1.4 Makefile中可以使用shell命令
TOPDIR := $(shell pwd)
  这是个立即变量,TOPDIR等于shell命令pwd的结果。
1.5在Makefile中怎么放置第1个目标
  执行make命令时如果不指定目标,那么它默认是去生成第1个目标。
  所以“第1个目标”,位置很重要。有时候不太方便把第1个目标完整地放在文件前面,这时可以在文件的前面直接放置目标,在后面再完善它的依赖与命令。比如:
First_target: // 这句话放在前面
.... // 其他代码,比如include其他文件得到后面的xxx变量
First_target : $(xxx) $(yyy) // 在文件的后面再来完善
command
1.6假想目标

clean:
    rm -f $(shell find -name "*.o")
    rm -f $(TARGET)

如果当前目录下恰好有名为“clean”的文件,那么执行“make clean”时它就不会执行那些删除命令。
  这时我们需要把“clean”这个目标,设置为“假想目标”,这样可以确保执行“make clean”时那些删除命令肯定可以得到执行。  
  使用下面的语句把“clean”设置为假想目标:
.PHONY : clean
2.常用的函数
2.1foreach

$(foreach var,list,text)

简单地说,就是 for each var in list, change it to text。
对list中的每一个元素,取出来赋给var,然后把var改为text所描述的形式。
例子:

objs := a.o b.o
dep_files := $(foreach  f,  $(objs),  .$(f).d)  // 最终 dep_files := .a.o.d .b.o.d

2.2wildcard

$(wildcard pattern)

pattern所列出的文件是否存在,把存在的文件都列出来。
例子:

src_files := $( wildcard  *.c)  // 最终 src_files中列出了当前目录下的所有.c文件

2.3filter

$(filter pattern...,text)

把text中符合pattern格式的内容,filter(过滤)出来、留下来。
例子:

obj-y := a.o b.o c/ d/
DIR :=  $(filter  %/,  $(obj-y))   //结果为:c/ d/

2.4filter-out
把text中符合pattern格式的内容,filter-out(过滤)出来、扔掉。
例子:

obj-y := a.o b.o c/ d/
DIR :=  $(filter-out  %/,  $(obj-y))   //结果为:a.o  b.o

2.5patsubst
寻找text’中符合格式pattern’的字,用replacement’替换它们。pattern’和`replacement’中可以使用通配符。
例子:

subdir-y    :=  c/  d/
subdir-y    := $(patsubst  %/,  %,  $(subdir-y))   // 结果为:c  d
  1. 通用Makefile的设计思想
    3.1在Makefile文件中确定要编译的文件、目录,比如:
obj-y += main.o
obj-y += a/

“Makefile”文件总是被“Makefile.build”包含的。
3.2在Makefile.build中设置编译规则,有3条编译规则
3.2.1怎么编译子目录? 进入子目录编译:

$(subdir-y):
    make -C $@ -f $(TOPDIR)/Makefile.build

3.2.2怎么编译当前目录中的文件?

%.o : %.c
    $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -Wp,-MD,$(dep_file) -c -o $@ $<

3.2.3当前目录下的.o和子目录下的built-in.o要打包起来:

built-in.o : $(cur_objs) $(subdir_objs)
    $(LD) -r -o $@ $^

3.3顶层Makefile中把顶层目录的built-in.o链接成APP:

$(TARGET) : built-in.o
    $(CC) $(LDFLAGS) -o $(TARGET) built-in.o
$(EXECUTABLE) : $(OBJS)
        $(CC) -o $(EXECUTABLE) $(OBJS) $(addprefix -l,$(LIBS))

( E X E C U T A B L E ) 为 可 执 行 文 件 名 ; (EXECUTABLE)为可执行文件名; (EXECUTABLE)(OBJS)为所有.o文件名; ( C C ) 在 这 里 是 g + + ; (CC)在这里是g++; (CC)g++(addprefix -l,$(LIBS)添加引用库;

前面说好的*.d文件和*.o文件是怎么生成的呢?貌似没有命令指出要生成它们呀!请看隐含规则!

  1. 隐含规则(Implicit rules)

( E X E C U T A B L E ) 依 赖 于 (EXECUTABLE)依赖于 (EXECUTABLE)(OBJS),但makefile中没有指明$(OBJS)依赖于谁,也没指明命令生成它们;

这时,make的隐含规则开始起作用;针对$(OBJS)中的每个目标,make自动调用:

$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@

依次生成.o文件和.d文件;

$<表示依赖文件列表的第一个文件名;

$@表示目标文件名;

之所以会生成.d文件,是由于“-MMD”这一编译选项。为g++加上这一选项后,编译器会生成文件依赖信息,并存放至.d文件中。

每一个.cpp文件相应地生成一个.d文件和一个.o文件。

13.@符号

命令行前的@符号表示不回显命令行;

14.CFLAGS和CPPFLAGS

这两者包含编译选项,更详细内容请Google之。

-g 添加gdb调试信息;

-Wall 提示warning信息;

-O3 表示第3级优化;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值