linux環境下的GUN make學習筆記(一)

来源:http://www.cnblogs.com/jhmu0613/archive/2017/10/30/7754475.html
-Advertisement-
Play Games

第一章:概述 1.1:make概述 在linux環境下使用make工具能夠比較容易的構建一個屬於自己的工程,整個工程的編譯只需要一個命令就可以完成編譯、連接以至於最後的執行。不過我們需要投入一些時間去學習如何完成makefile文件的編寫,這個文件也是make正常工作的基礎。 所要完成的makefi ...


第一章:概述

1.1:make概述

  在linux環境下使用make工具能夠比較容易的構建一個屬於自己的工程,整個工程的編譯只需要一個命令就可以完成編譯、連接以至於最後的執行。不過我們需要投入一些時間去學習如何完成makefile文件的編寫,這個文件也是make正常工作的基礎。

  所要完成的makefile文件描述了整個工程的編譯、連接等規則。其中包括:工程中的哪些源文件需要編譯以及如何編譯、需要創建那些庫文件以及如何創建這些庫文件、如何最後產生我們想要的可執行文件。

  make是一個命令工具,他解釋了makefile中的指令。在makefile文件中描述了整個工程所有文件的編譯順序、編譯規則。makefile有自己的書寫格式,關鍵字、函數。想c語言有自己的格式、關鍵字和函數一樣。而且在makefile中可以使用系統shell所提供的任何命令來完成想要的工作。

1.2:準備知識

  在討論make之前首先需要明確一些基本概念:

  編譯:把高級語言書寫的代碼轉換為機器可識別的機器指令。編譯後產生的機器指令雖然可被機器識別,但是還不能被執行。編譯時,編譯器檢察高級語言的語法、函數與變數的聲明是否正確。只有所有語法正確、相關變數定義正確,編譯器就可以編譯出中間目標文件。通常一個高級語言的源文件都可對應一個目標文件。目標文件在linux中預設尾碼為“.o”。

  鏈接:將多個目標文件,或者目標文件和庫文件鏈接稱為可被操作系統執行的可執行程式。鏈接器不檢查函數所在的源文件,只檢查所有目標文件的定義的符號。將目標文件使用的函數和其他目標或者庫文件中的相關符號進行合併,並對所有文件中的符號進行重新安排,並連接系統相關文件最終生成可執行程式。

  靜態庫:又稱文檔文件,十多個目標文件的集合。

  共用庫:也是多個目標文件的集合,但是這些目標文件按照一種特殊的方式生成。模塊中各個成員的地址都是相對地址。使用此共用庫的程式在運行時,共用庫被動態載入到記憶體並和主程式在記憶體中進行鏈接。多個可執行程式可共用庫文件中的代碼段。

  

第二章:GUN make介紹

  makemakefile告訴make以何種方式編譯和鏈接程式,當某一文件更新時,make通過比較對應文件的最後修改時間,來決定那些文件需要更新,對需要的文件執行相應命令。

2.1:makefile簡介:

  當使用make工具進行編譯時,工程中一些集中文件在執行make時將會被編譯:

  1、所有源文件中沒有被編譯過,則對各個c源文件進行編譯併進行鏈接,生成最後的可執行程式;

  2、每一個在上次執行make之後修改過的c源代碼文件在本次執行make時將會被重新編譯;

  3、頭文件在上一次執行make之後被修改。則所有包含此頭文件的c源文件在本次執行make時將會被重新編譯。

2.2:makefile規則介紹:

  一個簡單的makefile描述規則組成如下:

  TARGET... : PREREQUITES

      COMMAND

  target:規則的目標,通常是最後需要生成的文件名或者為了實現這個目標而必須的中間過程文件名。可以是目標文件、也可以是最後的可執行程式的文件名。另外目標也可以使一個make執行的動作的名稱,如clean,我們稱這樣的目標是偽目標。

  prerequisites:規則的依賴。生成規則所需要的文件名列表。通常一個文件依賴於一個或者多個文件。

  command:規則的命令行。是規則所要執行的動作(任意的shell命令或者是可在shell下執行的程式)。它限定了make執行這條規則時所需要的動作。

  一個規則可以有多個命令行,每一條命令占一行。註意:每一個命令行必須一[tab]字元開始,[tab]字元告訴make此行是一個命令行。make按照命令完成相應的動作。這也是書寫makefile中容易產生,而且比較隱蔽的錯誤。

  命令就是任意一個目標的依賴文件發生變化後重建目標的動作描述。一個目標可以沒有依賴而只有動作。

  在makefile中的規則就是描述在什麼情況下、如何重建規則的目標文件,通常規則中包括了目標的依賴關係和重建目標的命令。make執行重建目標的命令,來創建或者重建目標。規則包含了文件之間的依賴關係和更新此規則目標所需要的命令。

  make程式根據規則的依賴關係,決定是夠執行規則所定義的命令的過程我們稱之為執行規則。

2.3:簡單的示例

main.c:

#include"hello.h"

int main(){
    print();
    return 0;
}

 

hello.c:

#include"hello.h"

void print(){
    printf("hello world!\n");    
}

hello.h:

#ifndef HELLO_H
#define HELLO_H

#include<stdio.h>
void print();

#endif

 

makefile文件如下:

obj = main.o \
  hello.o main: $(obj) gcc $(obj) -o main main.o: main.c hello.h gcc -c main.c -o main.o hello.o: hello.c hello.h gcc -c hello.c -o hello.o clean: rm -rf *.o main

  

  首先書寫時,可以將一個較長行使用反斜杠分解為多行,使得更容易理解。但是需要註意:反斜杠之後不能有空格。在完成這個makefile以後;需要創建可執行程式main,所要做的就是在包含此makefile的目錄下鍵入命令make。刪除此目錄下的使用make生成的文件,也只需要鍵入命令make clean就可以了。

  命令行必須以tab鍵開始,以和makefile其他行區別。就是說所有的命令行必須以tab字元開始,但並不是所有的以tab字元開始的行都作為命令行來處理。(記住:make程式本身並不關心命令是如何工作的,對目標文件的更新需要你在規則描述中提供正確的命令。make程式所做的就是當目標程式需要更新時執行規則所定義的命令)。

  目標clean不是一個文件,它僅僅代表執行一個動作的標識。正常情況下,不需要執行這個規則所定義的動作,因此目標clean沒有出現在其他任何規則的依賴列表中。因此在執行make時,它所指定的動作不會被執行。除非在執行make時明確地指定它。而且目標clean沒有任何依賴文件,他只有一個目的,就是通過這個目標名來執行它所定義的命令。makefile中把那些沒有任何依賴只有執行動作的目標稱為偽目標。

2.4:make如何工作

  預設情況下,make執行的是makefile中的第一個規則,此規則的第一個目標稱為最終目的或者終極目標。例如上例中的main文件。

  當在shell中鍵入make命令後,make讀取當前目錄下的makefile文件,並將makefile文件中的第一個目標作為其執行的終極目標,開始處理第一個規則。在處理此規則所定義的命令之前,首先處理目標main所有的依賴文件的更新規則。這些目標文件為目標的規則的處理有下列三種情況:

  1、目標文件不存在,使用其描述規則創建它;

  2、目標文件存在,目標文件所以來的.c源文件或者頭文件中的任何一個比目標文件更新。則根據規則重新編譯生成它;

  3、目標文件存在,目標文件比它的任何一個依賴文件更新,什麼也不做。

  在makefile中的一個規則的目標不是終極目標所依賴的,那麼這個規則不會被執行,除非明確指定執行這個規則。

  完成了對目標文件的創建或者更新之後,make程式將處理終極目標main所在的規則,分為以下三種情況:

  1、目標文件不存在,則執行規則以創建目標main;

  2、目標文件main存在,其依賴文件中有一個或者多個文件比它更新,則根據規則重新鏈接生成mian;

  3、目標文件存在。它比它的任何一個依賴文件都新,則什麼都不做。

  總結對一個makefile文件,make首先解析終極目標所在的規則,根據其依賴文件依次尋找創建這些以來文件的規則。首先為第一個依賴文件尋找創建規則,如果第一個依賴文件依賴於其他文件,則同樣為這個依賴文件尋找創建規則,知道為所有依賴文件找到合適的創建規則。之後make從最後一個規則回退開始執行,最終完成終極目標的第一個依賴文件的創建和更新。之後對第一個、第二個、第三個、。。。終極目標的依賴文件執行同樣的過程。最後一步是創建此規則的目標。

  更新終極目標的過程中,如果任何一個規則出現錯誤make就立即報錯並退出。整個過程make只是負責執行規則,而對具體規則所描述的依賴關係的正確性、規則所定義的命令的正確性不做任何判斷。就是說,一個規則的依賴關係是否正確、描述重建目標的規則命令行是夠正確,make不做任何錯誤檢查。因此編寫一個正確的makefile文件愛你就顯得尤為重要。

2.5:制定變數

  上面的例子中的obj就是一個指定變數,下麵每次使用時都可以直接使用;這樣做不但減少書寫的工作量,而且還可以減少修改而產生錯誤的可能。

2.6:自動推導規則

  在使用make編譯.c源文件時,編譯.c源文件時,編譯.c源文件規則的命令可以不用明確給出。這是因為make本身存在一個預設的規則,能夠自動完成對.c文件的編譯並生成對應的目標文件。他執行命令cc -c來編譯.c文件。在makefile中我們只需要給出需要重建的目標文件名,meke會自動為這個目標文件尋找合適的依賴文件,並且使用正確的命令,來重建這個目標文件,對於上面的例子,此預設規則就是使用命令“cc -c main.c -o main.o”來創建文件'main.o'對一個目標文件。此預設規則稱為make的隱含規則。

  在書寫時我們就可以省略掉描述重名的目標文件與依賴文件的規則,只需要給出那些特定的規則描述。因此上面的例子就可以更加簡單的寫成:

obj = main.o hello.o

main: $(obj)
        cc -o main $(obj)
main.o: hello.h
hello.o: hello.h
clean:
        rm -rf *.o main

  

2.7:另類風格的makefile

  我們也可以根據依賴而不是目標對規則進行分組。上例的makefile就可以這樣來實現:

obj = main.o hello.o

main : $(obj)
        cc -o main $(obj)
#(obj) : hello.h
clean:
        rm -rf *.o main

  

  例子中hello.h作為所有.o文件的依賴文件。但這種書寫方式不建議,後期維護會比較麻煩。

  書寫規則建議的方式是:單目標,多依賴。就是說儘量做到一個規則中只存在一個目標文件,可以有多個依賴文件。儘量避免多目標,單依賴的方式。

2.8:清除工作目錄過程文件

  規則除了完成源代碼編譯之外,也可以完成其他任務,例如前面提到的清除編譯過程中產生的臨時文件的規則。

clean:
        rm -rf *.o main

  

  在實際應用時,我們把這個規則寫成如下稍微複雜一些的樣子,以防止始料未及的情況。

.PHONY:clean
clean:
        -rm -rf *.o main

  

  這兩個實現有兩點不同:

  1、通過“.PHONY”特殊目標將clean目標聲明為偽目標。避免當磁碟上存在一個名為clean文件時,目標clean所在規則的命令無法執行。

  2、在命令行之前使用-,意思是忽略命令“rm”的執行錯誤。

  這樣一個目標在makefile中,不能將其作為終極目標。因為我們的初衷並不是當你在命令行上輸入make以後執行刪除動作。而是要創建或者更新程式。


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

-Advertisement-
Play Games
更多相關文章
  • Linux下的大頁分為兩種類型:標準大頁(Huge Pages)和透明大頁(Transparent Huge Pages)。Huge Pages有時候也翻譯成大頁/標準大頁/傳統大頁,它們都是Huge Pages的不同中文翻譯名而已,順帶提一下這個,免得有人被這些名詞給混淆、誤導了。Huge Pag... ...
  • 本來一直想瞭解瀏覽器地址欄中url尾碼名如何去除,今天正好抽空折騰一下。 下麵參考一位博友文章(出處見文章末尾),基於windows平臺(windows7)詳細介紹。 1. URL重寫組件url-rewrite2 微軟官方下載地址:http://www.iis.net/downloads/micro ...
  • 1.1 在yum伺服器上創建yum倉庫命令 1 mkdir -p /application/nginx/html/yum 2 cd /application/nginx/html/yum rz #上傳rpm包到此目錄 rz #上傳rpm包到此目錄 1.2 安裝createrepo軟體 1 yum i ...
  • 軟體環境:vmware10.0破解版 centos版本:6.4 1、啟動vmware,新建虛擬機,選擇自定義安裝 2,出現如下界面,保持預設,點擊下一步 3、這個步驟要特別註意,選擇“稍後安裝”,我們就可以對linux系統自定義 4,選擇2.6的內核 5,為虛擬機起個名字,選擇存放的位置,註意存放的 ...
  • 參考文檔: 本文涉及CMDBuild的安裝配置。 一.環境 1. 操作系統 os:CentOS-7-x86_64-Everything-1511, ip:10.11.4.186 2. 版本 jdk版本(cmdb推薦版本1.8,採用1.8.0_131):http://www.oracle.com/te ...
  • 1.1 快速部署方案 ✔ 問題:當領導給你 100 台已經安裝好系統的伺服器,然後讓優化,讓你提出一個快速部署方案。 解答: 1.tar 打包 先編譯安裝 打包--》分發--》解包(比如 mysql 打包後直接就可以使用 2.SaltStack,puppet,ansible 3.定製 rpm yum ...
  • 1、關掉不需要的外設的時鐘和電源開關; 2、在睡眠前設置IO引腳的狀態,根據硬體電路把IO置高或置低; 3、在低功耗狀態下是否需要內核運行,如果不需要,也要關掉電源或時鐘,如果不能關閉,看能否啟用低頻率的時鐘源; 4、註意RAM區,在低功耗下哪些可以不掉電,哪些會掉電,需要保存的數據可以放在不掉電的 ...
  • NFS通常用於網路中的多台電腦實現共用存儲。 由於測試環境沒有購買阿裡雲的NFS,所以自己搭建一個NFS文件系統,實現一些比如上傳圖片,靜態資源等同享功能。 下麵的測試是在CentOS release 6.8 (Final)中進行的。其他的系統略有不同。 網路環境 :nfs伺服器IP: 192.1 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...