中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Makefile及其工作原理是什么

發布時間:2022-01-25 09:22:23 來源:億速云 閱讀:159 作者:柒染 欄目:開發技術

這篇文章給大家介紹Makefile及其工作原理是什么,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

當你需要在一些源文件改變后運行或更新一個任務時,通常會用到 make 工具。make 工具需要讀取一個 Makefile(或 makefile)文件,在該文件中定義了一系列需要執行的任務。你可以使用 make 來將源代碼編譯為可執行程序。大部分開源項目會使用 make 來實現最終的二進制文件的編譯,然后使用 make install 命令來執行安裝。

依然從打印 “Hello World” 開始。首先創建一個名字為 myproject 的目錄,目錄下新建 Makefile 文件,文件內容為:

  1. say_hello:

  2. echo"Hello World"

myproject 目錄下執行 make,會有如下輸出:

  1. $ make

  2. echo"Hello World"

  3. HelloWorld

在上面的例子中,“say_hello” 類似于其他編程語言中的函數名。這被稱之為目標target。在該目標之后的是預置條件或依賴。為了簡單起見,我們在這個示例中沒有定義預置條件。echo ‘Hello World' 命令被稱為步驟recipe。這些步驟基于預置條件來實現目標。目標、預置條件和步驟共同構成一個規則。

總結一下,一個典型的規則的語法為:

  1. 目標:預置條件

  2. 步驟

作為示例,目標可以是一個基于預置條件(源代碼)的二進制文件。另一方面,預置條件也可以是依賴其他預置條件的目標。

  1. final_target: sub_target final_target.c

  2. Recipe_to_create_final_target

  3. sub_target: sub_target.c

  4. Recipe_to_create_sub_target

目標并不要求是一個文件,也可以只是步驟的名字,就如我們的例子中一樣。我們稱之為“偽目標”。

再回到上面的示例中,當 make 被執行時,整條指令 echo "Hello World" 都被顯示出來,之后才是真正的執行結果。如果不希望指令本身被打印處理,需要在 echo 前添加 @ say_hello:    @echo "Hello World"

重新運行 make,將會只有如下輸出:

  1. $ make

  2. HelloWorld

接下來在 Makefile 中添加如下偽目標:generateclean

  1. say_hello:

  2. @echo"Hello World"

  3. generate:

  4. @echo"Creating empty text files..."

  5. touchfile-{1..10}.txt

  6. clean:

  7. @echo"Cleaning up..."

  8. rm*.txt

隨后當我們運行 make 時,只有 say_hello 這個目標被執行。這是因為Makefile 中的第一個目標為默認目標。通常情況下會調用默認目標,這就是你在大多數項目中看到 all 作為第一個目標而出現。all 負責來調用它他的目標。我們可以通過 .DEFAULT_GOAL 這個特殊的偽目標來覆蓋掉默認的行為。

Makefile 文件開頭增加 .DEFAULT_GOAL

  1. .DEFAULT_GOAL := generate

make 會將 generate 作為默認目標:

  1. $ make

  2. Creatingempty text files...

  3. touchfile-{1..10}.txt

顧名思義,.DEFAULT_GOAL 偽目標僅能定義一個目標。這就是為什么很多 Makefile 會包括 all 這個目標,這樣可以調用多個目標。

下面刪除掉 .DEFAULT_GOAL,增加 all 目標:

  1. all: say_hello generate

  2. say_hello:

  3. @echo"Hello World"

  4. generate:

  5. @echo"Creating empty text files..."

  6. touchfile-{1..10}.txt

  7. clean:

  8. @echo"Cleaning up..."

  9. rm*.txt

運行之前,我們再增加一些特殊的偽目標。.PHONY 用來定義這些不是文件的目標。make 會默認調用這些偽目標下的步驟,而不去檢查文件名是否存在或最后修改日期。完整的 Makefile 如下:

  1. .PHONY: all say_hello generate clean

  2. all: say_hello generate

  3. say_hello:

  4. @echo"Hello World"

  5. generate:

  6. @echo"Creating empty text files..."

  7. touchfile-{1..10}.txt

  8. clean:

  9. @echo"Cleaning up..."

  10. rm*.txt

make 命令會調用 say_hellogenerate

  1. $ make

  2. HelloWorld

  3. Creatingempty text files...

  4. touchfile-{1..10}.txt

clean 不應該被放入 all 中,或者被放入第一個目標中。clean 應當在需要清理時手動調用,調用方法為 make clean

  1. $ make clean

  2. Cleaning up...

  3. rm*.txt

現在你應該已經對 Makefile 有了基礎的了解,接下來我們看一些進階的示例。

進階示例
變量

在之前的實例中,大部分目標和預置條件是已經固定了的,但在實際項目中,它們通常用變量和模式來代替。

定義變量最簡單的方式是使用 = 操作符。例如,將命令 gcc 賦值給變量 CC

  1. CC =gcc

這被稱為遞歸擴展變量,用于如下所示的規則中:

  1. hello: hello.c

  2. ${CC} hello.c -o hello

你可能已經想到了,這些步驟將會在傳遞給終端時展開為:

  1. gcc hello.c -o hello

${CC}$(CC) 都能對 gcc 進行引用。但如果一個變量嘗試將它本身賦值給自己,將會造成死循環。讓我們驗證一下:

  1. CC =gcc

  2. CC = ${CC}

  3. all:

  4. @echo ${CC}

此時運行 make 會導致:

  1. $ make

  2. Makefile:8:***Recursive variable 'CC' references itself (eventually). Stop.

為了避免這種情況發生,可以使用 := 操作符(這被稱為簡單擴展變量)。以下代碼不會造成上述問題:

  1. CC :=gcc

  2. CC := ${CC}

  3. all:

  4. @echo ${CC}

模式和函數

下面的 Makefile 使用了變量、模式和函數來實現所有 C 代碼的編譯。我們來逐行分析下:

  1. #Usage:

  2. #make     # compile all binary

  3. #make clean  # remove ALL binaries and objects

  4. .PHONY = all clean

  5. CC =gcc            # compiler to use

  6. LINKERFLAG =-lm

  7. SRCS := $(wildcard *.c)

  8. BINS := $(SRCS:%.c=%)

  9. all: ${BINS}

  10. %:%.o

  11. @echo"Checking.."

  12. ${CC} ${LINKERFLAG} $

  13. %.o:%.c

  14. @echo"Creating object.."

  15. ${CC}-c $

  16. clean:

  17. @echo"Cleaning up..."

  18. rm-rvf *.o ${BINS}

  • # 開頭的行是評論。

  • .PHONY = all clean 行定義了 allclean 兩個偽目標。

  • 變量 LINKERFLAG 定義了在步驟中 gcc 命令需要用到的參數。

  • SRCS := $(wildcard *.c)$(wildcard pattern) 是與文件名相關的一個函數。在本示例中,所有 “.c”后綴的文件會被存入 SRCS 變量。

  • BINS := $(SRCS:%.c=%):這被稱為替代引用。本例中,如果 SRCS 的值為 'foo.c bar.c',則 BINS的值為 'foo bar'

  • all: ${BINS} 行:偽目標 all 調用 ${BINS} 變量中的所有值作為子目標。

  • 規則:

    下面通過一個示例來理解這條規則。假定 foo 是變量 ${BINS} 中的一個值。% 會匹配到 foo%匹配任意一個目標)。下面是規則展開后的內容:

    如上所示,%foo 替換掉了。$foo.o 替換掉。$用于匹配預置條件,$@ 匹配目標。對 ${BINS} 中的每個值,這條規則都會被調用一遍。

    1. foo: foo.o

    2. @echo"Checking.."

    3. gcc-lm foo.o -o foo

    1. %:%.o

    2. @echo"Checking.."

    3. ${CC} ${LINKERFLAG} $

  • 規則:

    之前規則中的每個預置條件在這條規則中都會都被作為一個目標。下面是展開后的內容:

    1. foo.o: foo.c

    2. @echo"Creating object.."

    3. gcc-c foo.c

    1. %.o:%.c

    2. @echo"Creating object.."

    3. ${CC}-c $

  • 最后,在 clean 目標中,所有的二進制文件和編譯文件將被刪除。

下面是重寫后的 Makefile,該文件應該被放置在一個有 foo.c 文件的目錄下:

  1. #Usage:

  2. #make     # compile all binary

  3. #make clean  # remove ALL binaries and objects

  4. .PHONY = all clean

  5. CC =gcc            # compiler to use

  6. LINKERFLAG =-lm

  7. SRCS := foo.c

  8. BINS := foo

  9. all: foo

  10. foo: foo.o

  11. @echo"Checking.."

  12. gcc-lm foo.o -o foo

  13. foo.o: foo.c

  14. @echo"Creating object.."

  15. gcc-c foo.c

  16. clean:

  17. @echo"Cleaning up..."

  18. rm-rvf foo.o foo

關于Makefile及其工作原理是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

汽车| 鲜城| 涞源县| 武宣县| 沾益县| 昂仁县| 晴隆县| 乡城县| 新乡市| 阳曲县| 毕节市| 通州市| 灯塔市| 南澳县| 北宁市| 苍山县| 彰化市| 宁远县| 元氏县| 桂东县| 新营市| 财经| 长丰县| 威远县| 庆阳市| 五河县| 汶川县| 汉中市| 道孚县| 周口市| 沾益县| 陆川县| 泸州市| 鄱阳县| 七台河市| 福安市| 林口县| 文化| 新建县| 镇雄县| 二连浩特市|