makefile講解

makefile基礎知識linux

一、賦值符號的區別:shell

  =  是最基本的賦值,用到了以後才賦值,不能在變量後追加內容
  :=  是覆蓋以前的值,當即賦值,能夠在變量後追加內容   ?= 是若是沒有被賦值過就賦予等號後面的值   += 是添加等號後面的值
函數

二、自動變量:工具

  $<    第一個依賴文件的名稱
  $?    全部的依賴文件,以空格分開,這些依賴文件的修改日期比目標的建立日期晚
  $@  目標的完整名稱
  $^    全部的依賴文件,以空格分開,不包含重複的依賴文件
ui

三、經常使用的函數:spa

  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)
.net

通用的makefile文件的編譯過程:code

  從頂層開始遞歸進入子目錄,當進入到一個目錄的最底層時,開始使用編譯器編譯,再將該層的全部.o文件打包成build-in.o,返回它的上一層目錄再遞歸進入子目錄,當編譯完全部的子目錄後,就開始編譯頂層的.c文件,最後將頂層的.o文件和頂層每一個子目錄的build-in.o連接成咱們的目標文件。blog

實戰:遞歸

  假如一個目錄結構以下:

  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/  

就是添加該目錄下的文件和子目錄,子目錄要以 / 結尾。

相關文章
相關標籤/搜索