Linux操作系統從入門到實戰(九)Linux開發工具(中)自動化構建-make/Makefile知識講解

Linux操作系統從入門到實戰(九)Linux開發工具(中)自動化構建-make/Makefile

  • 前言
  • 一、 make/Makefile是什么?
    • 1. 我們先想個問題:手動編譯代碼有多麻煩?
    • 2. 為了解決麻煩,才有了自動化工具
    • 3. 什么是 Makefile ?
    • 4. 什么是 make ?
  • 二、如何使用 make/Makefile
    • 1. 如何創建第一個Makefile?
      • (1) 創建源文件
      • (2) 創建Makefile文件
      • (3) 編寫Makefile規則
      • (4) 執行make命令
    • 2. 依賴關系與命令
      • (1) 依賴關系
      • (2) make的執行邏輯
      • (3) 為什么需要依賴關系?
    • 3. 如何清理編譯結果?
      • (1) 添加clean目標
      • (2) 執行清理命令
      • (3) .PHONY 標簽的作用
    • 4. Makefile的執行規則
      • (1) 默認執行第一個目標
      • (2) 如何執行其他目標?
      • (3) 多個目標的執行順序
    • 5. 常見錯誤與注意事項
      • (1) 命令行必須以Tab鍵開頭
      • (2) 文件名大小寫敏感
  • 三、偽目標是什么,為什么偽目標總被執行?
    • 1. make如何判斷是否需要重新編譯?
    • 2. 什么是偽目標(.PHONY)?
      • (1)定義:
      • (2) 常見用途:
    • 3. 為什么偽目標總是被執行?
      • (1)核心原因:
      • (2) 對比實驗:
    • 4. 為什么需要偽目標?
      • (1) 避免與文件沖突
      • (2) 強制執行命令
    • 5. 常見偽目標示例
      • 1. clean目標(最常見)
      • 2. all目標(批量編譯多個程序)
      • 3. install目標(安裝程序到系統)


前言

  • 前面的博客里我們講解了vim編譯,g++/gcc編譯的步驟和動靜態鏈接與庫的相關知識
  • 接下來我們繼續講解Linux開發工具自動化構建-make/Makefile

我的個人主頁,歡迎來閱讀我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的Linux知識文章專欄
歡迎來閱讀指出不足
https://blog.csdn.net/2402_83322742/category_12879535.html?spm=1001.2014.3001.5482


一、 make/Makefile是什么?

1. 我們先想個問題:手動編譯代碼有多麻煩?

  • 假設你寫了一個小項目,里面有好幾個 .c 源文件(比如 a.cb.cmain.c)。
  • 要讓它們變成能運行的程序,得用 gcc 編譯,比如:
    gcc a.c b.c main.c -o myprogram

這看起來簡單,但如果項目變大呢?

  • 假設有 100 個源文件,每次都手動敲這串命令,累不說,還容易輸錯;
    在這里插入圖片描述

  • 如果只改了 a.c,手動編譯時還得重新編譯所有文件,浪費時間

  • 不同文件有依賴關系(比如 main.c 要用 a.c 的結果),手動編譯得記清順序,錯一步就失敗

2. 為了解決麻煩,才有了自動化工具

就像做復雜的菜時,你需要一份「步驟清單」(先切菜、再炒肉、最后燉),再找個「幫手」按清單一步步做。

在編程里,「步驟清單」就是 Makefile,「幫手」就是 make

3. 什么是 Makefile ?

Makefile 是一個我們自己創建的文件(名字就叫 Makefile,沒有后綴),里面寫的是「編譯規則」

比如在一個 Makefile 里,你可以在里面寫下:

現在看一下代碼,后面會詳細講

# 規則1:最終要生成的程序叫 myprogram,它依賴 a.o、b.o、main.o
myprogram: a.o b.o main.ogcc a.o b.o main.o -o myprogram  # 生成 myprogram 的命令# 規則2:a.o 依賴 a.c
a.o: a.cgcc -c a.c  # 把 a.c 編譯成 a.o(中間文件)# 規則3:b.o 依賴 b.c
b.o: b.cgcc -c b.c# 規則4:main.o 依賴 main.c
main.o: main.cgcc -c main.c

簡單說,Makefile 就像一份「菜譜」:

  • 明確最終要做什么(比如 myprogram 這個程序);
  • 明確需要哪些「原材料」(比如 a.o 這些中間文件);
  • 明確每一步怎么做(比如用什么命令編譯,先編譯哪個、后編譯哪個)。

4. 什么是 make ?

make 是 Linux 自帶的一個命令工具(就像 lscd 一樣,輸入 make 就能運行)。

  • 它的作用很單純:Makefile 里的規則,然后自動執行命令

比如剛才寫好了 Makefile,你在終端敲一句 make,它就會:

  1. 先看最終要生成 myprogram,發現需要 a.ob.omain.o
  2. 檢查這些 .o 文件有沒有,如果沒有,就按規則編譯 a.c 生成 a.o,以此類推;
  3. 最后把所有 .o 文件拼起來,生成 myprogram

如果之后我們只改了 a.c,再敲 make 時,它會聰明地只重新編譯 a.omyprogram,其他沒改的文件不碰——省時間!

二、如何使用 make/Makefile

1. 如何創建第一個Makefile?

(1) 創建源文件

首先,創建一個簡單的C語言程序code.c
在這里插入圖片描述

// code.c
#include <stdio.h>
int main() {printf("Hello, Makefile!\n");return 0;
}

在這里插入圖片描述

(2) 創建Makefile文件

在相同目錄下創建Makefile文件(注意大小寫和文件名):

touch Makefile
vim Makefile

在這里插入圖片描述

(3) 編寫Makefile規則

Makefile中寫入以下內容:

# 目標: 依賴文件
code: code.cgcc -o code code.c  # 注意這行必須以Tab鍵開頭

在這里插入圖片描述

(4) 執行make命令

在終端輸入make,它會自動讀取Makefile并執行編譯:

在這里插入圖片描述

$ make
gcc -o code code.c

此時,當前目錄下會生成可執行文件code,運行它:

$ ./code

在這里插入圖片描述

2. 依賴關系與命令

(1) 依賴關系

在Makefile中,每行規則的基本格式是:

目標文件: 依賴文件列表命令1命令2...
  • 目標文件:要生成的文件(如code
  • 依賴文件:生成目標所需要的文件(如code.c
  • 命令:生成目標的具體操作(如gcc -o code code.c

(2) make的執行邏輯

當你執行make時,它會:

  1. 檢查目標文件是否存在
  2. 如果不存在,或依賴文件比目標文件更新(即依賴文件被修改過)
  3. 則執行對應的命令來生成/更新目標文件

(3) 為什么需要依賴關系?

假設你修改了code.c,再次執行make時:

$ make
make: 'code' is up to date.

make會自動判斷:由于code已存在且code.c未修改,因此無需重新編譯——這就是Makefile智能編譯能力,大大節省時間!

在這里插入圖片描述

3. 如何清理編譯結果?

(1) 添加clean目標

Makefile中新增一個clean目標:

code: code.cgcc -o code code.c.PHONY: clean
clean:rm -f code  # 刪除生成的可執行文件

在這里插入圖片描述

(2) 執行清理命令

當需要刪除編譯結果時,執行:

$ make clean
rm -f code

在這里插入圖片描述

(3) .PHONY 標簽的作用

.PHONY用于聲明clean是一個偽目標(即它不是真正的文件名),防止目錄中真的存在名為clean的文件導致沖突。

4. Makefile的執行規則

(1) 默認執行第一個目標

當你直接輸入make時,它會執行Makefile中的第一個目標(如上面的code)。

(2) 如何執行其他目標?

通過指定目標名來執行特定規則,例如:

$ make clean    # 只執行clean目標下的命令
$ make code     # 只執行code目標下的命令(等同于直接make)

(3) 多個目標的執行順序

Makefile會按照依賴關系自動處理執行順序。例如:

all: program1 program2program1: file1.cgcc -o program1 file1.cprogram2: file2.cgcc -o program2 file2.c

執行make all時,會先編譯program1,再編譯program2

5. 常見錯誤與注意事項

(1) 命令行必須以Tab鍵開頭

在Makefile中,命令行必須以Tab鍵開頭,否則會報錯:

# 錯誤示例(使用空格縮進)
code: code.cgcc -o code code.c  # 錯誤!會提示"*** missing separator.  Stop."# 正確示例(使用Tab鍵縮進)
code: code.cgcc -o code code.c

(2) 文件名大小寫敏感

Makefilemakefile是不同的文件,GNU make默認優先讀取GNUmakefile,然后是makefile,最后是Makefile。建議統一使用Makefile

三、偽目標是什么,為什么偽目標總被執行?

1. make如何判斷是否需要重新編譯?

當我們執行make時,它會檢查兩件事:

  • 目標文件(如code)是否存在
  • 依賴文件(如code.c)的修改時間是否比目標文件更新

如果目標文件不存在,或依賴文件被修改過(修改時間比目標文件晚),make就會執行命令重新生成目標文件。

舉個例子

# Makefile
code: code.cgcc -o code code.c
  • 第一次執行make:生成code文件
  • 第二次執行makemake發現code已存在,且code.c沒修改,==“code”已是最新 ==
    在這里插入圖片描述
$ make
gcc -o code code.c  # 第一次執行,生成code
$ make
make: “code”已是最新  

2. 什么是偽目標(.PHONY)?

(1)定義:

偽目標是用.PHONY聲明的目標,它不代表一個真實的文件,而是一個動作名稱

(2) 常見用途:

  • 清理編譯結果(如clean目標)
  • 執行測試(如test目標)
  • 批量操作(如all目標)

示例:

.PHONY: clean  # 聲明clean是偽目標
clean:rm -f code  # 刪除生成的可執行文件

3. 為什么偽目標總是被執行?

(1)核心原因:

偽目標不對應真實文件,因此make無法檢查它的修改時間
當你執行make 偽目標名時,make會直接執行對應的命令,而不做任何檢查。

(2) 對比實驗:

情況1:普通目標(無.PHONY)

hello:echo "Hello, World!"

執行效果:

$ make hello
echo "Hello, World!"
Hello, World!
$ make hello
make: 'hello' is up to date.  # 第二次不會執行,因為默認認為hello是文件且已存在

情況2:偽目標(有.PHONY)

.PHONY: hello
hello:echo "Hello, World!"

執行效果:

$ make hello
echo "Hello, World!"
Hello, World!
$ make hello
echo "Hello, World!"  # 每次都會執行!因為hello是偽目標
Hello, World!

4. 為什么需要偽目標?

(1) 避免與文件沖突

如果目錄中真的有一個名為clean的文件,會發生什么?

# 錯誤示例:沒有.PHONY的clean目標
clean:rm -f code

此時執行make cleanmake會認為:“clean文件已存在,無需執行任何命令”——這顯然不是你想要的!

(2) 強制執行命令

對于cleantest這類目標,你總是希望它們無條件執行而不是根據文件時間判斷

5. 常見偽目標示例

1. clean目標(最常見)

.PHONY: clean
clean:rm -f *.o       # 刪除所有.o文件rm -f executable  # 刪除可執行文件

2. all目標(批量編譯多個程序)

.PHONY: all
all: program1 program2  # 先編譯program1,再編譯program2program1: file1.cgcc -o program1 file1.cprogram2: file2.cgcc -o program2 file2.c

3. install目標(安裝程序到系統)

.PHONY: install
install:cp program /usr/bin/  # 復制程序到系統目錄

以上就是這篇博客的全部內容,下一篇我們將繼續探索Linux的更多精彩內容。

我的個人主頁
歡迎來閱讀我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的Linux知識文章專欄
歡迎來閱讀指出不足
https://blog.csdn.net/2402_83322742/category_12879535.html?spm=1001.2014.3001.5482

非常感謝您的閱讀,喜歡的話記得三連哦

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/91194.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/91194.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/91194.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

開源b2b2c商城源碼 支持多端適用 含完整代碼包和圖文搭建教程

在電商行業蓬勃發展的當下&#xff0c;b2b2c商城系統成為眾多企業拓展業務版圖的有力工具。這種支持自營與商家入駐并存的系統&#xff0c;含豐富平臺商品種類&#xff0c;能通過多元化運營提升平臺競爭力。本文分享一個開源b2b2c商城源碼的相關知識&#xff0c;并詳細介紹其搭…

Vue3入門-指令補充

&#x1f3e0;個人主頁&#xff1a;Yui_ &#x1f351;操作環境&#xff1a;vscode\node.js &#x1f680;所屬專欄&#xff1a;Vue3 文章目錄1. 指令修飾符1.1 按鍵修飾符1.2 事件修飾符1.3 v-model修飾符2. v-model用在其他表單元素上3. 樣式綁定3.1 操作class4. 操作style5.…

UDP類型套接字

理解UDP協議&#xff1a;互聯網世界的"明信片"通信 UDP是什么&#xff1f;為什么需要它&#xff1f; 想象一下&#xff0c;你正在給朋友寄送兩種不同的東西&#xff1a;一份重要的合同文件和一疊度假時的風景明信片。對于合同文件&#xff0c;你會選擇掛號信&#xf…

redis快速入門教程

更新中基本概念安裝centOS安裝redis&#xff1a;yum install redis -y啟動&#xff1a;systemctl start redis設置開機啟動&#xff1a;systemctl enable redis檢查運行狀態&#xff1a;systemctl status redis遠程訪問編輯配置文件 vi /etc/redis.conf在其中修改為bind 0.0.0.…

UDP和TCP的主要區別是什么

UDP&#xff08;用戶數據報協議&#xff09;和 TCP&#xff08;傳輸控制協議&#xff09;是互聯網傳輸層的兩大核心協議&#xff0c;主要區別體現在??連接方式、可靠性、傳輸效率、頭部開銷??及??適用場景??上。以下是具體對比&#xff1a;??一、核心區別對比表???…

ASP .NET Core 8結合JWT輕松實現身份驗證和授權

身份驗證和授權是每一個后端服務必不可少的&#xff0c;可以實現對非法請求進行攔截&#xff0c;能夠有效保護數據的安全性。 JSON Web Token&#xff08;JWT&#xff09;是一項開放標準&#xff08;RFC 7519&#xff09;&#xff0c;它定義了一種緊湊且自包含的方法&#xff…

5G時代的智慧燈桿:塔能“一桿多用”方案如何激活城市新基建?

在《5G應用“揚帆”行動計劃》持續推進的進程之中&#xff0c;智慧桿已然成為了5G基站部署環節極為重要的載體&#xff0c;并且被明確地歸入到新型基礎設施建設的重點范疇之內。相關政策提出&#xff0c;要在2025年達成重點區域5G網絡全面且深度覆蓋的目標&#xff0c;與此同時…

護照閱讀器:國外證件識別的 OCR “解碼師”

國外證件版式多樣、語種繁雜&#xff0c;人工識別不僅耗時&#xff0c;還易因翻譯誤差、格式不熟悉導致信息錯漏。尤其在跨境業務場景中&#xff0c;傳統識別方式嚴重影響效率與準確性。護照閱讀器搭載的 OCR 技術成為破局關鍵。它能精準提取國外護照、駕照等證件上的多語種文字…

Linux部署Python服務

1、創建項目目錄與虛擬環境#確保安裝 Python 和 python3-venv 工具 sudo apt update sudo apt install python3 python3-pip python3-venvmkdir myproject cd myproject python3 -m venv venv # 創建虛擬環境#Linux source venv/bin/activate # 激活虛擬環境#Windowds venv\S…

【Python辦公】使用Python和Tkinter構建Excel數據導入MySQL工具(GUI版)

目錄 專欄導讀前言項目概述技術棧環境準備核心代碼實現1. 導入必要的庫2. 主應用類設計3. 用戶界面設計數據庫配置區域數據庫選擇區域4. 數據庫連接功能測試連接獲取數據庫列表5. 數據導入功能關鍵技術點解析1. SQLAlchemy 2.x 兼容性2. MySQL 8.0 認證問題3. 避免啟動時連接錯…

華為OD機試_2025 B卷_猜數字(Python,100分)(附詳細解題思路)

題目描述 一個人設定一組四碼的數字作為謎底&#xff0c;另一方猜。 每猜一個數&#xff0c;出數者就要根據這個數字給出提示&#xff0c;提示以XAYB形式呈現&#xff0c;直到猜中位置。 其中X表示位置正確的數的個數&#xff08;數字正確且位置正確&#xff09;&#xff0c;而…

【網絡安全】理解安全事件的“三分法”流程:應對警報的第一道防線

1. 簡介 在網絡安全領域&#xff0c;每天都會產生大量安全警報。作為一名安全分析師&#xff0c;識別、評估并優先處理這些警報的能力至關重要。三分法&#xff08;Triage&#xff09; 是確保安全團隊高效響應安全事件的核心流程&#xff0c;它能夠幫助我們合理分配資源、集中精…

AI大模型計數能力的深度剖析:從理論缺陷到技術改進

AI大模型計數能力的深度剖析&#xff1a;從理論缺陷到技術改進 AI大模型在計數任務上表現出明顯的局限性&#xff0c;這不僅反映了模型架構的核心缺陷&#xff0c;也揭示了當前深度學習技術在處理結構化信息時的本質挑戰。通過對文本計數、圖像計數以及相關技術改進方向的全面分…

[C語言初階]結構體初階

目錄一、結構體的聲明二、結構體的定義和初始化三、結構體成員訪問四、結構體傳參五、函數調用的參數壓棧&#xff08;了解&#xff09;在C語言中&#xff0c;我們知道數組是一組相同類型元素的集合&#xff0c;而結構體則更為靈活&#xff0c;它允許我們將不同類型的數據組合在…

LVS(Linux Virtual Server)集群技術詳解

一.集群和分布式: 集群&#xff1a;同一個業務系統&#xff0c;部署在多臺服務器上&#xff0c;集群中&#xff0c;每一臺服務器實現的功能沒有差別&#xff0c;數據和代碼都是一樣的 分布式&#xff1a;一個業務被拆成多個子業務&#xff0c;或者本身就是不同的業務&#…

leetcode_27 移除元素

1. 題意 給定一個數組&#xff0c;把不等于val的元素全部移動到數組的前面來。 不需要考慮值為val里的元素。 2. 題解 2.1 同向雙指針 我們利用雙指針&#xff0c;慢指針指向下一個插入的位置。而快指針不斷向前找到首個不為val的值&#xff0c;找到后將快指針位置值賦給慢…

Linux-Ubuntu下的git安裝與配置

一、安裝git1.打開終端&#xff0c;運行以下命令&#xff08;需要聯網&#xff09;sudo apt-get update sudo apt-get install git2.驗證安裝安裝完成之后&#xff0c;通過運行以下命令驗證git是否已經正確安裝&#xff1a;git --version二、配置git2.1.配置用戶名及郵箱地址在…

2D和3D激光slam的點云去運動畸變

在使用激光雷達設備采集點云的時候&#xff0c;我們都知道&#xff0c;激光雷達是邊運動邊采集的&#xff0c;每一個點云采集時的激光雷達的中心和姿態都是不一樣的&#xff0c;如果不加以矯正&#xff0c;那么這一幀數據就會出現問題&#xff0c;比如采集一個平面的結構的時候…

Java 熱門面試題 200 道(Markdown表格版)【簡化版】

Java 熱門面試題 200 道(Markdown表格版)【簡化版】 Java與數據庫核心面試題摘要 本文精選200道Java與數據庫高頻面試題,重點涵蓋: Java集合: HashMap原理(數組+鏈表/紅黑樹)、ConcurrentHashMap分段鎖優化、紅黑樹改進目的(解決哈希沖突性能問題) MySQL索引: 最左前…

OpenCV探索之旅:多尺度視覺與形狀的靈魂--圖像金字塔與輪廓分析

在我們學會用Canny算法勾勒處世界的輪廓之后&#xff0c;一個更深層次的問題擺在了面前&#xff1a;這些由像素組成的線條&#xff0c;如何才能被賦予“生命”&#xff0c;成為我們能夠理解和分析的“形狀”&#xff1f;如果一個物體在圖像中時大時小&#xff0c;我們又該如何穩…