• 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/  

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

      

  • 相关阅读:
    javap,是 java printer 的缩写,是 JDK 自带的 Java 字节码分析工具
    这段代码的返回值在出现异常和不出现异常的情况下,分别应该是多少?
    strictfp 关键字修饰方法,即 strict float point (精确浮点)
    transient 修饰符修饰属性:不需要序列化的属性
    Java 中的 CAS 操作
    ReentrantLock 与 synchronized 的比较
    线程安全的实现方法:互斥同步、非阻塞同步、无同步方案
    J.U.C包的意义
    synchronized 原理
    什么场景下,使用 final、volatile、Atomic原子类、synchronized、J.U.C 包中的锁?
  • 原文地址:https://www.cnblogs.com/hypnus-ly/p/8574593.html
Copyright © 2020-2023  润新知