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下,必須先將路徑分割符由“/”替換成 “/”
- 目標目錄不存在,創建目錄。
- 目標文件不存在,拷貝文件。
