<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    一個通用的Makefile

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    一 makefile的作用

        Makefile是用于自動編譯和鏈接的,一個工程有很多文件組成,每一個文件的改變都會導致工程的重新鏈接,但是不是所有的文件都需要重新編譯,Makefile中記錄有文件的信 息,在make時會決定在鏈接的時候需要重新編譯哪些文件。Makefile的宗旨就是:讓編譯器知道要編譯一個文件需要依賴其他的哪些文件。當那些依賴文件有了改變,編譯器會自動發現最終的生成文件已經過時,而應該重新編譯相應的模塊。 makefile帶來的好處就是—"自動化編譯",一旦寫好,只需要一個make命令,整個工程完全自動編譯,極大的提高了軟件開發的效率。默認的情況下,make命令會在當前目錄下按順序找尋文件名為"GNUmakefile"、"makefile"、"Makefile"的文件,找到了解釋這個文件。當然也可以使用make -f DIR/makefile 來指定用于makefile文件

    二 makefile語法簡述

    2.1 makefile規則

    target ... : dependencies ... 
                command

    target目標文件,可以是Object File,也可以是執行文件,還可以是一個標簽 
    dependencies就是,要生成那個target所需要的文件或是目標。 
    command也就是make需要執行的命令。(任意的Shell命令,可以有若干行)

        這是一個文件的依賴關系,也就是說,target這一個或多個的目標文件依賴于dependencies中的文件,其生成規則定義在command中。dependencies 中如果有一個以上的文件時間要比target文件要新的話,command所定義的命令就會被執行。這就是 Makefile的規則。也就是Makefile中最核心的內容。在Makefile中的命令,必須要以[Tab]鍵開始。

    2.2 變量定義

        Makefile中變量的定義一般有兩種: =和:=。 =符號定義的變量叫延時變量,只有在使用的時候才擴展開來; :=符號定義的變量為立即變量,一旦定義就擴展。 使用=定義的變量不能追加新值,使用:=定義的變量可以使用+=追加新值

    2.3 文件指示

        在Makefile使用include關鍵字可以把別的Makefile包含進來,這很像C語言的#include,被包含的文件會原模原樣的放在當前文件的包含位置。include的語法是:include <filename> filename可以是當前操作系統Shell的文件模式(可以保含路徑和通配符)

    2.4 偽目標

        偽目標并不是一個文件,只是一個標簽,由于偽目標不是文件,所以make無法生成它的依賴關系和決定 它是否要執行。我們只有通過顯示地指明這個目標才能讓其生效。當然,偽目標的取名不能和文件名重名,不然其就失去了偽目標的意義了。當然,為了避免和文件重名的這種情況,我們可以使用一個特殊的標記.PHONY來顯示地指明一個目標是偽目標,向make說明,不管是否有這個文件,這個目標就是偽目標。

    2.5 自動化變量

        $<    第一個依賴文件的名稱

        $?    所有的依賴文件,以空格分開,這些依賴文件的修改日期比目標的創建日期晚

        $@    目標的完整名稱

        $^    所有的依賴文件,以空格分開,不包含重復的依賴文件

     三 通用的makefile實例

    工程必備:

    頂層Makefile 頂層Makefile.build 子目錄Makefile

    編譯過程:

        從頂層開始遞歸進入子目錄,當進入到一個目錄的最底層時,開始使用GCC編譯,再將該層的所有.o文件打包成build-in.o,返回它的上一層目錄再遞歸進入子目錄,當編譯完所有的子目錄后,就開始編譯頂層的.c文件,最后將頂層的.o文件和頂層每個子目錄的build-in.o鏈接成我們的目標文件

    頂層Makefile解析(隨工程而變):

    #----------------------------------------------指定編譯工具鏈---------------------------------------------------

    CROSS_COMPILE =                             #指定編譯器種類

    AS        = $(CROSS_COMPILE)as         #

    LD        = $(CROSS_COMPILE)ld          #鏈接工具

    CC        = $(CROSS_COMPILE)gcc       #編譯工具

    CPP        = $(CC) -E                             #

    AR        = $(CROSS_COMPILE)ar         #打包工具

    NM        = $(CROSS_COMPILE)nm       #

     

    STRIP        = $(CROSS_COMPILE)strip              #優化工具

    OBJCOPY        = $(CROSS_COMPILE)objcopy   #

    OBJDUMP        = $(CROSS_COMPILE)objdump  #

     

    export AS LD CC CPP AR NM                           #將定義的變量導出,方便其他makefile使用

    export STRIP OBJCOPY OBJDUMP                   #將定義的變量導出,方便其他makefile使用

     

    CFLAGS := -Wall -O2 -g                                    #編譯器參數

    CFLAGS += -I $(shell pwd)/include                     #指定編譯器頭文件(根據實際項目手動修改)

    LDFLAGS := -lm -lfreetype -lvga                         #指定編譯器鏈接庫(根據實際項目手動修改)

    export CFLAGS LDFLAGS                                #將定義的變量導出,方便其他makefile使用

    TOPDIR := $(shell pwd)                                     #獲得當前程序的頂層目錄

    export TOPDIR                                                 #輸出頂層目錄

     TARGET := show_file                                      #編譯后的程序名(根據實際項目手動修改)

    #-------------------------頂層要生成的.o文件以及頂層文件夾(根據實際項目手動修改)------------------

    obj-y += main.o

    obj-y += display/

    obj-y += draw/

    obj-y += encoding/

    obj-y += fonts/

    #--------------------------------------------頂層的第一個規則(默認規則)-----------------------------------------

    all :

        make -C ./ -f $(TOPDIR)/Makefile.build           #進入當前目錄,使用頂層的makefile.build進行編譯

        $(CC) $(LDFLAGS) -o $(TARGET) built-in.o    #將編譯好的built-in.o文件鏈接生成我們的目標文件

    #------------------------------------------------頂層的清除規則-------------------------------------------------------

    clean:

        rm -f $(shell find -name "*.o")                        #刪除所有的.o文件

        rm -f $(shell find -name "*.d")                        #刪除所有的.d文件

        rm -f $(TARGET)                                         #刪除目標文件

    .PHONY:all clean

    頂層Makefile.build解析(無需改動):

    PHONY := __build                                        #定義一個PHONY變量

    __build:                                                       #開頭說明__build偽目標,使其成為Makefile.build的第一個目標

    obj-y :=                                                        #定義當前目錄的目標變量,初始值為空

    subdir-y :=                                                   #定義當前目錄的子目錄變量,初始值為空

    include Makefile                                          #將當前目錄的Makefile包含進來,初始化obj-y

                                                                       #obj-y:=a.o b.o c/ d/

    __subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))   #篩選出當前目錄的目標變量中的子目錄,并且去掉/

                                                                                       #$(filter %/, $(obj-y)):c/ d/

                                                                                       #__subdir-y:c d

    subdir-y += $(__subdir-y)                                           #將開始定義的subdir-y賦值為__subdir-y

                                                                                       #subdir-y:c d

    subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)  #對于subdir-y里面的每一個值(目錄),增加一個相應的目錄/built-in.o的變量值

                                                                                       #subdir_objs:c/built-in.o d/built-in.o

    cur_objs := $(filter-out %/, $(obj-y))                            #得到obj-y中的.o文件

                                                                                       #cur_objs:a.o b.o

    dep_files := $(foreach f,$(cur_objs),.$(f).d)                #對于所有的.o文件,定義它的依賴文件名

                                                                                       #dep_files: .a.d .b.d

    dep_files := $(wildcard $(dep_files))

    ifneq ($(dep_files),)                                                    #根據依賴文件名,判斷依賴文件是否存在,存在就包含就來

        include $(dep_files)

    endif

    PHONY += $(subdir-y) #將$(subdir-y)也加入到變量PHONY中

    --------------------------------------------Makefile. build的第一個規則--------------------------------------------------------------

    __build : $(subdir-y) built-in.o                                    #第一個規則

    $(subdir-y):                                                                #第一個規則的第一個依賴規則

        make -C $@ -f $(TOPDIR)/Makefile.build              #依次進入該子目錄變量里面存儲的值,使用的Makefile.build進行編譯

     built-in.o : $(cur_objs) $(subdir_objs)                       #第一個規則的第二個依賴規則

          $(LD) -r -o $@ $^                                                 #該規則的命令:將該目錄下的.o和$(subdir_obj)打包成built-in.o文件

    dep_file = .$@.d                                                        #

    %.o : %.c                                                                   #第一個規則的第二個依賴規則的依賴規則 

    $(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<#用于將目錄下所有的.c文件編譯成.o文件

    .PHONY : $(PHONY)                                                  #將PHONY聲明為偽目標

     子目錄Makefile(隨工程而變):

    子目錄的Makefile就是包含該目錄下所有的目標文件名和子目錄文件夾名。

    例如任何一個子目錄可寫成:

    objs-y := a.o

    objs-y += b.o

    objs-y += c/

    objs-y += d/

    四 示例工程

         http://pan.baidu.com/share/link?shareid=145262&uk=101680913

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全