淺談 qmake 之 shadow build


shadow build

shadow build 是什么東西?就是將源碼路徑和構建路徑分開(也就是生成的makefile文件和其他產物都不放到源碼路徑),以此來保證源碼路徑的清潔。

這不是qmake獨創的東西,cmake中早就使用這個東西了

 

cmake

qmake

備注

in-source

cmake .

qmake project.pro

在源碼路徑下執行

out-of-source
(shadow-build)

mkdir build

cd build
cmake ../project

mkdir build

cd build 
qmake ../project/project.pro

創建目錄,在其他路徑下執行(參數指向源碼路徑)

  • 注意:
  • 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 =

PWD/temp/
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下,必須先將路徑分割符由“/”替換成 “/”
  • 目標目錄不存在,創建目錄。
  • 目標文件不存在,拷貝文件。
    本人的一些操作,


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM