引言
假如想在 Windows 下進行 C++ 的開發,可以直接使用 Visual Studio 和相應的 C++ 插件來實現,但編譯和構建過程是不可見的。爲了更徹底地瞭解 C++ 工程的編譯和構建,可以藉助另外兩個工具在 Windows 環境下實現。
MinGW
是 Windows 系統下的一個編譯環境,包含了 C++ 代碼編譯所需的三方庫、頭文件等,用於完成 C++ 源碼的編譯和鏈接。
-
安裝:
在官網下載安裝包:mingw-get-setup.exe ,雙擊開始安裝,然後在 MinGW Installation Manager 中選擇需要安裝的工具庫。
Basic Setup
中的庫都是比較常用的,例如編譯代碼使用的g++
工具,這些最好都選中並安裝。 -
配置:
將安裝目錄的 bin 目錄配置到系統環境變量中的 Path 中,啓動 cmd 命令行,輸入一下指令驗證上面選擇的庫是否安裝成功,例如 g++ 庫:
E:\C++\projects>g++ --version g++ (MinGW.org GCC-6.3.0-1) 6.3.0 Copyright (C) 2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
輸出上述內容則表示庫安裝成功。
-
測試編譯:
隨便編寫一個 C++ 代碼文件,然後使用 g++ 來編譯生成可執行文件:
#include <iostream> using namespace std; int main() { cout << "Hello, World!"; return 0; }
先編譯但不鏈接,然後鏈接生成可執行文件:
$ g++ -c helloworld.cpp $ g++ helloworld.o -o helloworld.exe
假如使用
-c
標識,則是編譯但不鏈接,會生成對應的.o
文件,不設置標識,則會直接生成最終的.exe
可執行文件。 -
靜態關聯:
上述編譯生成的可執行文件,雙擊打開都會提示
"無法啓動此程序,因爲計算機中丟失 libgcc_s_dw2-1.dll。..."
這樣的錯誤(假如是在命令行中執行文件則不會報錯,但會命令行窗口會一閃而過,看不到輸出的結果)。這是因爲 gcc 編譯器 編譯時默認使用的不是靜態關聯的方式,運行時找不到對應的庫導致報錯。解決方案:可以直接將缺失的 dll 庫手動複製到可執行文件目錄下,當然這不是根治的方法,其實只要在鏈接時帶上標識
-static-libgcc
來指定靜態關聯即可解決此問題:$ g++ helloworld.o -o helloworld.exe -static-libgcc
後面使用 CMake 來構建的話,可以在 CMakeList.txt 配置編譯參數。
MinGW-w64
上面安裝的 MinGW 只能編譯生成 32 位的可執行程序,而 MinGW-w64
可以編譯生成 64 位或 32 位的可執行程序。安裝步驟如下:
-
安裝:
可以從 mingw-w64 官網 下載最新的安裝包,也可以直接從 SourceForge 中去下載 mingw-w64-install.exe
下載完成後,直接雙擊安裝包進行安裝,除了修改一下安裝目錄,其餘設置都是用默認設置接口。
這裏直接下載安裝程序進行安裝的話,在安裝過程需需要去服務器下載資源,似乎速度很慢,所以最後我改成直接從 這裏 下載離線的完整壓縮包:
根據自己的需求選擇,此包爲:64 位系統,且使用效率較好較新的 seh 異常處理模型(至於 win32 和 posix 的區別暫時還沒搞懂)
-
配置:
通上面的 MinGW 一樣,只需將安裝目錄下的 bin 目錄配置到系統 Path 中即可。查詢配置結果:
$ gcc --version gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0 Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
在執行 gcc 命令時,加上
-m32
生成 32 位可執行程序,加上-m64
生成 64 位可執行程序
CMake
一個跨平臺的自動構建系統,使用一個 CMakeLists.txt 文件來描述構建過程(等同於 Linux 系統下編譯構建 C/C++ 時使用的 Makefile 的作用),通常在編譯一個多文件的工程時使用這樣的工具。
-
安裝:
直接下載官方 cmake-3.13.0-rc3-win64-x64.zip 包,解壓即可,無需安裝。
-
配置:
參考 MinGW 的配置方式,將解壓後目錄中的 bin 目錄配置到系統 的 Path 參數中,通過命令行驗證是否配置成功:
E:\C++\projects>cmake --version cmake version 3.13.0-rc3 CMake suite maintained and supported by Kitware (kitware.com/cmake).
如上標識配置生效。
-
測試:
在測試目錄下創建一個
CMakeLists.txt
文件:cmake_minimum_required (VERSION 3.0) # cmake 最低版本 project (helloworld) # 工程名稱 add_executable(helloworld helloworld.cpp) # 源文件 if(WIN32) # 靜態關聯配置 set(CMAKE_CXX_FLAGS "-static-libgcc") endif(WIN32)
打開 cmake-gui.exe ,然後 source 目錄選擇工程目錄,bin 目錄可以隨便自定義,然後點擊
Configure
選擇MinGW Makefiles
,無報錯的話,在命令行進入 bin 目錄,輸入mingw32-make
編譯工程:E:\C++\projects\helloworld\build>mingw32-make Scanning dependencies of target helloworld [ 50%] Building CXX object CMakeFiles/helloworld.dir/helloworld.cpp.obj [100%] Linking CXX executable helloworld.exe [100%] Built target helloworld
成功編譯出目標文件
helloworld.exe
,在命令行中執行如下:E:\C++\projects\helloworld\build>helloworld.exe Hello World!
-
命令行模式:
上面我們使用藉助 cmake-gui.exe 工具完成了工程的編譯,而實際上也可以直接通過命令行來完成:
$ mkdir build $ cd build $ cmake -G"Unix Makefiles" ../ -- The C compiler identification is GNU 8.1.0 -- The CXX compiler identification is GNU 8.1.0 -- Check for working C compiler: E:/C++/installs/x86_64-8.1.0-release-posix-seh- rt_v6-rev0/mingw64/bin/gcc.exe -- Check for working C compiler: E:/C++/installs/x86_64-8.1.0-release-posix-seh- rt_v6-rev0/mingw64/bin/gcc.exe -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: E:/C++/installs/x86_64-8.1.0-release-posix-se h-rt_v6-rev0/mingw64/bin/c++.exe -- Check for working CXX compiler: E:/C++/installs/x86_64-8.1.0-release-posix-se h-rt_v6-rev0/mingw64/bin/c++.exe -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: E:/C++/projects/helloworld/build
上面的步驟用於生成 makefile 文件,生成成功後,在執行 make 進行編譯:
$ make Scanning dependencies of target helloworld [ 50%] Building CXX object CMakeFiles/helloworld.dir/helloworld.cpp.obj [100%] Linking CXX executable helloworld.exe [100%] Built target helloworld
然後在命令行中執行編譯後的可執行文件:
$ .\helloworld.exe Hello World!
CMakeLists.txt
關於 CMakeLists.txt
的語法還是需要再補充一下的,可以參考:cmake-tutorial
當然,在使用過程中會發現很多很微妙的地方,例如: link_directories
必須在 add_executable
之前使用,這樣 target_link_libraries
才能從 link_directories
中指定的目錄中去搜索庫文件。
GCC 、Make 和 CMake
這裏有必要梳理一下 gcc
、make
以及 cmake
的關係:
-
gcc
:即 GNU Compiler Collection(GNU 編譯器套件),也可以理解爲編譯器,可用於編譯很多種編程語言(如:C、C++、Objective-C、Java 等);
-
make
:可以看作一個智能的批處理工具,本身沒有編譯和鏈接功能,而是通過調用
makefile
文件中用戶指定的命令來進行編譯和鏈接的; -
cmake
:可以根據
CMakeLists.txt
文件,跨平臺來生成對應平臺的 makefile 文件。
綜上所述:
-
gcc 是用於編譯和鏈接和工具,編譯少量文件可以直接使用 gcc 命令完成,但當源文件很多,用 gcc 命令去逐個編譯則是很混亂且工作量巨大。
-
因此,需要藉助 make 來來管理整個編譯過程,make 安裝 makefile 中的命令進行編譯和鏈接,而 makefile 命令中就包含了調用 gcc 去編譯某個源文件的命令。
-
而當工程規模非常大時,且需要跨平臺時,手寫 makefile 也開始變得麻煩,這是可以藉助 cmake 來生成 makefile 。
MinGW-w64 和 CMake 配置
MinGW-w64
就是 Windows 平臺下集成了 gcc 和 make (gcc.exe
和 bin/mingw32-make.exe
)的工具 ,上面我們已經分別配置好了 MinGW-w64 和 CMake ,爲了更好地配合這兩個工具來完成工程的編譯,下面需要再完成一點點額外的配置:
打開 MinGW-w64 的 bin 目錄,拷貝一份 mingw32-make.exe
改名爲 make.exe
:
$ make --version
GNU Make 4.2.1
Built for x86_64-w64-mingw32
Copyright (C) 1988-2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.