zoukankan      html  css  js  c++  java
  • 《Makefile解析》

    1.Makefile解析

    1.1Makefile规则:

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

      如果“依赖文件”比“目标文件”更加新,那么执行“命令”来重新生成“目标文件”。

      命令被执行的2个条件:依赖文件比目标文件新,或是 目标文件还没生成。

      $@--目标文件,$^--所有的依赖文件,$<--第一个依赖文件。 

      执行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中以“$(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

     

    3. 通用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
  • 相关阅读:
    动态规划 ------最短路径问题
    回溯算法 ------回溯算法的设计思想和适用条件
    回溯算法 ------ 回溯算法的设计思想及适用条件
    回溯算法 ------回溯算法的几个例子
    纯css实现翻书效果
    从vue源码看props
    js循环中使用async/await踩过的坑
    js实现word转换为html
    从vue源码看Vue.set()和this.$set()
    微信、qq二次分享
  • 原文地址:https://www.cnblogs.com/zhuangquan/p/11776138.html
Copyright © 2011-2022 走看看