以QT為例談環境搭建
作者:哲思
時間:2022.1.5
GitHub:zhe-si (哲思) (github.com)
前言
自從實習結束,好久沒寫博客了,作為2022年的開端,打算先談一談幾乎讓所有開發人員發愁的問題——環境搭建,而貧訓,是最近在615所做的一個QT專案中QT的環境搭建,
本文主要有兩個目的:
- 提供一種簡單、有效的QT安裝與環境配置解決方案
- 從通用軟體層面聊一聊對軟體環境的理解,并嘗試回答:我們配的環境,到底是什么?
注:本文提到的“軟體”,不談軟體工程中 程式 + 資料 + 檔案 的定義,而指一個完整可運行的程式,
QT安裝與環境配置
QT簡介
說起qt,很多人下意識的認為這是一個c++的界面開發庫,qt確實在界面開發中使用最廣泛,但它并不止于此,
簡單來說,Qt 是一個跨平臺的C++應用程式開發框架,并提供給開發者一個便捷的圖形界面開發工具與較為高級的面向物件開發方法,
大家安裝與配置QT,只需按照以下步驟進行:
- 下載QT
- 安裝QT
- 配置任意一個 qt 開發環境
- 配置 qt 運行時環境
QT下載
-
途徑一:官網下載,在 Try QT -> Download QT 注冊后下載,當前QT官網下載都需要注冊,在安裝中也需要登錄賬號,
-
途徑二:百度網盤下載,筆者提供的是 qt 5.12.12 離線安裝包(qt-opensource-windows-x86-5.12.12.exe)和 qt 在線安裝包(qt-unified-windows-x86-4.2.0-online.exe)
下載鏈接,提取碼:lznc
注:可通過關倍訓聯網的方式跳過安裝包的登錄程序
-
途徑三:清華鏡像下載
鏡像中 qt 5.14.2 (該版本在大部分場景已經足夠高)及以下版本提供了安裝包,以上版本只有原始碼,若想以安裝包安裝,可以使用官網的在線下載器下載安裝,
QT安裝
離線安裝包
-
雙擊打開安裝包,如圖

左邊是安裝步驟,在 welcom 步驟需要登錄QT官網的賬號,此步驟可通過關閉網路后重新打開安裝包跳過,
-
如果登錄了,會增加一個 open source obligations 步驟讓你確認開源協議,個人用戶可忽略,勾選兩個選項,

-
setup 步驟直接next;在 installation floder 步驟選擇安裝位置,勾選“Associate common file types with Qt Creator”會自動關聯Qt相關的檔案格式到Qt Creator(就是默認用Qt creator打開)
-
Select Components 步驟選擇了安裝的具體組件,先從內容比較少的 Developer and Designer Tools 看起,

該部分是 Qt 的額外工具部分,不是 Qt 的庫,包括了必選的 Qt Creator,和可選的 Qt Creator debug工具、MinGW 工具鏈套件、Perl語言構建工具,默認選擇如圖,
MinGW 是 Qt 附贈的工具套件,構建工具鏈需要和 Qt 的版本兼容,若為了避免版本不兼容的麻煩,推薦勾選該構建工具并用它構建Qt專案,
Qt + 版本號目錄下的組件是 Qt 庫中的內容,如下圖:

在 Sources 之上的是Qt的各種版本,Qt版本對應構建工具鏈,需要與構建工具鏈版本兼容(一般會向下兼容,但盡量保持一致),各種版本的 Qt 根據使用場景至少選擇一套,
-
MSVC是visual studio(以下簡稱vs)的默認構建工具,版本對應vs的版本,舉例:使用64位 vs2017的用戶需要選擇MSVC 2017 64-bit,
-
MinGW,是 GNU 針對 windows系統的最小頭檔案與庫的集合,通過將 Linux 標準的API介面翻譯為 Windows 標準的API介面來實作跨平臺專案開發,此處筆者推薦采用 MinGW 開發(更標準,易跨平臺),舉例:開發工具鏈選擇MinGW7.3.0-64bit,則此處選擇
-
UWP是 windows 提出的通用 windows 開發的專案,期望讓不同種類的終端上跑的windows系統提供相同的API,
-
同時,Qt還為 Android 提供了一套開發工具庫,
Sources是Qt的源代碼,推薦勾選;其下是Qt的補充庫,提供了web等相關組件,并不必要,但由于不大,可以勾選上,
-
-
之后就一路next就好,如果讓同意協議,就點擊同意,其他全部默認,安裝成功撒花,
在線安裝包
在線安裝包是一個下載器,可以根據你的選擇自動從官方倉庫下載對應組件,版本可以自由挑選,但可能下載較慢,
安裝的基本步驟與離線一致,在選擇安裝組件的時候,在線安裝包顯示了當前所有版本的 qt,以下是選擇 qt6.1.2 時筆者推薦的選擇,如有特殊需要(如串口相關),可以在Additional Libraries中添加,這里筆者在 Tools 中選擇了與 Qt6.2.1 中 QT MinGW版本一致的 MinGW工具鏈套件,如下圖:


QT開發環境配置
QT Creator配置
無需配置,在安裝時自動配好,QT Creator會自動找到所有安裝的QT 版本、構建工具鏈(此處為編譯器)、debugger、cmake,當前配置可在 工具 -> 選擇 -> Kits 查看與修改,

MinGW 構建工具鏈直接包含了debug工具 gdb.exe,可以直接使用,
若使用 msvc 構建工具鏈,其中不包含 debug 工具,需要自行補充安裝,Windows 10 的除錯工具(WinDbg)集成在了 Windows 10 sdk中,若沒有安裝過該 sdk,可以根據官網教程安裝或者安裝一個vs;若已經安裝過 Windows 10 sdk(安裝過vs一般會默認安裝一個),可以在 控制面板 -> 程式和功能 找到 Windows Software Development Kit- Windows,右鍵更改,添加debug工具,如下:



配置其他開發環境的 msvc debug工具,方法同上,
visual studio配置
-
在 vs 工具 -> 拓展與更新 -> 聯機 搜索與安裝 Qt Visual studio Tools,之后重啟vs

-
在 vs -> Qt VS Tools -> Qt Versions 配置對應版本的QT目錄,需要在 path 選擇 qt 安裝路徑下 bin -> qmake.exe,在 vs 中要配置 msvc 版本的 qt,(該界面可能在不同 vs 版本下不同,但都是添加新安裝的 qt 版本)

-
配置專案的 qt 引數,在專案右鍵 -> 屬性 -> Qt Project Setting

主要引數有兩個,在 Qt Installation 選擇剛配置的 qt,在 Qt Modules 添加需要使用的 Qt 模塊,
clion配置(CMake)
clion無自己的工程配置,而是采用了 Cmake 進行專案管理,筆者比較喜歡使用該方式,配置比較清晰,專案也比較跨平臺,
clion需要配置兩個地方,構建工具鏈與工程的 CmakeLists 檔案,
-
構建工具鏈
clion沒有默認的構建工具鏈,需要自行安裝 MinGW、clang或使用 vs 的構建工具,若在環境變數配置了構建工具,可自動找到,也可以自行配置,在 檔案 -> 設定 -> 構建、執行、部署 -> 工具鏈 點擊 + 進行添加,
在最上面的為默認構建工具鏈,在專案中也可以指定其他的,但要選擇與 qt 版本兼容的構建工具鏈(最好版本對應),

-
CmakeLists.txt
CmakeLists.txt 是 cmake 工程的工程檔案,描述了工程的所有配置與構建,具體語法推薦大家在官網教程中學習,
以下給出一個 cmake 配置 qt 的 CmakeLists 配置,相信大家都一目了然:
cmake_minimum_required(VERSION 3.15.5) project(ProjectName) set(CMAKE_CXX_STANDARD 17) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) # 本地qt安裝路徑(指定了庫的查找位置,不是運行環境,若不指定,從path讀取,若找不到,找不到Qt庫) set(CMAKE_PREFIX_PATH "D:/env/c++/qt/qt5_12_12/5.12.12/mingw73_64") # 從 qt 庫中找到對應的組件庫(需要根據自己需要設定),但還沒將庫鏈接到產物 find_package(Qt5 COMPONENTS Core Gui Widgets SerialPort Xml REQUIRED) # 表示如果找不到某個組件,cmake加載專案時報錯 # 指定頭檔案的搜索路徑 include_directories( # find_package core組件自動添加qt include目錄 ) # 指定參考的外部庫的搜索路徑 link_directories( # find_package 匯入組件時,就已經找到組件的位置,無需額外指定 ) # 添加產物 add_executable(EXEName main.cpp ) # 鏈接lib到產物(將 Qt 的庫也鏈接進去) target_link_libraries(TE_TEST Qt5::Core Qt5::Gui Qt5::Widgets Qt5::SerialPort Qt5::Xml )
QT運行環境配置
將安裝的 qt 下的 bin 目錄配到環境變數 path 中即可,
構建工具鏈(MinGW、MSVC等)無需配置到 path 環境變數中,但如果想要在命令列使用 gcc 命令等,可以進行配置,注意不要把多個版本的構建工具鏈在 path 中進行配置,
小結
至此,QT環境配置完成,從在集成開發環境撰寫代碼并編譯、編譯程序正確連接到對應的靜態鏈接庫,到在 ide 中運行/除錯或直接雙擊 exe 打開,
軟體環境理解
作為一個軟體開發者,筆者多次被配置環境所折磨,尤其是跑別人的專案或者使用框架的時候,
這次配置 QT 環境,原來的專案是在 vs 下的 QT工程,經筆者根據網上教程的小心配置,終于不再飄紅,跑過了構建,又在運行程序中找不到 libgcc_s_seh-1.dll和QtCored.dll、無法定位到程式輸入點于元件等諸多問題,如下:
經過艱苦卓絕的奮戰,終于解決了一個個奇怪的問題,并搞清了問題的根源,忽然回顧了一下多次配環境的經歷與解決方法,發現原理都大同小異,在搞明白了之后,配其他環境也有種輕車熟路的感覺,所以想借此機會談一談,什么是軟體環境?到底如何配軟體環境?
QT環境
重新回顧一下我們剛剛配的 QT 環境,我們都干了什么?
安裝QT
首先我們下載安裝了一個QT,安裝是什么?
最簡單的安裝就是解壓壓縮包,安裝包就是一個壓縮包,內部可能包含了多個可執行檔案(exe)、元件(dll)等檔案,我們將它解壓縮到某個檔案夾就是最簡單的安裝程序,而我們就是要正確運行其中的某個或某幾個可執行檔案,
有時,安裝中還伴隨著下載程序,相當于安裝包只包含了部分的程式檔案,在安裝中可以根據用戶選擇自動下載其他附加功能的程式檔案,
在安裝中,有時要我們選擇是否在桌面或者選單添加快捷方式,其實就是根據程式的主可執行檔案生成快捷方式并放到桌面或者選單檔案夾,以下是筆者的選單檔案夾:

有些時候,程式希望能在全域找到自己,就會把自己的可執行檔案或者元件添加到 path 環境變數下,或者放到已經添加到 path 的檔案夾中,可以在cmd輸入“path”查看當前的path環境變數包含的內容:

還有些時候,安裝包希望讓作業系統感知到安裝的軟體,還會把自己的資訊寫到注冊表中,下面是筆者電腦中QQ在注冊表中注冊的資訊:

安裝還有根據軟體需要而產生的很多個性化需求,但無外乎都是讓安裝的軟體讀寫某些資訊或者找到某個檔案,進而可以正確運行,
對于 QT,它從安裝包與網路上的官方倉庫獲得需要的檔案后,全部放到了安裝路徑,并將自己的資訊寫到注冊表,告訴了作業系統它的存在,但并未在環境變數進行配置,所以無法在全域直接找到 QT,
配置QT開發環境
接下來,我們配置了 QT 的開發環境,
像開發c/c++的 dev c++、visual studio、clion、開發 java 的 eclipse、idea等,相信大家都不陌生,而他們都有一個統一的名字,叫 IDE,全名“集成開發環境”,下圖是筆者常用的 IDE :
引 RedHat 對 IDE 的定義:集成開發環境(IDE)是一種用于構建應用程式的軟體,可將常用的開發人員工具合并到單個圖形用戶界面(GUI)中,
IDE 主要包括一個源代碼編輯器、本地構建版本自動化工具(也就是代碼的編譯、封裝等)、除錯器,當然還可能集成了一些其他開發中的工具,如資料庫訪問工具、性能分析器等,
所以顧名思義,我們配置 QT 的開發環境,就是將 QT 的開發 sdk 集成到 ide 中(讓 IDE 能找到 QT 的 sdk),好讓 ide 可以使用 sdk 完成 QT 的配置、構建、運行/除錯作業,同時復用 ide 提供的其他工具,
在前面,我們配置了 c++ 的構建工具鏈(MinGW、MSVC),用來構建一般的 c++ 程式,
同時配置了 QT 的特有構建工具與庫,
- vs 的 QT VS Tools 采用的是 qmake 進行專案構建描述,需要配置 qmake 的位置,而 qmake 知道如何找到和使用 QT 對應的構建工具與庫,
- clion(cmake)不直接配置并使用 QT 的某個工具,而是采用 cmake 對構建的通用描述能力,QT 在庫中撰寫 cmake 可以直接讀取的庫的描述檔案,該描述檔案描述了應該如何找到 uic、rcc、moc 等 QT 特有的構建工具并使用它們將 .ui、.rcc、QT 元物件等處理為一般 c++ 的源代碼,該描述也說明了 QT 庫的位置,所以我們才可以通過 find_package 自動找到對應的庫,
配置QT運行時環境
最后,我們配置了 QT 的運行時環境,
運行時環境是什么?顧名思義,就是程式運行的時候它所處的環境,而我們說某個軟體的運行時環境,也就是在說該軟體對外界的依賴,
這樣就很清晰了,為什么軟體在運行時環境不對時會報錯?因為軟體在這個運行時環境中運行,依賴(也就是使用)了環境中的其他東西,當這個東西找不到或者和我們想象中的不一樣,我們沒法使用它時,程式就運行不下去了,就會報錯,
那環境中我們的依賴是什么呢?在大部分情況下,我們可以說是元件,元件在 Windows 下后綴名為 .dll,在 linux 下為 .so,
那 QT 程式需要什么依賴呢?就是 QT 安裝目錄中 bin 內的 dll(Windows 下的元件),所以我們把 QT 的 bin 目錄配到環境變數里即可,
注:此處無需配置構建工具鏈的 bin 目錄,
軟體環境
剛才我們重新回顧了一遍 QT 的安裝與環境配置的流程與每一個流程的意義,回顧其他安裝與配置的流程,便會發現都大同小異,而其中的原理都是一致的,我們可以基于 QT 的配置由點到面的總結一下:
一個程式,從源代碼到運行,包括:編譯(compile)、鏈接(link)、加載(load)、運行(execute),對應的GNU工具一般為:編譯器compiler(gcc)、聯結器linker(ld)、加載器loader,
一般編譯和鏈接統稱為編譯,期間為編譯時(compile time);而加載和運行統稱為運行,期間為運行時或執行時(runtime/execution time),
-
安裝
安裝就是解壓,并幫助用戶便捷的配置運行時環境的程序,概念比較簡單,在上一節“QT 環境”的“安裝QT”小節中已基本敘述清楚,
-
軟體環境
-
開發環境(編譯時環境是開發環境的子集):
-
構建工具:如編譯器、聯結器、QT元物件處理器 moc、QT 用戶界面編譯器 uic、QT 資源檔案編譯器 rcc 等,這些構建工具也有自己的運行時環境(依賴其他動態庫等),共同組成了被開發的軟體的編譯時環境,
-
除錯工具:gdb
-
專案依賴的靜態鏈接庫、頭檔案與隱式加載元件:
專案在編譯程序中需要使用的外部庫,
-
靜態鏈接庫:
編譯時(compile time)被使用(鏈接的時候),在鏈接靜態庫的時候,聯結器會在其中找到所需要鏈接的函式,然后將它們拷貝到執行檔案,這種拷貝是完整的拷貝,所以在鏈接成功后,程式運行不需要靜態庫的參與,
-
頭檔案:
函式或型別等的宣告檔案,向編譯器宣告該函式或型別等已經存在,在其他地方有宣告的具體實作,在鏈接的時候將二者關聯起來,如果找不到具體實作,會報錯:
undefined reference to xxx靜態鏈接庫與隱式加載的元件都是宣告的實作可能存在的地方,
-
隱式加載的元件:
在運行時環境介紹元件時進行詳細介紹,
-
-
其他:如代碼分析器、性能分析器等,文本編輯與代碼提示也包含在內,
-
-
運行時環境 / 執行時環境:
-
元件
元件的查找方式是名字查找,也就是說,呼叫某個函式,只要元件記憶體在該名字的函式(函式簽名也一致),哪怕不是一開始的元件也可以正常呼叫,
-
隱式加載
編譯時和運行時被使用,在編譯時,聯結器在其中找到所需要的函式(或其他物件檔案),生成地址/位置無關代碼(Position Independent Code (PIC)),并沒有真正的實作拷貝;在運行時(runtime/execution-time),某個程式在運行中要呼叫某個元件函式的時候,作業系統首先會查看所有正在運行的程式,看在記憶體里是否已有此庫函式的拷貝了,如果有,則讓其共享那一個拷貝;只有沒有才鏈接載入,
如果鏈接庫被更換,系統會自動同步記憶體,
-
顯示加載
在代碼中主動呼叫系統 API 加載元件,由于指定了準確的位置,與讀取檔案類似,
-
-
其他軟體
-
資料庫
-
檔案
-
系統注冊表
-
等等,可以說凡是軟體使用到的都是其運行環境,軟體最大的軟體環境就是作業系統了,
-
-
而“配環境”,就是指讓系統無二義性的找到我們想要的外部依賴,
開發環境
開發環境簡單來說就是程式猿敲代碼的環境,從我們創建一個專案、到源代碼編輯與版本管理、再到源代碼構建、最后到程式除錯等一整個開發流程,
最基本的開發環境就是編譯器和聯結器,其次是文本編輯器,再然后是除錯器、專案構建工具等等,
在開發中,我們可以分別使用每一個工具(可執行檔案)去處理某個開發流程;也可以使用一個 ide 集成開發環境,告訴 ide 那些工具在哪里,這樣你就可以在 ide 中便捷的使用所有的工具了,
一般開發環境問題較少,但請注意:
- 有些庫是與構建工具鏈的版本一一對應的
- 有些庫分 release / debug 版本、64 / 32 位,盡量選擇場景對應的版本
運行時環境
運行時環境是出問題最多的地方,尤其是運行時環境中的元件,因為它采用運行時動態查找鏈接庫的位置,
我們還沒有詳細說明“找不到”和“不一樣”的具體含義,那什么時候我們會找不到依賴呢?這就要先說系統是如何找這個依賴的,這里以 Windows 傳統的桌面應用程式 和 linux 為例,
-
Windows 桌面應用程式
在 Windows 傳統的桌面應用程式中(官方說明),系統會按照以下順序搜索目標(以下為默認的安全 DLL 搜索模式,非安全模式就是將第5項提前插入到第二項,也就是當前目錄優先于系統的庫目錄):
- 從其中加載應用程式的目錄,
- 系統目錄, 使用 GetSystemDirectory 函式獲取此目錄的路徑,
- 16 位系統目錄, 沒有函式可獲取此目錄的路徑,但會進行搜索,
- Windows 目錄, 使用 GetWindowsDirectory 函式獲取此目錄的路徑,
- 當前目錄,
- PATH 環境變數中列出的目錄, 請注意,這不包括應用路徑注冊表項指定的 每個應用程式路徑 , 計算 DLL 搜索路徑時,不會使用應用路徑密鑰,
-
linux
- 編譯目標代碼時指定的動態庫搜索路徑;
- 環境變數 LD_LIBRARY_PATH 指定的動態庫搜索路徑;
- ldconfig 快取組態檔 /etc/ld.so.conf 中指定的動態庫搜索路徑;
- 系統默認動態庫搜索路徑 /lib;
- 系統默認動態庫搜索路徑 /usr/lib,
找不到元件,通常會報錯:
由于找不到 dll, 無法繼續執行代碼,
這里還有幾個注意點:
-
查找的順序的前后
系統會按照順序根據庫的名字進行查找,直到找到第一個符合的動態庫,也就是說當出現同名動態庫,前面的配置優先于后面的配置,
這里還要注意,一般有一個環境變數作為用戶自定義的動態庫搜索路徑集合,而該環境變數的賦值是覆寫方式,可能存在非增量式覆寫或覆寫了后面其他程式使用的元件,
-
記憶體已經加載某靜態庫的問題
如果記憶體已加載某動態庫,則后來的程式如果依賴該名字的動態庫,系統會直接使用記憶體中的同名動態庫,不會重新搜索,
而“不一樣”指的是與預期呼叫的函式宣告不一致,這可能由于版本不一致,也可能被后添加的同名庫覆寫導致呼叫了錯誤的動態庫等,而該錯誤下通常會報錯:
無法定位程式輸入點 xxx 于 xxx.dll 上
總結,把書本讀薄
讀到這里,想必大家對軟體環境與環境搭建有了一定的認識,但可能上面的文字太多,還不夠清晰,讓我們一起把書讀薄,
- 環境主要有兩種:開發環境、運行時環境
- 開發環境下的產物就是軟體本身,而軟體想要獨立運行,就需要在合適的運行時環境下
- 配置環境就是讓系統無二義性的找到外部的依賴,如構建工具、靜態庫、動態庫等
- 配置開發環境重點要解決構建工具鏈與靜態鏈接庫的兼容、靜態鏈接庫與構建目標(x86 / x64、release / debug)的兼容
- 配置運行時環境重點解決確定軟體的實際運行時環境、讓系統正確找到對應的元件兩個問題
后記
理解了軟體的環境與環境的搭建對一個開發人員十分重要,不但大大減輕了配環境帶來的成本,也讓我們的軟體包更清晰易用、兼容性好,
包括 python 的 pip、烏班圖的 apt 包管理器也是這個道理,但它們通過更清晰的軟體包的依賴自描述讓軟體包管理變得更加明確、簡單,而很多游戲將所有依賴的元件都打包到游戲中也是一個經典的解決運行時依賴的方法,
最后,獻出美好的祝福:愿世間再無因配環境而痛苦的程式猿!
本文來自博客園,作者:_哲思,轉載請注明原文鏈接:https://www.cnblogs.com/zhe-si/p/16001124.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/442761.html
標籤:C++
