1.編譯器與集成開發環境
編譯器,即Compiler,是讓源程序生成計算機語言的工具。編譯器的工作原理稱爲編譯原理;編譯原理號稱計算機科學課程的“四大天書”之一。但編譯原理,本質就是告訴你,編譯器如何通過關鍵字識別,詞法分析,語法分析,語義分析和語言優化,生成可執行程序的過程。隨着計算機性能的提高,很多語言已經不使用編譯器,開始使用JIT的解釋器。但解釋器的工作原理,和編譯器本身並無太大區別。
編譯器只用來編譯生成可執行文件,但工程師進行項目研發,最常規工作是進行Coding。Coding的方法是通過文本編輯器(Editor)。理論上來說,文本編輯器只要能把鍵盤輸入的字符進行顯示並存取就可以了。但是,好的文本編輯器,最好能顯示出編程語言的特點,並顯示出可能的錯誤。隨着計算機技術的發展,一些文本編輯器可以展示出可能的編程語法錯誤。
可執行程序生成以後,一般都需要調試。調試器,即Debugger,可以讓可執行程序與源文件對應起來,並監視程序運行的對應數值變化。
這三個組成,是軟件程序生成必不可少的三個組件。對於傳統的Unix/Linux工程師來說,可以用Vi工具編輯源程序,gcc/g++(GNU編譯器)編譯可執行文件,gdb調試可執行文件。但顯然,這三個工具,如果能組合起來,顯然會發揮更大功能。
集成開發環境,即IDE(Integrated Development Environment),就是這三個組件的組合。
比較常見的IDE有:
1)Visual Studio:微軟的官方IDE,號稱“宇宙第一IDE”;
2)Eclipse:免費IDE,主要用於JAVA開發(如下圖所示);
3)Pycharm:Python的IDE;
4)Goland:Golang語言IDE;
5)IDEA:主要用於JAVA開發,集成了廣泛的工具,可以用於Web和安卓移動應用程序開發;
6)QT Creator:QT開發的通用工具,本文介紹的目標(如下圖所示)。
2.QTCreator工作原理
其實,上文已經介紹了多的IDE的基本原理,但本文由於是介紹QTCreator,所以,會比較詳細介紹QT Creator的工作原理。
在新建項目之後,會生成相應的pro文件。pro文件,是對本次項目的詳細描述。添加文件,會讓相應的文件加到pro裏面(如下圖所示)。
然而,整個IDE最難的部分,是編譯器功能。編譯器功能設置如下:
1)打開項目;
2)可以看出相應的編譯器設置情況。
可以得知,QT Creator的構建過程爲“qmake.exe XXX.pro -spec win32-g++”。
打開QT安裝目錄,隨後進行對應的編譯器選項。我個人的編譯器爲MinGW,然後,進入mingw53_32文件夾裏面。然後進入mkspecs文件夾下面(即-spec所對應的文件夾)。然後,進入選項配置的win32-g++目錄。
win32-g++文件夾下面,只有兩個文件:1)qmake.conf; 2)qplatformdefs.h。其中,qplatformdefs.h是用來對平臺進行支持的。而編譯選項的基本配置在qmake.conf裏面。
打開qmake.conf,可以看到最關鍵的幾句話
load(device_config)
include(../common/g++-base.conf)
include(../common/angle.conf)
include(../common/gcc-base.conf)
load(qt_config)
可以得知,qmake文件,需要g++-base.conf,gcc-base.conf等文件的支持。同時,可以看到幾個文件常量定義:
MAKEFILE_GENERATOR = MINGW
QMAKE_PLATFORM = win32 mingw
CONFIG += debug_and_release debug_and_release_target precompile_header
DEFINES += UNICODE
QMAKE_COMPILER_DEFINES += __GNUC__ WIN32
QMAKE_EXT_OBJ = .o
QMAKE_EXT_RES = _res.o
QMAKE_CC = $${CROSS_COMPILE}gcc
QMAKE_LEX = flex
QMAKE_INCDIR =
QMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -o $obj $src
QMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
QMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $obj $src
QMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
QMAKE_LINK = $${CROSS_COMPILE}g++
QMAKE_LINK_C = $${CROSS_COMPILE}gcc
QMAKE_LFLAGS_EXCEPTIONS_ON = -mthreads
如果你對Makefile有了解,即可知道這些文件爲Makefile的選項。
gcc-base.conf文件的主要配置爲:
QMAKE_CFLAGS_OPTIMIZE = -O2
QMAKE_CFLAGS_OPTIMIZE_FULL = -O3
QMAKE_CFLAGS_OPTIMIZE_DEBUG = -Og
QMAKE_CFLAGS_OPTIMIZE_SIZE = -Os
QMAKE_CFLAGS += -pipe
QMAKE_CFLAGS_DEPS += -M
QMAKE_CFLAGS_WARN_ON += -Wall -W
QMAKE_CFLAGS_WARN_OFF += -w
QMAKE_CFLAGS_RELEASE += $$QMAKE_CFLAGS_OPTIMIZE
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -g
QMAKE_CFLAGS_DEBUG += -g
QMAKE_LFLAGS +=
QMAKE_LFLAGS_DEBUG +=
QMAKE_LFLAGS_APP +=
QMAKE_LFLAGS_RELEASE +=
QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO +=
g++-base.conf的主要選項爲:
QMAKE_COMPILER = gcc
QMAKE_CC = gcc
QMAKE_LINK_C = $$QMAKE_CC
QMAKE_LINK_C_SHLIB = $$QMAKE_CC
QMAKE_CXX = g++
QMAKE_LINK = $$QMAKE_CXX
QMAKE_LINK_SHLIB = $$QMAKE_CXX
QMAKE_PCH_OUTPUT_EXT = .gch
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_CXXFLAGS_CXX14 = -std=c++1y
QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
QMAKE_CXXFLAGS_GNUCXX11 = -std=gnu++11
QMAKE_CXXFLAGS_GNUCXX14 = -std=gnu++1y
QMAKE_CXXFLAGS_GNUCXX1Z = -std=gnu++1z
QMAKE_LFLAGS_CXX11 =
QMAKE_LFLAGS_CXX14 =
QMAKE_LFLAGS_CXX1Z =
即規定了g++編譯服從的C++標準。同時可以得知,QT Creator其實提供了可以擴展的標準。
在這些配置之後,並運用 “qmake.exe XXX.pro -spec win32-g++” 這一命令,可以生成Makefile。Makefile在自己編譯所在的路徑之下(如圖所示)。
有Makefile,即可編譯生成可以執行文件。
3.pro文件與編譯選項
值得注意的是,常見的編譯選項,可以通過修改pro文件,從而改變相應設置,從而打開或者關閉某些功能。舉例如下:
1)讓release版本可以調試,可以在pro文件裏,輸入如下:
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_LFLAGS_RELEASE = $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO
2)讓QT Creator禁止O2優化
#Debug 禁止O2優化
QMAKE_CFLAGS_DEBUG -= -O2
QMAKE_CXXFLAGS_DEBUG -= -O2
#Release 禁止O2優化
QMAKE_CFLAGS_RELEASE -= -O2
QMAKE_CXXFLAGS_RELEASE -= -O2
4編譯優化與禁止優化
可執行程序,在正式發佈的時候,會進行編譯優化。
編譯器優化的原則是:減少不必要的值傳遞,從而使空間更小,速度更快。
常見的優化方法爲(更多可參考網址:https://www.jianshu.com/p/0caa9cfd995a,或者自己查閱更多資料):
1)常量傳播;
2)常量摺疊;
3)複寫傳播;
4)公共子表式消除;
5)無用代碼消除;
6)數組範圍檢查消除;
7)方法內聯;
8)逃逸分析。
但優化會讓調試的時候出問題。最常見的問題爲,如果有優化,會發現調試的程序在源代碼之間亂跳,而不知道具體的程序運行地址。
優化的級別一般爲O0、O1、O2、O3;一般情況下,在調試時,禁止O2優化即可達到目的。