#C++# C++編譯相關說明
共 7243字,需瀏覽 15分鐘
·
2024-12-01 23:26
“ 文章所涉及內容更多來自網(wǎng)絡,在此聲明,并感謝知識的貢獻者!”
C++ 編譯過程
—
C++的編譯過程
編寫完成一個C/C++程序后,想要運行起來,必須要經過四個步驟:預處理、編譯、匯編和鏈接。每個步驟都會生成對應的文件,如下圖所示(注意后綴名):
預處理(Preprocess)
預編譯把一些#define的宏定義完成文本替換,然后將#include的文件里的內容復制到.cpp文件里,如果.h文件里還有.h文件,就遞歸展開。在預處理這一步,代碼注釋直接被忽略,不會進入到后續(xù)的處理中,所以注釋在程序中不會執(zhí)行。
編譯(Compile)
編譯只是把我們寫的代碼轉為匯編代碼,它的工作是檢查詞法和語法規(guī)則,所以,如果程序沒有詞法或則語法錯誤,那么不管邏輯是怎樣錯誤的,都不會報錯。
編譯不是指程序從源文件到二進制程序的全部過程,而是指將經過預處理之后的程序轉換成特定匯編代碼(assembly code)的過程。
匯編(Assemble)
匯編過程將上一步的匯編代碼(main.s)轉換成機器碼(machine code),這一步產生的文件叫做目標文件(main.o),是二進制格式。
匯編這一步需要為每一個源文件(本文示例代碼中為main.cpp、func.cpp)產生一個目標文件。因此func.cpp也需要執(zhí)行一次這個匯編過程產生一個func.o文件
鏈接(Link)
C/C++代碼經過匯編之后生成的目標文件(*.o)并不是最終的可執(zhí)行二進制文件,而仍是一種中間文件(或稱臨時文件),目標文件仍然需要經過鏈接(Link)才能變成可執(zhí)行文件。
既然目標文件和可執(zhí)行文件的格式是一樣的(都是二進制格式),為什么還要再鏈接一次呢?
因為編譯只是將我們自己寫的代碼變成了二進制形式,它還需要和系統(tǒng)組件(比如標準庫、動態(tài)鏈接庫等)結合起來,這些組件都是程序運行所必須的。
鏈接(Link)其實就是一個“打包”的過程,它將所有二進制形式的目標文件(.o)和系統(tǒng)組件組合成一個可執(zhí)行文件。完成鏈接的過程也需要一個特殊的軟件,叫做鏈接器(Linker)。
此外需要注意的是:C++程序編譯的時候其實只識別.cpp文件,每個cpp文件都會分別編譯一次,生成一個.o文件。這個時候,鏈接器除了將目標文件和系統(tǒng)組件組合起來,還需要將編譯器生成的多個.o或者.obj文件組合起來,生成最終的可執(zhí)行文件(Executable file)。
以本文中的代碼為例,將func.o和main.o鏈接成可執(zhí)行文件main.out
參考資料
詳解C/C++代碼的預處理、編譯、匯編、鏈接全過程 - 知乎 (zhihu.com)
https://zhuanlan.zhihu.com/p/618037867
C++ 編譯器類型
—
C++ 編譯器類型
GNU的gcc/g++、
LLVM的clang/clang++、
Windows的Mingw/MSVC、
CMake,make的升級版
Microsoft Visual C++ (MSVC)
MSVC 是 Microsoft 提供的 C++ 編譯器,用于 Windows 平臺。它是 Visual Studio 集成開發(fā)環(huán)境(IDE)的一部分,支持多種 C++ 標準,包括最新的 C++17 和 C++20 標準。
MinGW
即 Minimalist GNU For Windows。它是一些頭文件和端口庫的集合,該集合允許人們在沒有第三方動態(tài)鏈接庫的情況下使用 GCC(GNU Compiler C)產生 Windows32 程序。實際上 MinGW 并不是一個 C/C++ 編譯器,而是一套 GNU 工具集合。除開 GCC (GNU 編譯器集合) 以外,MinGW 還包含有一些其他的 GNU 程序開發(fā)工具 (比如 gawk bison 等等)。
Cygwin
是全面模擬了Linux的接口,提供給運行在它上面的的程序使用,并提供了大量現(xiàn)成的軟件,更像是一個平臺。
相對的 MingW 也有一個叫 MSys(Minimal SYStem)的子項目,主要是提供了一個模擬 Linux 的 Shell 和一些基本的 Linux 工具。因為編譯一個大型程序,光靠一個 GCC 是不夠的,還需要有 Autoconf 等工具來配置項目,所以一般在 Windows 下編譯 ffmpeg 等 Linux 下的大型項目都是通過Msys 來完成的,當然 Msys 只是一個輔助環(huán)境,根本的工作還是 MingW 來做的。
GNU
GNU操作系統(tǒng)是一種由自由軟件構成的類 Unix 操作系統(tǒng),該系統(tǒng)基于 Linux 內核,目標在于建立一個完全相容于UNIX的自由軟件環(huán)境。
gcc是GCC中的GNU C Compiler(C 編譯器)
g++是GCC中的GNU C++ Compiler(C++編譯器)
Makefile
一個工程中的源文件不計其數(shù),其按類型、功能、模塊分別放在若干個目錄中,makefile定義了一系列的規(guī)則來指定哪些文件需要先編譯,哪些文件需要后編譯,哪些文件需要重新編譯,甚至于進行更復雜的功能操作,因為 makefile就像一個Shell腳本一樣,也可以執(zhí)行操作系統(tǒng)的命令。
make是一個命令工具,它解釋Makefile 中的指令。在Makefile文件中描述了整個工程所有文件的編譯順序、編譯規(guī)則。Makefile 有自己的書寫格式、關鍵字、函數(shù)。像C 語言有自己的格式、關鍵字和函數(shù)一樣。而且在Makefile 中可以使用系統(tǒng)shell所提供的任何命令來完成想要的工作。Makefile在絕大多數(shù)的IDE 開發(fā)環(huán)境中都在使用,譬如 Visual C++的 nmake、linux 下的 GNU make、Qt 的 qmake 等等。
CMake
不同的IDE所集成的make工具所遵循的規(guī)范和標準都不同,也就導致其語法、格式不同,也就不能很好的跨平臺編譯,會使得工作繁瑣。那么cmake為了解決這個問題而誕生了,其允許開發(fā)者指定整個工程的編譯流程,在根據(jù)編譯平臺,生成本地化的Makefile和工程文件,最后用戶只需make編譯即可。簡而言之,可以把cmake看成一款自動生成 Makefile 的工具,所以編譯流程就變成了:cmake—>make–>用戶代碼–>可執(zhí)行文件
LLVM
(Low Level Virtual Machine)是一個編譯器基礎設施項目,它提供了一個編譯器的前端和后端之間的“中間表示”(Intermediate Representation,IR),使得編譯器可以更容易地進行優(yōu)化和跨平臺操作。Clang和Clang++是LLVM項目中的C、C++、Objective-C和Objective-C++編程語言的編譯器前端
Intel C++ Compiler (ICC)
Intel 提供的 C++ 編譯器,主要針對 Intel 架構的處理器進行優(yōu)化。它支持多種 C++ 標準,并提供了針對 Intel 架構的特定優(yōu)化。
Xcode Clang
對于 macOS 開發(fā)者來說,Xcode 是官方的 IDE,它內置了 Clang 編譯器,用于編譯 C++ 代碼。Xcode 提供了豐富的開發(fā)工具和界面,方便 macOS 應用的開發(fā)。
Clang-CL
Clang-CL 是 Clang 的一個變種,專門用于在 Windows 平臺上進行編譯,兼容 Microsoft Visual C++。
g++ 與 clang++對比
g++ 與 clang++安裝
a. 安裝較新版本的 GCC:
您可以通過使用 SCL (Software Collections) 來安裝較新版本的 GCC,這將允許您在不影響系統(tǒng)的情況下安裝并使用較新的 GCC。
sudo yum install centos-release-scl -y
sudo yum install devtoolset-10-gcc-c++ -y
激活 devtoolset-10 環(huán)境以使用新的 GCC 版本:
scl enable devtoolset-10 bash
b. 安裝 Clang:
您也可以選擇安裝 Clang 編譯器,它對 C++20 提供了良好的支持。
sudo yum install llvm-toolset-7 -y
激活 llvm-toolset-7 環(huán)境以使用 Clang:
scl enable llvm-toolset-7 bash
驗證安裝:
確保您已經成功安裝了新版本的編譯器。您可以通過以下命令來驗證:
g++ --version
或者
clang++ --version
g++ 與 clang++優(yōu)缺點
--g++(GCC)優(yōu)點:
成熟穩(wěn)定:GCC 是一個歷史悠久的編譯器,已經經過長時間的發(fā)展和測試,因此非常穩(wěn)定。
廣泛支持:GCC 在許多平臺上都有良好的支持,包括各種 UNIX/Linux 發(fā)行版以及其他操作系統(tǒng)。
標準符合:GCC 對 C++ 標準的支持通常很好,并且在新標準發(fā)布后會迅速更新以支持新功能。
錯誤消息:一些開發(fā)人員認為 GCC 的錯誤消息更易于理解和調試。
社區(qū)活躍:GCC 有一個龐大的社區(qū)和開發(fā)團隊,因此可以在廣泛的環(huán)境中找到支持和資源。
g++ 缺點:
編譯速度:相對而言,GCC 編譯速度可能會比 Clang 慢一些,尤其是在大型項目中。
模板錯誤消息:有時 GCC 對模板錯誤的報告不夠清晰,可能需要更多的工作來調試。
--clang++(Clang)優(yōu)點:
速度:Clang 以其快速的編譯速度而聞名,特別是對于大型項目來說,它通常比 GCC 編譯速度更快。
清晰的錯誤消息:Clang 提供了非常清晰和易于理解的錯誤消息和警告,有助于更輕松地調試代碼。
模塊化設計:Clang 的設計更加模塊化,這使得它更容易與其他工具集成,并且更容易為特定任務創(chuàng)建自定義編譯器。
靜態(tài)分析工具:Clang 自帶了一套強大的靜態(tài)代碼分析工具,可以幫助您發(fā)現(xiàn)潛在的問題和改進代碼質量。
clang++ 缺點:
標準支持:盡管 Clang 的標準支持逐漸改善,但在某些情況下可能會落后于 GCC,尤其是在新標準發(fā)布后不久的時候。
非 GNU 工具鏈兼容性:某些 GNU 工具鏈特性可能不被 Clang 完全支持,這可能導致在一些項目中的不兼容問題。
g++ 與 clang++
示范代碼:
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::cout << "Numbers:";
for (int num : numbers) {
std::cout << " " << num;
}
std::cout << std::endl;
return 0;
}
使用 GCC 10 編譯
g++ -std=c++20 -o main main.cpp
使用 Clang 7 編譯
clang++ -std=c++2a -o main main.cpp
使用 GCC 10 編譯時添加優(yōu)化選項, 使用優(yōu)化選項來提高生成的可執(zhí)行文件的性能
g++ -std=c++20 -O3 -o main main.cpp
使用 Clang 7 編譯時添加優(yōu)化選項
clang++ -std=c++2a -O3 -o main main.cpp
編譯器的優(yōu)化級別
-O0:
含義:無優(yōu)化。
描述:編譯器不執(zhí)行任何優(yōu)化,生成的代碼與源代碼相對應,用于調試目的。
-O1:
含義:基本優(yōu)化。
描述:編譯器執(zhí)行一些基本的優(yōu)化,如刪除未使用的函數(shù)、變量和內聯(lián)簡單函數(shù)等。
-O2:
含義:常規(guī)優(yōu)化。
描述:除了 -O1 中的優(yōu)化之外,編譯器還執(zhí)行更多的優(yōu)化,如函數(shù)內聯(lián)、循環(huán)展開等。這是默認的優(yōu)化級別。
-O3:
含義:更高級別的優(yōu)化。
描述:除了 -O2 中的優(yōu)化之外,編譯器還執(zhí)行更多的優(yōu)化,如函數(shù)內聯(lián)的限制更松、更激進的循環(huán)優(yōu)化等。這可能會增加編譯時間,并且生成的代碼可能會更大。
-Os:
含義:優(yōu)化代碼大小。
描述:該選項主要優(yōu)化生成的目標代碼的大小,通常會犧牲一些性能來減小可執(zhí)行文件的大小。
-Ofast:
含義:快速優(yōu)化。
描述:這是一個特殊的優(yōu)化級別,它試圖盡可能快地生成代碼,通常會關閉一些嚴格的符合標準的優(yōu)化,如 IEEE 浮點數(shù)語義等。這可能會導致生成的代碼在某些情況下不符合標準,并且可能會導致一些未定義行為。
C++ Linux 編譯方法
—
Linux C++ 編譯的常用方法:
Linux CMake 編譯C++
【Linux】CMake編譯C/C++工程文件_cmake 編譯 c-CSDN博客
https://blog.csdn.net/Cxj__/article/details/125996702
Visual studio Linux C++ WSL2
Visual Studio 2022 引入了用于 Linux C++ 開發(fā)的本機 WSL2 工具集,可以構建和調試 Linux C++ 代碼,并提供了非常好的 Linux 文件系統(tǒng)性能、GUI 支持和完整的系統(tǒng)調用兼容性。
使用 Visual Studio 2022 開發(fā) Linux C++ 應用程序的過程詳解_C 語言_腳本之家 (jb51.net)
https://www.jb51.net/article/230687.htm
怎么使用Visual Studio 2022開發(fā)Linux、C++應用程序 - 開發(fā)技術 - 億速云 (yisu.com)
https://www.yisu.com/zixun/620515.html
Visual studio Linux C++ 遠程連接到Linux服務器
VS(官方)跨平臺開發(fā)遠程調試教程(遠程開發(fā))_vs遠程開發(fā)-CSDN博客
https://dontla.blog.csdn.net/article/details/122833229
Visual studio 2019 安裝 詳細圖文教程_vs2019安裝教程-CSDN博客
https://blog.csdn.net/m0_56051805/article/details/125650044
Visual Studio CMake在遠程Linux服務器編譯C++
Linux環(huán)境配置
https://www.jianshu.com/p/99c631a069b9
在 Visual Studio 中配置 Linux CMake 項目 | Microsoft Learn
https://learn.microsoft.com/zh-cn/cpp/linux/cmake-linux-configure?view=msvc-170
VS遠程調試(Visual Studio)遠程連接到linux cmake(跨平臺開發(fā))(適用于VS2019,且遠程目標平臺cmake版本大于等于3.8)_cmake 大于3.8-CSDN博客
https://blog.csdn.net/Dontla/article/details/122632139
修改遠程生成根目錄
Visual Studio連接Linux服務器編譯CMake項目,生成在Linux上運行的程序_vs運行在linux-CSDN博客
https://blog.csdn.net/weixin_44131612/article/details/129295558
其他資料:
visual studio 2019
Downloads & Keys - Visual Studio Subscriptions
https://my.visualstudio.com/Downloads?q=visual%20studio%202019&wt.mc_id=o~msft~vscom~older-downloads
參考資料
—
參考資料
執(zhí)行腳本時,Cmake報錯 “Unix Makefiles“_cmake error: cmake was unable to find a build prog-CSDN博客
https://blog.csdn.net/qq_42181775/article/details/131534688
詳解三大編譯器:gcc、llvm 和 clang - 知乎 (zhihu.com)
https://zhuanlan.zhihu.com/p/357803433
gcc,clang,msvc等編譯器有什么區(qū)別?- 知乎 (zhihu.com)
https://www.zhihu.com/question/445921363
MinGW到底是個什么ghost_mingw這是啥-CSDN博客
https://blog.csdn.net/lee_ham/article/details/81778581
有沒有大佬給我講解一下MSVC、MINGW,gcc、g++,qmake、cmake的聯(lián)系和區(qū)別是什么?- 知乎 (zhihu.com)https://www.zhihu.com/question/33356025
