當然這完全沒什麼,其他同學至少兩年前就寫過了LOL。
只能說Qt 真是相當強大的工具,最基本的signal & slot的概念,如果對GTK的callback熟悉的話,很快就能上手。
一般在寫Qt時,最常用的還是用qmake來產生Makefile,畢竟qmake寫得還不賴,打一次就會產生好Makefile,接著make即可;不過有時個人習慣還是偏好用gnu-make,可以自己編寫Makefile,做一些細部的調整,用qmake的話只要重新產生一次Makefile,這些細部調整就要重新再修改一次。
這篇就是說明一下,要如何使用gnu-make來處理Qt專案。
--
基本上Qt的運作原理,是對原有的C++進行擴展,然後透過Qt提供的解析程式,產生額外的原始碼檔,少了這些額外的原始碼,在編譯的時候會產生一堆可怕的錯誤資訊,要用gnu-make編譯Qt專案,其實只要呼叫這些解析程式來產生原始碼即可;總共會用到的程式有三個:moc, rcc, uic;分別作用是:產生meta object(故名Meta-Object Compiler)、處理resource(resource compiler)檔、產生介面檔(User Interface Compiler)。
一般Makefile裡面會有這些東西,用來把所有的source轉換成object file。
SOURCE_FILE = main.cpp OBJECT_FILE += $(addsuffix .o, $(basename $(SOURCE_FILE)))
為了Qt,我們加上下列的變數定義:
#================================================== # Qt special function #================================================== QT_LIBS = -lQtCore -lQtGui -lQtOpenGL QT_PATH = /usr/lib/qt4/bin QT_MOCFILE = mainwindow.h QT_RCCFILE = resource.qrc QT_UICFILE = first.ui QT_MOCSOURCE = $(addprefix moc_, $(addsuffix .cpp, $(basename $(QT_MOCFILE)))) QT_RCCSOURCE = $(addprefix qrc_, $(addsuffix .cpp, $(basename $(QT_RCCFILE)))) QT_UICSOURCE = $(addprefix ui_, $(addsuffix .h, $(basename $(QT_UICFILE))))
這一整個區塊與QT有關,所有參數都加上QT為標示。
QT_PATH設定Qt的執行檔位置,如果安裝在其他地方、或要用其他版本就要自己換地方。
QT_*FILE是先定義,moc, rcc, uic分別要處理的檔案,moc會處理所有.h檔,產生含meta object的cpp檔;rcc會處理qrc file,產生相對應的cpp檔;uic則會處理ui,產生可包入的header file。
透過makefile的suffix, prefix,轉成我們需要轉出的檔案名稱,個人的習慣是在這些檔名前加上關鍵字moc_, qrc_, ui_。
--
接著是利用implicit rules來compile所有的物件檔:
TARGET = program BIN_DIR = bin LIBRARY_DIR = library SOURCE_FILE = main.cpp $(QT_MOCSOURCE) $(QT_RCCSOURCE) OBJECT_FILE += $(addsuffix .o, $(basename $(SOURCE_FILE)))
由於moc和rcc會產生新的cpp檔,因此需要將它們列入;然後就可以用implicit rules執行:
%.o:%.c $(CC) -c lt; -o $@ $(CFLAGS) $(INCLUDE) @$(MOVE) $@ $(LIBRARY_DIR) %.o:%.cpp $(CXX) -c lt; -o $@ $(CXXFLAGS) $(INCLUDE) @$(MOVE) $@ $(LIBRARY_DIR) moc_%.cpp: %.h $(QT_PATH)moc $(DEFINES) $(INCLUDE) lt; -o $@ qrc_%.cpp: %.qrc $(QT_PATH)rcc lt; -o $@ ui_%.h: %.ui $(QT_PATH)uic lt; -o $@前兩項是將c/cpp-編成 .o檔,當遇到QT_MOCSOURCE, QT_RCCSOURCE的檔案,就會由moc, rcc產生。
另外在編譯主程式的相依性中,原本我們只要它編譯所有的OBJECT_FILE,現在還要加上由uic產生的header file:
$(TARGET): $(OBJECT_FILE) $(QT_UICSOURCE) cd $(LIBRARY_DIR); \ $(LINKER) -o $@ $(OBJECT_FILE) $(LIBS); \ cd .. mv $(LIBRARY_DIR)/$@ $(BIN_DIR)如此一來,就會觸發uic產生出header file。
--
透過以上的設定,即可完成Qt專案的編譯,不過最後還是要說,雖然我這裡是這麼寫,但其實真的用的時候還是用qmake來產生Makefile =w=,套句AZ大神的話「它寫得這麼好幹嘛不用?你白痴嗎。」
結論:這篇網誌是一篇垃圾,寫Qt請愛用qmake。 lol
參考資料:
1. C++ GUI Programming with Qt 4
2. http://woboq.com/blog/how-qt-signals-slots-work.html