【編譯、鏈接與構建詳解】Makefile 與 CMakeLists 的作用

【編譯、鏈接與構建詳解】Makefile 與 CMakeLists 的作用

  • 前言
  • 源代碼(.c、.cpp)
  • 編譯
    • 編譯的本質
    • 編輯的結果
    • 編譯器(GCC、G++、NVCC 等)
  • 目標文件(`.o`)
    • 什么是 `.o` 目標文件
    • 為什么單個 `.o` 目標文件不能直接執行?
  • 鏈接
    • 鏈接的本質
    • 如果需要鏈接的 `.o` 文件很多且雜亂怎么辦?
  • 庫文件(.a、.so)
    • 靜態庫(`.a`)
    • 動態庫(`.so`)
  • 構建
    • 構建的步驟
    • 自動化構建
  • 構建工具與構建規則(Make、Makefile)
  • 構建配置工具與構建配置文件(CMake、CMakeLists)

前言

在大型項目中,通常會使用 C 或 C++ 語言進行開發,而編譯、鏈接、構建等概念,以及相關工具如 GCC、G++、NVCC、CMake、Make、Makefile 等,是每個開發者都無法繞過的重要內容。這些概念雖然至關重要,但往往容易混淆。因此,本文將簡明扼要地介紹這些概念,幫助讀者更深入地理解編譯、鏈接與構建過程。

源代碼(.c、.cpp)

我們編寫的代碼通常以 .c.cpp 文件的形式存在,這些源代碼文件是人類可讀的,但計算機無法直接理解和執行。
計算機只能理解二進制的機器語言,因此,需要通過編譯將源代碼轉換為機器可以識別的格式,這就涉及到編譯的相關知識。

編譯

編譯的本質

程序員編寫的 .c.cpp 源代碼是人類可讀的,但計算機無法直接理解。為了讓計算機執行這些代碼,需要將其轉換為計算機能夠識別的二進制語言,這個過程就是編譯的本質。

編輯的結果

編譯的結果是目標文件.o 文件),它包含了經過翻譯但尚未完整鏈接的二進制代碼(機器可以理解的語言)。理解目標文件的作用,有助于更深入地掌握編譯過程。

編譯器(GCC、G++、NVCC 等)

編譯器是將源代碼翻譯為計算機能夠理解的目標文件的“翻譯官”。它負責將人類編寫的 .c.cpp.cu 等源代碼轉化為機器可執行的二進制代碼。常見的編譯器包括:

  • GCC(GNU Compiler Collection):主要用于編譯 C 語言的源代碼(.c 文件)。
  • G++:是 GCC 的 C++ 編譯器,用于編譯 C++ 語言的源代碼(.cpp 文件)。
  • NVCC:NVIDIA CUDA 編譯器,用于編譯并行計算的 CUDA 程序(.cu 文件)。

這些編譯器各自對應不同類型的源代碼文件,執行代碼翻譯的任務。

目標文件(.o

什么是 .o 目標文件

.c.cpp 源代碼經過編譯后,會生成 .o 目標文件。目標文件是計算機可以理解的二進制代碼,意味著源代碼已經被翻譯成機器語言,程序的執行又向前邁進了一步。

為什么單個 .o 目標文件不能直接執行?

目標文件(.o)本身并不能直接運行,因為它只是編譯后的中間產物,尚未構成完整的可執行程序。通常,一個程序由多個 .c.cpp 文件組成,而 main 函數往往位于其中的一個文件中,負責調用其他模塊的函數。

可以將程序比作一輛汽車:main 函數相當于車架,而各個 .o 文件代表輪子、方向盤、控制臺等組件。單獨的 .o 文件只是一個零件,只有經過鏈接,將所有模塊正確拼接在一起,才能形成最終可運行的程序。

要將這些獨立的目標文件整合成一個可執行程序,就涉及到鏈接的過程。

鏈接

鏈接的本質

當所有 .c.cpp 代碼經過編譯后,都會生成 .o 目標文件。這些 .o 文件雖然已經被翻譯成機器可以識別的語言,但它們彼此獨立,尚無法直接運行。

鏈接就是組裝:
可以將 .o 文件比作汽車的零部件:單獨的目標文件就像輪子、方向盤、發動機等組件,只有經過鏈接,將這些部件正確組裝起來,才能形成一個完整的可執行程序(拼成一個可以跑的汽車)。鏈接的本質,就是將多個 .o 目標文件整合在一起,最終拼接成可以運行的可執行文件。

通常,在所有被鏈接的 .o 目標文件中,只有一個包含 main 主函數,它相當于汽車的車架,而其他 .o 文件則封裝了各種功能模塊(如發動機、剎車系統、座椅等)。鏈接的過程,就是將這個帶有 main 入口的*“車架”與其他“零部件”*拼接在一起,使其成為一個完整可運行的程序。

如果需要鏈接的 .o 文件很多且雜亂怎么辦?

在大型項目中,編譯過程中會生成大量 .o 目標文件。如果直接鏈接所有 .o 文件,不僅會導致項目結構混亂,還會增加管理和分發的難度。

為了解決這個問題,通常會將多個 .o 文件打包成庫文件,即 .so(動態/共享庫).a(靜態庫)。這些庫文件可以幫助我們更高效地組織、管理和復用代碼,使項目結構更加清晰,鏈接過程也更加簡潔。

庫文件(.a、.so)

為了更方便地管理大量的 .o 目標文件,引入了庫文件的概念。庫文件可以看作是多個 .o 文件的集合,用于提高代碼的組織性和復用性。然而,庫文件分為兩種類型:

  • .a(靜態庫)
  • .so(動態庫/共享庫)

二者雖然都是 .o 文件的集合,但在使用方式上存在明顯區別。

靜態庫(.a

靜態庫(.a)本質上是多個 .o 目標文件的打包集合,在編譯時會被直接鏈接到可執行文件中。這種方式可以提高代碼復用性,并減少每次編譯時重復編寫相同代碼的工作量。

然而,靜態庫是固定的,如果庫中的 .o 文件對應的源代碼發生修改,就需要重新編譯修改的部分并更新靜態庫文件,然后再重新鏈接生成新的可執行文件。這意味著每次庫文件更新后,所有依賴該庫的程序都必須重新編譯和鏈接。

動態庫(.so

動態庫(.so,共享庫)與靜態庫類似,也是多個 .o 目標文件的集合,但它不會在編譯時直接嵌入可執行文件,而是在程序運行時被加載。這種方式減少了可執行文件的體積,并允許多個程序共享同一個庫,從而提高資源利用率。

此外,動態庫是靈活的,如果庫中的 .o 文件對應的源代碼發生修改,只需重新編譯動態庫文件,無需重新編譯和鏈接所有依賴它的程序。程序在運行時會自動加載最新版本的動態庫,因此更新更加便捷。

構建

構建是將源代碼轉化為可執行文件的完整過程,通常包括以下幾個主要步驟:

構建的步驟

  1. 清理
    在進行新一輪構建之前,需要先清理掉之前構建的產物,比如刪除舊的目標文件 .o、可執行文件和庫文件等。這一步確保構建環境干凈,避免舊文件影響新一輪構建。

  2. 管理依賴
    項目可能依賴外部庫或資源,這時候需要下載、安裝并管理這些依賴,確保它們的版本正確且可用。

  3. 編譯
    這一階段將源代碼文件(.c.cpp)編譯成目標文件(.o)。編譯過程將人類可讀的代碼轉化為機器可以理解的中間產物。

  4. 鏈接
    鏈接過程將多個目標文件(.o 文件)和庫文件(.a.so 文件)整合、拼接成一個完整的可執行文件,最終生成可以運行的程序。

  5. 其他
    在某些構建過程中,還可能涉及其他步驟,如單元測試、部署、打包等,這些步驟根據項目需求可能會有所不同。

自動化構建

如上所述,構建過程包含多個環節,涉及到源代碼的編譯、目標文件的生成、依賴的管理等操作。為了實現高效且自動化的構建,通常會使用構建工具來控制這一過程。

最常見的構建工具是 Make,它通過 Makefile 文件定義的構建規則和依賴關系,從而自動化管理和執行構建步驟。接下來,我們將介紹 Make 工具及其 Makefile 構建規則的相關內容。

構建工具與構建規則(Make、Makefile)

Make 是一種常用的構建工具,它根據 Makefile 中定義的 構建規則 來自動化構建過程。Makefile 中指定了構建目標、依賴關系、編譯器選項、可執行文件名等具體的構建命令。
然而,Make 的一些局限性也較為明顯:它的語法較為底層,可讀性較差,并且對多平臺兼容性較弱(例如,它通常只適用于 UNIX 系統,而在其他平臺的構建可能會遇到困難)。

為了克服這些問題,CMake 應運而生。CMake 是一個更高級的構建配置工具,它通過平臺無關的配置文件生成適用于不同平臺的構建文件(例如 Makefile 或 Visual Studio 工程文件),從而解決了多平臺兼容性和可讀性差的問題。

構建配置工具與構建配置文件(CMake、CMakeLists)

正如前文所述,CMake 是一個高級的構建配置工具,它通過讀取 CMakeLists.txt 文件中定義的構建配置來生成適應不同平臺的構建規則。CMake 會根據 CMakeLists.txt 中的內容,自動生成對應的構建文件(例如 Makefile 或 Visual Studio 工程文件),然后調用相應的構建工具(如 make)來執行構建過程。

相較于 Make,CMake 提供了更高層次的抽象,具有更強的實用性和更好的跨平臺兼容性。因此,CMake 在大型項目中得到了更廣泛的應用,尤其是在需要支持多平臺構建時,CMake 和 CMakeLists.txt 文件成為了主流的選擇。

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

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

相關文章

Ubuntu / Debian 創建快捷方式啟動提權

簡述 在 Linux 系統中,.desktop 文件是 桌面入口文件,用于在桌面環境(如 GNOME、KDE)中定義應用程序的啟動方式、圖標、名稱等信息。當你執行 touch idea.desktop 時,實際上創建了一個空的 .desktop 文件(…

ISIS報文

IS-IS 報文 目錄 IS-IS 報文 一、報文類型與功能 二、報文結構解析 三、核心功能特性 四、典型應用場景 五、抓包數據分析 六、總結 IS-IS(中間系統到中間系統)協議報文是用于鏈路狀態路由協議中網絡設備間交換路由信息的關鍵載體,其設…

beikeshop多商戶跨境電商獨立站最新版v1.6.0版本源碼

一.介紹 beikeshop跨境電商獨立站最新版V1.6.0源碼 多商戶 多商家 多語言 多幣結算 本博主親測搭建代碼全開源質量相對來說很穩定的 二.服務器環境 系統:CentOS、 環境:PHP7.4 Nginx 1.21 MySQL 5.6 常見插件:fileinfo ; re…

Redis批量操作詳解

一、原生批量命令(MSET) 適用場景:所有鍵的過期時間相同或無過期設置,且無需條件判斷。 方法: 將多個SET命令合并為MSET命令,但需要注意MSET的局限性(無法設置過期時間,且所有鍵值對…

Spring Boot 集成實戰:AI 工具如何自動生成完整微服務模塊

在數字化轉型的浪潮中,開發效率和質量是企業競爭力的關鍵要素。飛算 JavaAI 作為一款創新的 AI 工具,能在 Spring Boot 開發中,自動生成完整微服務模塊,極大提升開發效率。下面,我們就詳細介紹如何借助飛算 JavaAI&…

算法 | 2024最新算法:斑翠鳥優化算法原理,公式,應用,算法改進研究綜述,matlab代碼

基于斑翠鳥優化算法的原理、應用及改進研究綜述 一、算法原理 斑翠鳥優化算法(Pied Kingfisher Optimizer, PKO)是2024年由Bouaouda等人提出的一種新型仿生智能優化算法,其靈感來源于斑翠鳥的捕食行為與共生關系。算法通過模擬斑翠鳥的棲息懸停、潛水捕魚及與其他生物的共生…

RabbitMQ高級特性--重試特性

目錄 1.重試配置 2.配置交換機&隊列 3.發送消息 4.消費消息 5. 運行程序觀察結果 6. 手動確認 注意: 在消息傳遞過程中, 可能會遇到各種問題, 如網絡故障, 服務不可用, 資源不足等, 這些問題可能導致消息處理失敗. 為了解決這些問題, RabbitMQ 提供了重試機制, …

Vue 組件通信 - 中央事件總線

Vue 漸進式JavaScript 框架 基于Vue2的學習筆記 - Vue組件通信 - 中央事件總線 目錄 中央事件總線 圖示 準備工作 設置頁面元素 創建組件 總結 中央事件總線 使用vue的監聽和觸發來實現中央事件總線方式。 on監聽 emit觸發,組件按鈕綁定點擊事件&#xff0c…

5.0 WPF的基礎介紹1-Grid,Stack,button

WPF: Window Presentation Foundation. WPF與WinForms的對比如下: 特性WinFormsWPF技術基礎基于傳統的GDI(圖形設備接口)基于DirectX,支持硬件加速的矢量渲染UI設計方式拖拽控件事件驅動代碼(簡單但局限)…

QT軟件設計可考慮回答

在Qt應用中是否引入抽象類需要根據具體場景權衡&#xff0c;以下是分層建議&#xff1a; 建議采用抽象類的3個典型場景&#xff1a; 傳感器系統抽象&#xff08;強推薦&#xff09; class AbstractSensor { public:virtual ~AbstractSensor() default;virtual QVector<L…

pytorch學習(b站小土堆學習)

1 環境配置 參考鏈接 2. dir 和 help函數 dir()&#xff1a;用于查看某一模塊函數的方法 help()&#xff1a; 用于查看某方法的使用方法 3. dataset類實戰 利用Image對象打開圖片&#xff0c;利用os模塊的地址拼接組成圖片路徑 當我們用方括號訪問元素對象時&#xff0c;…

Unity TextMeshPro 實現文本逐字淡出效果

Unity TextMeshPro 實現文本逐字淡出效果 前言項目思路場景布置代碼編寫 前言 在處理角色對話時經常會用到一些文本動畫&#xff0c;正好記錄一下。使用 TextMeshPro&#xff0c;我們可以直接操作文本的頂點數據&#xff0c;實現諸如漸變、動畫等效果&#xff0c;為游戲界面和…

Mathtype無法插入到Word中

在word工具欄上有沒有出現Mtahtype&#xff0c;會出現以下兩種情況&#xff1a; 1. 沒有出現Mtahtype 2. 出現Mtahtype&#xff0c;但是點擊會出現彈窗 “ Couldnt find the MathPage.wll ” 解決方案 首先查看word版本是32位還是64位&#xff0c;這個位數是office安裝位數…

責任鏈模式_行為型_GOF23

責任鏈模式 責任鏈模式&#xff08;Chain of Responsibility Pattern&#xff09;是一種行為型設計模式&#xff0c;核心思想是將多個處理請求的對象連成一條鏈&#xff0c;請求沿鏈傳遞直到被處理。它像現實中的“多級審批流程”——請假或報銷時&#xff0c;申請會逐級提交給…

Qt圖形化界面為何總被“冷落“?

在Qt開發者的IDE中&#xff0c;Qt Designer總像一個被遺忘的角落——即便它有著直觀的拖拽式界面設計功能。通過分析GitHub上超過5000個Qt項目發現&#xff0c;僅有17%的項目使用.ui文件構建界面。這個數據背后&#xff0c;隱藏著開發者群體對GUI構建方式的集體選擇。我們不禁要…

SQL Server從安裝到入門一文掌握應用能力。

本篇文章主要講解,SQL Server的安裝教程及入門使用的基礎知識,通過本篇文章你可以快速掌握SQL Server的建庫、建表、增加、查詢、刪除、修改等基本數據庫操作能力。 作者:任聰聰 日期:2025年3月31日 一、SQL Server 介紹: SQL Server 是微軟旗下的一款主流且優質的數據庫…

簡單視圖函數

視圖函數 文章目錄 視圖函數[toc]一、什么是視圖函數二、簡單視圖函數三、返回錯誤視圖 一、什么是視圖函數 所謂視圖函數&#xff08;簡稱視圖&#xff09;&#xff0c;本質上就是一個Python函數&#xff0c;用于接收Web請求并且返回Web響應。Web響應可以包含很多類型&#x…

QT文件操作(QT實操學習3)

1.項目架構 1.UI界面 1.新建文本文檔 2.打開文件 3.另存為文件 2.mainwindow.h? #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QFileDialog> #include <QMessageBox> #include <QDebug> QT_BEGIN_NAMESPACE namespa…

HX324雙運算放大器:賦能萬物互聯時代的信號處理基石

一、運算放大器行業的技術演進與市場需求 在全球半導體市場規模突破6000億美元的背景下&#xff0c;模擬芯片作為電子系統的"感官神經"&#xff0c;正迎來智能化升級浪潮。據IC Insights數據顯示&#xff0c;2023年全球運算放大器市場規模達32.7億美元&#xff0c;其…

C++ 結構體與函數

一.結構體 1.概念&#xff1a; 結構體&#xff08;struct&#xff09;是一種用戶自定義復合數據類型&#xff0c;其中可以包含不同類型的不同成員 2.結構體的應用場景&#xff1a; 我們在使用多個變量描述一個對象時&#xff0c;雖然也可以做到&#xff0c;但是難免顯得雜亂…