Linux 自動化構建工具 make/Makefile

来源:https://www.cnblogs.com/helong-123/archive/2022/06/20/16393401.html
-Advertisement-
Play Games

鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 VS中有一鍵編譯+自動運行,Linux也給我們提供了對應的編譯方式,雖然不及VS那麼便捷,但是相比於手動輸入 gcc -o add add.c ,我們一句make就可以搞定 Makefile是一個文件,能夠存放上述 gcc -o add add. ...


鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站

VS中有一鍵編譯+自動運行,Linux也給我們提供了對應的編譯方式,雖然不及VS那麼便捷,但是相比於手動輸入 gcc -o add add.c ,我們一句make就可以搞定

Makefile是一個文件,能夠存放上述 gcc -o add add.c 這種編譯指令

make是一個命令工具,能夠解釋Makefile中的指令

要如何編譯.c文件,關鍵就在於Makefile是怎麼寫的,下麵我們主要介紹這兩者的使用

一、 單個文件的編譯

假設我們要編譯這麼一個test.c文件,我們希望編譯生成一個名為test的可執行文件

file

我們在test.c所在目錄下創建一個Makefile文件,這裡有兩種編譯寫法

1、寫法一:逐個生成.i、.s、.o文件,最後再生成 test執行文件

先一步步向下分析,需要什麼依賴文件,然後再一步步生成

file

編寫好以後,我們只需要在命令行輸入make,系統就會幫我們自動編譯了,同時會生成每一步產生的文件按

file

2、 寫法二:一步到位,直接通過 test.c 生成 test 執行文件(推薦)

Makefile中要寫的內容如下

file

第一行:確定好依賴文件和目標文件。也就是要用依賴文件來生成目標文件

第二行:編譯指令。

            $@ 指向第一行的目標文件,表示目標文件test

            $^ 指向第一行的依賴文件,表示依賴文件test.c

            -std 表示採用的C++標準

接下來我們只需要在命令行輸入make,系統就會幫我們編譯了,編譯成功以後,當前目錄下就會多出一個test 執行文件

file

file

3、 Makefile自動清理

我們每次開始編譯之前,我們最好先清理一下之前生成的執行文件,手動輸入 rm test 有點太麻煩了,Makefile只要寫入下麵的內容,就會自動幫我們清理了

file

如果我們還希望移除生成的.o 、.s、.i文件,那麼第6行只要換成

rm -f test test.o test.s test.i

一般我們make的時候,系統會自動調用,當然也可以手動調用,如

file

file

我們會發現之前的test執行文件不見了

二、多個文件的編譯(同一目錄下)

現在我們有三個文件,分別是test.c、sub.c、sub.h,而且我們要在test.c中調用sub.h中的函數

file

Makefile中的內容如下:

file

test執行文件 要依賴 多個文件生成的 .o文件,現在沒有 .o文件,所以需要重新生成 .o文件

當前路徑下有多個.c文件,我們逐個去寫的話,就是

test.o:test.c
    gcc -c $@ $^
sub.o:sub.c
    gcc -c $@ $^

但是這樣寫太複雜了,我們可以選擇下麵這種寫法

%.o: %.c
    gcc -c $<
  • %.o:表示目標文件是 .o文件

  • %.c:表示依賴文件是當前路徑下的 .c文件,可以看作是一個集合中放著 test.c sub.c

  • $< : 展開%.c ,逐個生成對應的 .o文件,比如test.c就會生成對應的test.o、sub.c就會生成對應的

      sub.o
    

現在我們來運行一下

file

file

三、多個文件的編譯(不同目錄下)

現在我們有三個文件,test.c、sub.h、sub.c,但是其中sub.h、sub.c在其目錄func_dir 下

file

file

Makefile的內容如下:

file

現在我們來運行一下試試

file

file

四、一次生成多個運行文件

1、常規寫法嘗試及其不可行的原因

=常規寫法嘗試=

上面的都是一個main函數文件 + 一堆函數文件的編譯,但是有的時候,比如不同進程間通信時,我們可能需要一次生成兩個運行文件,如果我們按照常規的思路來寫,會怎麼樣?

file

file

測試結果如下,我們發現只生成了一個運行文件,很顯然無法按照常規的寫法來寫

file

=原因分析=

Makefile自動構建結束會生成運行文件,預設只生成最開始的一個,我們寫的時候,server的生成放在client的前面,server就是最開始的哪一個,所以Makefile就只生成了 server

2、改進

Makefile既然生成server以後,就不會繼續生成下一個運行文件,那麼我們就要在這之前就告訴Makefile,我希望生成兩個運行文件(因為Makefile是自頂向下運行的,不會上來就去執行gcc指令)

file

然後我們再來看一下測試結果,現在就能一次生成兩個運行文件了

file

本文轉自:https://blog.csdn.net/challenglistic/article/details/124249349


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 大佬的理解->《Java IO(五) -- 字元流進階及BufferedWriter,BufferedReader》 1、BufferedReader BufferedReader高效字元流讀取文件基本用法,自帶緩衝區,讀取文件效率高,支持逐行讀取; 1.1 初始化 BufferedReader(R ...
  • 游戲的世界精彩紛呈,有動作類、策略類、角色扮演類等諸多類型,還有很多難以分類的小游戲,讓人玩起來往往愛不釋手 ...
  • 大佬的理解->《Java IO(四) -- 字元流》 FileReader字元流讀取文件,更適合用於讀取文件,可以讀取中文 1、FileReader 1.1 初始化 FileReader(File file) FileReader(String fileName) 1.2 讀取文件內容 read() ...
  • 項目全部代碼地址:https://github.com/Tom-shushu/work-study.git (mqtt-emqt 項目) 先看我們最後實現的一個效果 1.手機端向主題 topic111 發送消息,並接收。(手機測試工具名稱:MQTT調試器) 2.控制台列印 MQTT基本簡介 MQTT ...
  • 大佬的理解->《Java IO(三) -- 位元組流》 1、FileInputStream 1.1 初始化 FileInputStream(String name) FileInputStream(File file) //直接通過文件地址初始化 FileInputStream fis = new i ...
  • 第二回 巧習得元素分類 子不知懷璧其罪 雲溪父親見狀看了看雲溪,臉上滲出意思冷汗,但遲疑一下就立即退了出去,匆匆忙忙的往右邊廚房趕,只留下了雲溪和這位神秘的老爺子。 雲溪瞠目結舌的看著悠然自得的喝著老爹泡的茶的老爺子,下意識說了一句:“老先生你怎麼這麼快,還知道我要來這裡”。 “方向,你一直在繞巷子 ...
  • 一、Iproute2簡介 Iproute2是一個在Linux下的高級網路管理工具軟體。實際上,它是通過rtnetlink sockets方式動態配置內核的一些小工具組成的,從Linux2.2內核開始,Alexey Kuznetsov 實現了通過rtnetlink sockets用來配置網路協議棧,它 ...
  • 目錄 一、前景回顧 二、用C語言編寫內核 三、載入內核 四、運行測試 一、前景回顧 本回開始,我們要開始編寫內核代碼了,在此之前,先梳理一下已經完成的工作。 藍色部分是目前已經完成的部分,黃色部分是本節將要實現的。 二、用C語言編寫內核 為什麼要用C語言來編寫內核呢,其實用彙編語言也可以實現,只是對 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...