前言
Qt 是 C++ 的庫,Qt 在 ansi C++ 的基礎上進行了一點擴展。 有很大一部分人在學習Qt之前,連C++如何編譯似乎都不太清楚。 但本文不對C++編譯原理做過多的介紹,只提取Qt部分的編譯原理進行解析。
本文中將舍棄IDE或qmake、cmake等工具的束縛,嘗試通過幾個例子,一步一步從標准 C++ 的編譯過渡到 Qt 的編譯。
本文涉及的都是最基本的東西,或許可以說,只要你用C++ Qt,不管是通過哪種工具(qmake、cmake、boost.build、qtcreator、vs2008、Eclipse、...),本文的內容都是需要理解的(盡管真正寫程序時,我們都不會直接用C++編譯器來編譯Qt程序)。
注意 >> 由於本地Qt環境版本是 Qt 5.12.8,代碼更偏向於該版本,如果你是其他版本,請注意修改。
如果你對命令行比較恐懼,或許願意先看看資料 GCC新手入門
關鍵字
- UIC
- RCC
- MOC
Qt之UIC工具
// 簡介 >> UIC 是Qt環境下的一個插件,其功能是將*.ui文件擴展為ui_*.h文件,這個文件是C++源代碼頭文件
// 用法 >> uic *.ui -o ui_*.h
// 輸出uiC++源代碼文件 >> uic mainwindow.ui -o ui_mainwindow.h
/*
Options:
<-h> -help 顯示此幫助並退出
<-v> -version 顯示此版本信息
<-d> -dependencies 顯示依賴項
<-o> <file> 將輸入放到<file>中
<-tr> <func> 對i18n使用func()
<-p> -no-protection 禁用輸出文件的頭保護
<-n> -no-implicit-includes 禁用為uic生成的窗體生成#include指令
<-g> <name> 更改生成器
*/
Qt之RCC工具
// 簡介 >> RCC 是Qt環境下的一個插件,其功能是將*.qrc文件擴展為qrc_*.cpp文件,這個文件是將所有導入到QRC文件的資源擴展為數據並將其存放到靜態區。
// 所以這些圖片資源是編譯到exe(可執行文件),這樣軟件不會因為外部資源的缺失造成軟件界面的異常。有效的提高用戶體驗度。
// 注意 >> 一般的較小的軟件資源可以使用QRC的形式來添加到軟件,這將提高軟件的存活性,健壯性。
// 用法 >> rcc [name] [*.qrc] -o [qrc_*.cpp]
// 輸出 qrc C++源代碼文件 >> rcc mainwindow mainwindow.qrc -o qrc_mainwindow.cpp
/*
Options:
-o file 將輸出寫入文件而不是stdout
-name name 創建名為的外部初始化函數
-threshold level 壓縮文件的閾值
-compress level 按級別壓縮輸入文件
-root path 用根路徑作為資源訪問路徑的前綴
-no-compress 禁用所有壓縮
-binary 輸出二進制文件以用作動態資源
-namespace 關閉命名空間宏,不會生成 QT_BEGIN_NAMESPACE | QT_END_NAMESPACE
作用域控制宏
-project 輸出包含所有
當前目錄中的文件
-version 顯示版本
-help 顯示幫助
*/
QRC轉換CPP代碼效果圖
Qt之MOC工具
// 簡介 >> MOC 是Qt環境下的一個插件,其功能是將 Qt 相關的內核代碼擴展成CPP源代碼
// 用法 >> moc [options] <header-file>
// 輸出 moc C++源代碼文件 >> moc mainwindow.h -o moc_mainwindow.cpp
Options:
-o<file> 將輸出寫入文件而不是stdout
-I<dir> 將dir添加到頭文件的include路徑
-E 僅預處理;不生成元對象代碼
-D<macro>[=<def>] 定義宏,具有可選定義
-U<macro> 取消定義宏
-i 不要生成#include語句
-p<path> 包含文件的路徑前綴
-f[<file>] 強制使用#include<file>,可選文件名
-nn 不顯示便箋
-nw 不顯示警告
@<file> 從文件讀取其他選項
-v 顯示版本
*/
編譯原理實例圖
<1> C++沒有信號和槽是Qt的特性,及ui庫相關的模塊,所以Qt會將項目源文件擴展項擴展為 C++ 代碼,這樣就可以使用 C++的編譯器來編譯Qt的項目
<1.1> ui 擴展為 ui_*.h
<1.2> qrc 擴展為 qrc_*.cpp
<1.3> 引用了 Qt 的元對象系統頭文件擴展為 moc_<file>.cpp
<2> 現在Qt項目中的所有代碼都是C++源代碼了,這里就可以直接使用C++編譯器把源代碼編譯成二進制文件
<3> 執行編譯的鏈接步驟,輸出可執行文件
手動編譯Qt項目Gui案例
准備 >> 新建一個默認的 Qt Gui 程序,將其源代碼拷貝到准備好的編譯目錄,有以下文件:
<1> main.cpp
<2> widget.cpp
<3> widget.h
<4> widget.qrc
<5> widget.ui
<6> widget.pro widget.pro.user 刪掉,我們用不着
操作步驟:
<1> 新建編譯輸出目錄
mkdir build
cp .../src_dir/*.* .../build/
cd .../build/
<2> 擴展ui文件為C++格式
/opt/Qt5.12.8/5.12.8/gcc_64/bin/uic widget.ui -o ui_widget.h
<3> 擴展qrc文件為C++格式
/opt/Qt5.12.8/5.12.8/gcc_64/bin/rcc widget widget.qrc -o qrc_widget.cpp
<4> 擴展widget.h到moc_widget.cpp
/opt/Qt5.12.8/5.12.8/gcc_64/bin/moc widget.h -o moc_widget.cpp
<5> 當前所有的代碼都為C++代碼了,可以進行編譯了
<5.1> 編譯main.cpp
g++ -c -pipe -g -std=gnu++11 -Wall -W -D_REENTRANT -fPIC -DQT_DEPRECATED_WARNINGS -DQT_QML_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -I/opt/Qt5.12.8/5.12.8/gcc_64/include -I/opt/Qt5.12.8/5.12.8/gcc_64/include/QtWidgets -I/opt/Qt5.12.8/5.12.8/gcc_64/include/QtGui -I/opt/Qt5.12.8/5.12.8/gcc_64/include/QtCore -I. -isystem /usr/include/libdrm -I. -I/opt/Qt5.12.8/5.12.8/gcc_64/mkspecs/linux-g++ -o main.o main.cpp
<5.2> 編譯 widget.h
g++ -c -pipe -g -std=gnu++11 -Wall -W -D_REENTRANT -fPIC -DQT_DEPRECATED_WARNINGS -DQT_QML_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -I/opt/Qt5.12.8/5.12.8/gcc_64/include -I/opt/Qt5.12.8/5.12.8/gcc_64/include/QtWidgets -I/opt/Qt5.12.8/5.12.8/gcc_64/include/QtGui -I/opt/Qt5.12.8/5.12.8/gcc_64/include/QtCore -I. -isystem /usr/include/libdrm -I. -I/opt/Qt5.12.8/5.12.8/gcc_64/mkspecs/linux-g++ -o widget.o widget.cpp
<5.3> 編譯qrc_widget.cpp
g++ -c -pipe -g -std=gnu++11 -Wall -W -D_REENTRANT -fPIC -DQT_DEPRECATED_WARNINGS -DQT_QML_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -I/opt/Qt5.12.8/5.12.8/gcc_64/include -I/opt/Qt5.12.8/5.12.8/gcc_64/include/QtWidgets -I/opt/Qt5.12.8/5.12.8/gcc_64/include/QtGui -I/opt/Qt5.12.8/5.12.8/gcc_64/include/QtCore -I. -isystem /usr/include/libdrm -I. -I/opt/Qt5.12.8/5.12.8/gcc_64/mkspecs/linux-g++ -o qrc_widget.o qrc_widget.cpp
<5.4> 編譯moc_widget.cpp
g++ -c -pipe -g -std=gnu++11 -Wall -W -D_REENTRANT -fPIC -DQT_DEPRECATED_WARNINGS -DQT_QML_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -I/opt/Qt5.12.8/5.12.8/gcc_64/include -I/opt/Qt5.12.8/5.12.8/gcc_64/include/QtWidgets -I/opt/Qt5.12.8/5.12.8/gcc_64/include/QtGui -I/opt/Qt5.12.8/5.12.8/gcc_64/include/QtCore -I. -isystem /usr/include/libdrm -I. -I/opt/Qt5.12.8/5.12.8/gcc_64/mkspecs/linux-g++ -o moc_widget.o moc_widget.cpp
<6> 鏈接
g++ -Wl,-rpath,/opt/Qt5.12.8/5.12.8/gcc_64/lib -o testting main.o widget.o qrc_widget.o moc_widget.o /opt/Qt5.12.8/5.12.8/gcc_64/lib/libQt5Widgets.so /opt/Qt5.12.8/5.12.8/gcc_64/lib/libQt5Gui.so /opt/Qt5.12.8/5.12.8/gcc_64/lib/libQt5Core.so -lGL -lpthread
<7> Qt程序打包
省略