zoukankan      html  css  js  c++  java
  • makefile讲解

    makefile基础知识

    1、赋值符号的区别:

      =  是最基本的赋值,用到了之后才赋值,不能在变量后追加内容
      :=  是覆盖之前的值,立即赋值,可以在变量后追加内容   ?= 是如果没有被赋值过就赋予等号后面的值   += 是添加等号后面的值

    2、自动变量:

      $<    第一个依赖文件的名称
      $?    所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚
      $@  目标的完整名称
      $^    所有的依赖文件,以空格分开,不包含重复的依赖文件

    3、常用的函数:

      1. $(patsubst %.c,%.o,x.c.cbar.c)
      把字串“x.c.cbar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o bar.o”
      2.$(filter <pattern...>,<text> )
      以<pattern>模式过滤<text>字符串中的单词,保留符合模式<pattern>的单词。可以有多个模式。 
      3.$(filter-out <pattern...>,<text> )
      4.$(foreach <var>,<list>,<text> )
      把参数<list>中的单词逐一取出放到参数<var>所指定的变量中, 然后再执行<text>所包含的表达式。每一次<text>会返回一个字符串,循环这个过程。
      5.shell函数,例如files := $(shell echo *.c)

    通用的makefile文件的编译过程:

      从顶层开始递归进入子目录,当进入到一个目录的最底层时,开始使用编译器编译,再将该层的所有.o文件打包成build-in.o,返回它的上一层目录再递归进入子目录,当编译完所有的子目录后,就开始编译顶层的.c文件,最后将顶层的.o文件和顶层每个子目录的build-in.o链接成我们的目标文件。

    实战:

      假如一个目录结构如下:

      a

      ----d

      ----a.c

      b

      ----b.c

      c

      ----c.c

      main.c

      makefile

      makefile.built

    顶层的Makefile

     #定义各个编译用到的工具
    CROSS_COMPILE =         #交叉编译器 arm-none-Linux-gnueabi- AS = $(CROSS_COMPILE)as #汇编器 LD = $(CROSS_COMPILE)ld #连接器 CC = $(CROSS_COMPILE)gcc #编译器 CPP = $(CC) -E #预处理 AR = $(CROSS_COMPILE)ar #归档文件 NM = $(CROSS_COMPILE)nm   #列出object文件中的符号 STRIP = $(CROSS_COMPILE)strip  #丢弃目标文件中的符号 OBJCOPY = $(CROSS_COMPILE)objcopy #转换目标文件格式 OBJDUMP = $(CROSS_COMPILE)objdump #反汇编 export AS LD CC CPP AR NM #将变量导出供下一个makefile使用 export STRIP OBJCOPY OBJDUMP CFLAGS := -Wall -O2 -g #CFLAGS 指定编译参数
    #CFLAGS += -I $(shell pwd)/include
    LDFLAGS :
    = export CFLAGS LDFLAGS TOPDIR := $(shell pwd) export TOPDIR TARGET := test obj-y += main.o  #obj-y  main.o 编译链接进项目 obj-y += a/ obj-y += b/ obj-y += c/ all :
      # make的递归执行,make的“-C”选项,是首先进入子目录而后再执行make。
      #当需要将一个普通命名的文件作为makefile文件时,需要使用make的“-f”、“--file”或者“--makefile”选项来指定。
    make -C ./ -f $(TOPDIR)/Makefile.build $(CC) $(LDFLAGS) -o $(TARGET) built-in.o clean: rm -f $(shell find -name "*.o") #删除命令,默认是 rm -f rm -f $(shell find -name "*.d") rm -f $(TARGET)

    #执行make时,目标“all”被作为终极目标。
    #伪目标”并不是一个文件,只是一个标签,由于“伪目标”不是文件,所以make无法生成它的依赖关系和决定它 是否要执行。
    #我们只有通过显示地指明这个“目标”才能让其生效。
    #为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显示地指明一个目标是“伪目标”,向make说明,
    #不管是否有这个文件,这个目标就是“伪目标”。 .PHONY:all clean

    Makefile.build

        PHONY := build    #定义一个PHONY变量
        build :  #开头说明build伪目标,使其成为Makefile.build的第一个目标
        obj-y :=  
        subdir-y :=  
        include Makefile  
        __subdir-y  := $(patsubst %/,%,$(filter %/, $(obj-y)))  #筛选出当前目录的目标变量中的子目录,并且去掉/,在这里我们获得了子目录的名字
        subdir-y    += $(__subdir-y)  
        subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)  #对于subdir-y里面的每一个值(目录),增加一个相应的目录/built-in.o的变量值
        cur_objs := $(filter-out %/, $(obj-y))  # 得到obj-y中的.o文件
        dep_files := $(foreach f,$(cur_objs),.$(f).d)  # .$(f).d 第一个.表示隐藏的 后面的.表示后缀
        dep_files := $(wildcard $(dep_files))  
       #ifneq ($(dep_files),) # include $(dep_files) #endif PHONY += $(subdir-y) build : $(subdir-y) built-in.o $(subdir-y): make -C $@ -f $(TOPDIR)/Makefile.build built-in.o : $(cur_objs) $(subdir_objs) $(LD) -r -o $@ $^ dep_file = .$@.d %.o : %.c $(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $< .PHONY : $(PHONY)

    子目录下的Makefile

        obj-y += a.o  
        obj-y += d/  

    就是添加该目录下的文件和子目录,子目录要以 / 结尾。

      

  • 相关阅读:
    SpringBoot 应用程序启动过程探秘
    git创建分支并推送远程
    idea中@Autowired注解下变量报红
    java.lang.IllegalStateException: Either 'name' or 'value' must be provided in @FeignClient的解决方案
    项目启动中报错Address already in use: bind的解决方案
    Maven配置阿里云镜像和配置jdk1.8编译项目
    MySQL优化之Explain
    英文字母和中文汉字在不同字符集编码下的字节数
    Netty中两种Keepalive的区别
    @ConfigurationProperties和@Value的区别
  • 原文地址:https://www.cnblogs.com/hypnus-ly/p/8574593.html
Copyright © 2011-2022 走看看