shadow build
shadow build 是什么東西?就是將源碼路徑和構建路徑分開(也就是生成的makefile文件和其他產物都不放到源碼路徑),以此來保證源碼路徑的清潔。
這不是qmake獨創的東西,cmake中早就使用這個東西了
cmake |
qmake |
備注 |
|
in-source |
cmake . |
qmake project.pro |
在源碼路徑下執行 |
out-of-source |
mkdir build cd build |
mkdir build cd build |
創建目錄,在其他路徑下執行(參數指向源碼路徑) |
- 注意:
- qmake 的shadow build還是很不完善,與cmake尚不可同日而語
- qmake 的shadow build目錄不可以是源碼目錄的子目錄
之前
在shadow-build之前,為了將生成物和源碼盡可能的分開,我們一般都會設置很多qmake的變量,比如:
DESTDIR = $$PWD/bin |
目標文件放置位置 |
DLLDESTDIR = $$[QT_INSTALL_BINS] |
win下拷貝動態庫到qt安裝路徑 |
MOC_DIR = $$PWD/temp |
moc的產物放置何處 |
RCC_DIR = $$PWD/temp |
rcc的產物放置何處 |
UI_DIR = $$PWD/temp |
uic的產物放置何處 |
OBJECTS_DIR =
P
TARGET |
編譯器生成的.o(.obj)等文件放置 |
這樣一來,我們將Qt的擴展部分(moc/rcc/uic)以及編譯器的中間產物都放置到了一個 temp 子目錄中。源碼還算比較清潔,可是和out-of-source比較的話,還是不太爽:
- 生成的 makefile 依然在源碼路徑下
- 如果一套源碼要分別用msvc2008、msvc2008、mingw分別編譯又不互相干擾呢?
創建一個構建目錄,然后在該目錄下調用合適的qmake,並指向源碼下的工程文件即可
qmake ../project-sources/project.pro
本人的一個例子:
假設項目存於huang/下面叫xxx
shadow目錄與huang位於同一級叫huangbuild
我們想在huangbuild下建立xxx-Debug與xxx-Release用來標示是xxx的debug與release
我們需要進入huangbuild目錄下,如果是debug就進debug目錄下,這個時qmake ../../huang/xxx.pro
release與此類似
有用的變量
前面提到的了,qmake的shadow-build功能尚不完善
PWD |
使用該變量的文件(.pro 或 .pri)所在目錄,注意對比下一個 |
_PRO_FILE_PWD_ |
pro文件所在目錄(注意:即使它用在pri文件內,也是指代的包含它的pro文件所在的目錄) |
_PRO_FILE_ |
pro文件的全路徑 |
OUT_PWD |
生成的makefile文件所在路徑,和_PRO_FILE_PWD_對應 |
當不使用shadow build構建時,OUT_PWD 和 _PRO_FILE_PWD_ 是相同的,據此,我們可以判斷采用了何種構建方式,進而采用不同的動作:
!contains(_PRO_FILE_PWD_, $${OUT_PWD}) { #do something when using shadow build } #直接使用equals更好一些,但是manual對此沒有任何說明(所以我不清楚你的qmake對此是否支持,至少Qt4.5以后都是支持的) !equals(_PRO_FILE_PWD_, OUT_PWD) { #do something when using shadow build }
比如說,采用out-of-source構建時,我們可能需要將一些文件從源碼目錄拷貝到構建目錄下,用cmake時,這個很容易做到,但在qmake下,似乎缺少通用的方式,一個簡單的demo如下:
- 注意:所有要拷貝的文件只能用相對路徑指定(你可以幫着改進一下,我沒找到合適的函數)
-
這段代碼需要放到pro文件內,或者同目錄的pri文件內
FILES_COPY_SRC = $$SOURCES / dbzhang800.txt / images/abc.png / i18n/abcd.qm win32{ COPY = copy /y MKDIR = mkdir }else{ COPY = cp MKDIR = mkdir -p } !equals(_PRO_FILE_PWD_, OUT_PWD) { for(f, FILES_COPY_SRC){ dist_file = $$OUT_PWD/$$f dist = $$dirname(dist_file) win32:dist = $$replace(dist, /, //) !exists($$dist):system($$MKDIR $$dist) !exists($$dist_file):system($$COPY $$f $$dist) } }
還是寫一點解釋吧,可能對大家有幫助,也防止自己時間長了會忘記。
- windows下,必須先將路徑分割符由“/”替換成 “/”
- 目標目錄不存在,創建目錄。
- 目標文件不存在,拷貝文件。