<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系統、金蝶與條碼系統對接、用友與條碼系統對接

    1. Makefile 簡介

    Makefile 是和 make 命令一起配合使用的.

    很多大型項目的編譯都是通過 Makefile 來組織的, 如果沒有 Makefile, 那很多項目中各種庫和代碼之間的依賴關系不知會多復雜.

    Makefile的組織流程的能力如此之強, 不僅可以用來編譯項目, 還可以用來組織我們平時的一些日常操作. 這個需要大家發揮自己的想象力.

     

    本篇博客是基于 {精華} 跟我一起寫 Makefile 而整理的, 有些刪減, 追加了一些示例.

    非常感謝 gunguymadman_cu 提供如此詳盡的Makefile介紹, 這正是我一直尋找的Makefile中文文檔.

     

    1.1 Makefile 主要的 5個部分 (顯示規則, 隱晦規則, 變量定義, 文件指示, 注釋)

    Makefile基本格式如下:

    target ... : prerequisites ...
        command
        ...
        ...

    其中,

    • target        - 目標文件, 可以是 Object File, 也可以是可執行文件
    • prerequisites - 生成 target 所需要的文件或者目標
    • command       - make需要執行的命令 (任意的shell命令), Makefile中的命令必須以 [tab] 開頭

     

    1. 顯示規則 :: 說明如何生成一個或多個目標文件(包括 生成的文件, 文件的依賴文件, 生成的命令)
    2. 隱晦規則 :: make的自動推導功能所執行的規則
    3. 變量定義 :: Makefile中定義的變量
    4. 文件指示 :: Makefile中引用其他Makefile; 指定Makefile中有效部分; 定義一個多行命令
    5. 注釋     :: Makefile只有行注釋 "#", 如果要使用或者輸出"#"字符, 需要進行轉義, "\#"

     

    1.2 GNU make 的工作方式

    1. 讀入主Makefile (主Makefile中可以引用其他Makefile)
    2. 讀入被include的其他Makefile
    3. 初始化文件中的變量
    4. 推導隱晦規則, 并分析所有規則
    5. 為所有的目標文件創建依賴關系鏈
    6. 根據依賴關系, 決定哪些目標要重新生成
    7. 執行生成命令

     

    2. Makefile 初級語法

    2.1 Makefile 規則

    2.1.1 規則語法

    規則主要有2部分: 依賴關系 和 生成目標的方法.

    語法有以下2種:

    target ... : prerequisites ...
        command
        ...

    或者

    target ... : prerequisites ; command
        command
        ...

    *注* command太長, 可以用 "\" 作為換行符

     

    2.1.2 規則中的通配符

    • *     :: 表示任意一個或多個字符
    • ?     :: 表示任意一個字符
    • [...] :: ex. [abcd] 表示a,b,c,d中任意一個字符, [^abcd]表示除a,b,c,d以外的字符, [0-9]表示 0~9中任意一個數字
    • ~     :: 表示用戶的home目錄

     

    2.1.3 路徑搜索

    當一個Makefile中涉及到大量源文件時(這些源文件和Makefile極有可能不在同一個目錄中),

    這時, 最好將源文件的路徑明確在Makefile中, 便于編譯時查找. Makefile中有個特殊的變量 VPATH 就是完成這個功能的.

    指定了 VPATH 之后, 如果當前目錄中沒有找到相應文件或依賴的文件, Makefile 回到 VPATH 指定的路徑中再去查找..

    VPATH 使用方法:

    • vpath <directories>            :: 當前目錄中找不到文件時, 就從<directories>中搜索
    • vpath <pattern> <directories>  :: 符合<pattern>格式的文件, 就從<directories>中搜索
    • vpath <pattern>                :: 清除符合<pattern>格式的文件搜索路徑
    • vpath                          :: 清除所有已經設置好的文件路徑

     

    復制代碼
    # 示例1 - 當前目錄中找不到文件時, 按順序從 src目錄 ../parent-dir目錄中查找文件
    VPATH src:../parent-dir   
    
    # 示例2 - .h結尾的文件都從 ./header 目錄中查找
    VPATH %.h ./header
    
    # 示例3 - 清除示例2中設置的規則
    VPATH %.h
    
    # 示例4 - 清除所有VPATH的設置
    VPATH
    復制代碼

     

    2.2 Makefile 中的變量

    2.2.1 變量定義 ( = or := )

    OBJS = programA.o programB.o
    OBJS-ADD = $(OBJS) programC.o
    # 或者
    OBJS := programA.o programB.o
    OBJS-ADD := $(OBJS) programC.o

    其中 = 和 := 的區別在于, := 只能使用前面定義好的變量, = 可以使用后面定義的變量

    測試 =

    復制代碼
    # Makefile內容
    OBJS2 = $(OBJS1) programC.o
    OBJS1 = programA.o programB.o
    
    all:
        @echo $(OBJS2)
    
    # bash中執行 make, 可以看出雖然 OBJS1 是在 OBJS2 之后定義的, 但在 OBJS2中可以提前使用
    $ make
    programA.o programB.o programC.o
    復制代碼

     

    測試 :=

    復制代碼
    # Makefile內容
    OBJS2 := $(OBJS1) programC.o
    OBJS1 := programA.o programB.o
    
    all:
        @echo $(OBJS2)
    
    # bash中執行 make, 可以看出 OBJS2 中的 $(OBJS1) 為空
    $ make
    programC.o
    復制代碼

     

    2.2.2 變量替換

    復制代碼
    # Makefile內容
    SRCS := programA.c programB.c programC.c
    OBJS := $(SRCS:%.c=%.o)
    
    all:
        @echo "SRCS: " $(SRCS)
        @echo "OBJS: " $(OBJS)
    
    # bash中運行make
    $ make
    SRCS:  programA.c programB.c programC.c
    OBJS:  programA.o programB.o programC.o
    復制代碼

     

    2.2.3 變量追加值 +=

    復制代碼
    # Makefile內容
    SRCS := programA.c programB.c programC.c
    SRCS += programD.c
    
    all:
        @echo "SRCS: " $(SRCS)
    
    # bash中運行make
    $ make
    SRCS:  programA.c programB.c programC.c programD.c
    復制代碼

     

    2.2.4 變量覆蓋 override

    作用是使 Makefile中定義的變量能夠覆蓋 make 命令參數中指定的變量

    語法:

    • override <variable> = <value>
    • override <variable> := <value>
    • override <variable> += <value>

     

    下面通過一個例子體會 override 的作用:

    復制代碼
    # Makefile內容 (沒有用override)
    SRCS := programA.c programB.c programC.c
    
    all:
        @echo "SRCS: " $(SRCS)
    
    # bash中運行make
    $ make SRCS=nothing
    SRCS:  nothing
    
    #################################################
    
    # Makefile內容 (用override)
    override SRCS := programA.c programB.c programC.c
    
    all:
        @echo "SRCS: " $(SRCS)
    
    # bash中運行make
    $ make SRCS=nothing
    SRCS:  programA.c programB.c programC.c
    復制代碼

     

    2.2.5 目標變量

    作用是使變量的作用域僅限于這個目標(target), 而不像之前例子中定義的變量, 對整個Makefile都有效.

    語法:

    • <target ...> :: <variable-assignment>
    • <target ...> :: override <variable-assignment> (override作用參見 變量覆蓋的介紹)

     

    示例:

    復制代碼
    # Makefile 內容
    SRCS := programA.c programB.c programC.c
    
    target1: TARGET1-SRCS := programD.c
    target1:
        @echo "SRCS: " $(SRCS)
        @echo "SRCS: " $(TARGET1-SRCS)
    
    target2:
        @echo "SRCS: " $(SRCS)
        @echo "SRCS: " $(TARGET1-SRCS)
    
    # bash中執行make
    $ make target1
    SRCS:  programA.c programB.c programC.c
    SRCS:  programD.c
    
    $ make target2     <-- target2中顯示不了 $(TARGET1-SRCS)
    SRCS:  programA.c programB.c programC.c
    SRCS:
    復制代碼

     

    2.3 Makefile 命令前綴

    Makefile 中書寫shell命令時可以加2種前綴 @ 和 -, 或者不用前綴.

    3種格式的shell命令區別如下:

    • 不用前綴 :: 輸出執行的命令以及命令執行的結果, 出錯的話停止執行
    • 前綴 @   :: 只輸出命令執行的結果, 出錯的話停止執行
    • 前綴 -   :: 命令執行有錯的話, 忽略錯誤, 繼續執行

     

    示例:

    復制代碼
    # Makefile 內容 (不用前綴)
    all:
        echo "沒有前綴"
        cat this_file_not_exist
        echo "錯誤之后的命令"       <-- 這條命令不會被執行
    
    # bash中執行 make
    $ make
    echo "沒有前綴"             <-- 命令本身顯示出來
    沒有前綴                    <-- 命令執行結果顯示出來
    cat this_file_not_exist
    cat: this_file_not_exist: No such file or directory
    make: *** [all] Error 1
    
    ###########################################################
    
    # Makefile 內容 (前綴 @)
    all:
        @echo "沒有前綴"
        @cat this_file_not_exist
        @echo "錯誤之后的命令"       <-- 這條命令不會被執行
    
    # bash中執行 make
    $ make
    沒有前綴                         <-- 只有命令執行的結果, 不顯示命令本身
    cat: this_file_not_exist: No such file or directory
    make: *** [all] Error 1
    
    ###########################################################
    
    # Makefile 內容 (前綴 -)
    all:
        -echo "沒有前綴"
        -cat this_file_not_exist
        -echo "錯誤之后的命令"       <-- 這條命令會被執行
    
    # bash中執行 make
    $ make
    echo "沒有前綴"             <-- 命令本身顯示出來
    沒有前綴                    <-- 命令執行結果顯示出來
    cat this_file_not_exist
    cat: this_file_not_exist: No such file or directory
    make: [all] Error 1 (ignored)
    echo "錯誤之后的命令"       <-- 出錯之后的命令也會顯示
    錯誤之后的命令              <-- 出錯之后的命令也會執行
    復制代碼

     

    2.4 偽目標

    偽目標并不是一個"目標(target)", 不像真正的目標那樣會生成一個目標文件.

    典型的偽目標是 Makefile 中用來清理編譯過程中中間文件的 clean 偽目標, 一般格式如下:

    .PHONY: clean   <-- 這句沒有也行, 但是最好加上
    clean:
        -rm -f *.o

     

    2.5 引用其他的 Makefile

    語法: include <filename>  (filename 可以包含通配符和路徑)

    示例:

    復制代碼
    # Makefile 內容
    all:
        @echo "主 Makefile begin"
        @make other-all
        @echo "主 Makefile end"
    
    include ./other/Makefile
    
    # ./other/Makefile 內容
    other-all:
        @echo "other makefile begin"
        @echo "other makefile end"
    
    # bash中執行 make
    $ ll
    total 20K
    -rw-r--r-- 1 wangyubin wangyubin  125 Sep 23 16:13 Makefile
    -rw-r--r-- 1 wangyubin wangyubin  11K Sep 23 16:15 makefile.org   <-- 這個文件不用管
    drwxr-xr-x 2 wangyubin wangyubin 4.0K Sep 23 16:11 other
    $ ll other/
    total 4.0K
    -rw-r--r-- 1 wangyubin wangyubin 71 Sep 23 16:11 Makefile
    
    $ make
    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全