Qt之編譯原理解析


前言
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代碼效果圖

image

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> 執行編譯的鏈接步驟,輸出可執行文件

image

手動編譯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程序打包
      省略
程序編譯后執行效果圖

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM