本文是一篇翻譯,英文原文地址:
https://doc.qt.io/qt-5/qmake-language.html
大多數(shù)的 qmake 工程文件是用來簡單的描述被用在項目中的資源文件和頭文件信息的,它們被定義成
name = value
或者
name += value
的形式。qmake 也提供其它的一些操作符、函數(shù)和作用域,用于在處理變量聲明時提供必要的信息。這些高級功能使得在多個平臺從一個單一的項目文件生成 makefile 文件變得輕而易舉。
操作符
在大多數(shù)工程文件中,分配操作符(=)和添加操作符(+=)可被用來引入(include)有關(guān)于項目的幾乎全部信息。典型的使用方式是分配給一個變量的值列表,并且我們可以依據(jù)各種測試的結(jié)果來添加更多的值。由于 qmake 有時候會使用默認值來初始化某些變量,因此此時使用刪除(- =)操作符來過濾掉不需要的值就是相當必要的了。以下內(nèi)容將會講解用操作符來修改變量的內(nèi)容的方法。
- 我們使用 = 操作符將值指定給一個變量:
TARGET = myapp
在上一行中,設(shè)定 TARGET 變量的值為 myapp,這樣我們就可以使用一個 “myapp” 值來覆蓋任何以前設(shè)置給 TARGET 的值了。
- += 操作符將在一個變量的值列表添加一個新值:
DEFINES += USE_MY_STUFF
在上面一行語句中我們附加 USE_MY_STUFF 到預(yù)定義列表,這樣我們就可以在 Makefile 中使用 USE_MY_STUFF 這個預(yù)定義了。
- -= 操作符用于在一個變量的值列表中刪除一個值:
DEFINES -= USE_MY_STUFF
在上面一行語句中我們從預(yù)定義列表中移除 USE_MY_STUFF 的預(yù)定義,這樣在 Makefile 中的有關(guān) USE_MY_STUFF 的預(yù)定義將會失效。
- *= 操作符用于在一個變量的值列表中添加一個值,但只有當它不是已存在的時候才有效。這可以防止值被多次的包含在一個變量中。例如:
DEFINES *= USE_MY_STUFF
上面的語句中,USE_MY_STUFF 將只有在預(yù)定義列表中不存在該定義時才會被添加,友情提示,unique() 函數(shù)也可以用來確保一個變量的每個值只包含一個實例。
- ~= 操作符用于用指定的值替換任何一個相匹配的正則表達式的值:
DEFINES ~= s/QT_[DT].+/QT
上面一行語句中,在預(yù)定義列表中的任何以 QT_D 或者 QT_T 開頭的預(yù)定義都將被替換為 QT。
- $$ 操作符被用于提取變量的內(nèi)容,并且也能被用作在變量之間傳值,或者傳遞這些值給函數(shù)
EVERYTHING = $$SOURCES $$HEADERS
message("The project contains the following files:")
message($$EVERYTHING)
變量可以用來存儲環(huán)境變量的內(nèi)容。這些可以在運行 qmake 時使用,或者在生成項目時生成的 Makefile 中使用。
要在運行 qmake 時獲取環(huán)境值的內(nèi)容,請使用 $$(...) 運算符:
DESTDIR = $$(PWD)
message(The project will be installed in $$DESTDIR)
在上面的分配中,當處理項目文件時讀取 PWD 環(huán)境變量的值。
要在生成的 Makefile 處理時獲取環(huán)境值的內(nèi)容,請使用 $(...) 運算符:
DESTDIR = $$(PWD)
message(The project will be installed in $$DESTDIR)
DESTDIR = $(PWD)
message(The project will be installed in the value of PWD)
message(when the Makefile is processed.)
在上面的分配中,處理項目文件時會立即讀取 PWD 的值,但在生成的 Makefile 中將 $(PWD) 分配給 DESTDIR。這使得構(gòu)建過程更加靈活,只要在處理 Makefile 時正確設(shè)置環(huán)境變量即可。
- 訪問 qmake 屬性
特殊的 $$[...] 操作符可用于訪問 qmake 屬性:
message(Qt version: $$[QT_VERSION])
message(Qt is installed in $$[QT_INSTALL_PREFIX])
message(Qt resources can be found in the following locations:)
message(Documentation: $$[QT_INSTALL_DOCS])
message(Header files: $$[QT_INSTALL_HEADERS])
message(Libraries: $$[QT_INSTALL_LIBS])
message(Binary files (executables): $$[QT_INSTALL_BINS])
message(Plugins: $$[QT_INSTALL_PLUGINS])
message(Data files: $$[QT_INSTALL_DATA])
message(Translation files: $$[QT_INSTALL_TRANSLATIONS])
message(Settings: $$[QT_INSTALL_CONFIGURATION])
message(Examples: $$[QT_INSTALL_EXAMPLES])
更多內(nèi)容,大家可以查閱 Configuring qmake 文檔
這個操作符可以訪問的屬性通常用于使第三方插件和組件集成到 Qt 中。 例如,如果在其項目文件中進行了以下聲明,則可以將 Qt Designer 插件與 Qt Designer 的內(nèi)置插件一起安裝:
target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target
條件域
條件域類似于編程語言中的if語句。如果一個特定的條件是真的,在條件域內(nèi)的聲明將會被處理。
條件域的語法
條件域包含一個條件后跟一個在同一行的左花括號,然后是一系列的命令和定義,最后是在新的一行的一個右花括號。就像下面這樣:
<condition> {
<command or definition>
...
}
左花括號必須要和條件寫在同一行。條件域可以包擴不止一個條件;可以看一些例子:
條件域和條件的例子
一個條件域被寫成一個條件后跟一系列聲明包含在一對大括號中,例如:
win32 {
SOURCES += paintwidget_win.cpp
}
如果 qmake 用于 Windows 平臺,上面的代碼將添加 paintwidget_win.cpp 文件到 Makefile 的資源列表。如果 qmake 用于其他的平臺,定義將被忽略。
當然我們也可以逆向思維,達到同樣的目的,例如我們使用下面的語句:
!win32 {
SOURCES -= paintwidget_win.cpp
}
也可以達到一樣的目的。
條件域可嵌套組合多個條件。例如,如果您想要為一個特定的平臺中,在滿足了調(diào)試的被啟用后,包含(include)一個特定的文件,然后你就可以寫如下代碼:
macx {
debug {
HEADERS += debugging.h
}
}
來滿足你的需求。
為了簡化嵌套條件域,我們可以使用 : 操作符,對于上一個例子中的功能,我們可以用如下代碼來簡化:
macx:debug {
HEADERS += debugging.h
}
我們也可以使用 : 操作符來執(zhí)行單一線條件的操作,例如:
win32:DEFINES += USE_MY_STUFF
上面一行的作用是,僅在 windows 平臺上添加 USE_MY_STUFF 定義到預(yù)定義列表。通常,: 操作符很像是邏輯與(&&)操作符,它會拼接一些條件,并且要求它們都為真。
我們也有 | 操作符,用來實現(xiàn)像邏輯或操作符(|)一樣的功能,它用來連接一些條件,并且僅要求其中至少一個為真。例如:
win32|macx {
HEADERS += debugging.h
}
我們也可以編寫復雜的測試語句,對條件進行逐一的測試,這主要依靠 “else” 來完成,例如我們可以像下面這樣寫我們的代碼:
win32:xml {
message(Building for Windows)
SOURCES += xmlhandler_win.cpp
} else:xml {
SOURCES += xmlhandler.cpp
} else {
message("Unknown configuration")
}
配置和條件域
在 CONFIG 變量中存儲的值是由 qmake 特別處理的。每一個可能的值都可以用作條件域的條件。例如,CONFIG 保存的列表的值可以使用 opengl 來擴展:
CONFIG += opengl
如果我們像上面那樣做的話,任何測試 opengl 的條件域都將是有效的,并且會被處理,我們可以使用這個功能給最后的可執(zhí)行文件一個適當?shù)拿Q:
opengl {
TARGET = application-gl
} else {
TARGET = application
}
這 個特性使得它很容易為一個項目改變配置,而不失去所有的自定義設(shè)置,而我們所要做的,可能只是一個特定的配置。在上面的代碼中,在第一個條件域中聲明的代 碼將會被處理,因此最終的可執(zhí)行文件將會被命名為 “application-gl”。然而,如果 opengl 沒有被指定,聲明在第二個條件域內(nèi)的代碼會被 處理,最終的可執(zhí)行文件會被稱為 “application”。
正因為我們可以把自定義的值附加給 CONFIG,我們就可以很方便的定制項目文件和調(diào)整 Makefile 文件。
平臺條件域值
除了 win32,macx 和 unix 這樣的常用于條件域條件的值,還有其他各種內(nèi)置平臺和編譯器具體值也可以在條件域中用于測試。這些基于平臺規(guī)范在 Qt 的 mkspecs 目錄中被提供。例如,下面的代碼用于顯示當前使用的規(guī)范并且測試 linux-g++ 規(guī)范。
message($$QMAKESPEC)
linux-g++ {
message(Linux)
}
我們可以測試任何其它平臺的編譯器組合,只要它的規(guī)范在 mkspecs 目錄中存在。
變量處理功能
qmake 提供了一個可供選擇的內(nèi)置函數(shù),允許變量的內(nèi)容被處理。這些函數(shù)處理提供給它們的參數(shù),返回一個值或者值的列表作為結(jié)果。為了指定一個結(jié)果給一個變量,有必要使用 $$ 操作符應(yīng)用于這種用于以同樣的方式分配一個變量的內(nèi)容到另一個類型的函數(shù),例如:
HEADERS = model.h
HEADERS += $$OTHER_HEADERS
HEADERS = $$unique(HEADERS)
這種類型的函數(shù)應(yīng)該用在右側(cè)賦值(例如,作為操作數(shù))。 可以定義自己的函數(shù)來處理變量的內(nèi)容。這些函數(shù)可以像下面這樣定義:
defineReplace(functionName){
#function code
}
下面的示例函數(shù)接受一個變量名稱作為其唯一的參數(shù),使用 eval() 內(nèi)置函數(shù)從變量中提取值的列表,并且編制一個文件列表。
defineReplace(headersAndSources) {
variable = $$1
names = $$eval($$variable)
headers =
sources =
for(name, names) {
header = $${name}.h
exists($$header) {
headers += $$header
}
source = $${name}.cpp
exists($$source) {
sources += $$source
}
}
return($$headers $$sources)
}
條件函數(shù)
qmake 提供的內(nèi)置函數(shù),在寫條件域的時候可以作為條件。這些函數(shù)不返回值,而是返回 “成功” 或者 “失敗” 的提示:
count(options, 2) {
message(Both release and debug specified.)
}
這種類型的函數(shù)應(yīng)該只用于條件表達式。
可以定義自己的函數(shù)來提供條件給條件域。下面的示例測試列表中的每個文件是否存在,返回true,如果他們都存在,或 false 如果不存在:
defineTest(allFiles) {
files = $$ARGS
for(file, files) {
!exists($$file) {
return(false)
}
}
return(true)
}
添加新配置 Features
qmake 允許您創(chuàng)建自己的 Features,它們可以被包含在項目文件,我們只需要增加他們的名字到 CONFIG 變量的列表。Features 是自定義函數(shù)和定義的集合,這些被寫在 .prf 文件中,它可以放在任意的標準目錄之中。這些目錄的位置被定義在許多地方,并且當 qmake 查找 .prf 文件的時候,它會使用 下面的順序檢查每一個目錄:
- 進入一個目錄中列出的QMAKEFEATURES環(huán)境變量;這包含在一個以冒號分隔的目錄列表中。
- 進入一個目錄列出的QMAKEFEATURES屬性變量;這包含一個以冒號分隔的目錄列表中。
- 進入一個存在于一個mkspecs目錄中特性目錄。mkspecs目錄可以位于列出在QMAKEPATH環(huán)境變量(以冒號分隔的目錄列表)中的任何目錄。($QMAKEPATH/mkspecs/<features>)
- 進入特性目錄駐留在QMAKESPEC環(huán)境變量提供的目錄。 ($QMAKESPEC/<features>)
- 進入特性目錄駐留在data_install/mkspecs目錄。(data_install/mkspecs/<features>)
- 進入特性目錄駐留在QMAKESPEC環(huán)境變量指定的兄弟姐妹的目錄。($QMAKESPEC/../<features>)
下面的特性目錄被用于搜尋屬性文件:
- features/unix,features/win32,或者features/macx,根據(jù)不同的平臺使用不同的目錄
- features/
例如,考慮下面在一個項目文件的賦值語句:
CONFIG += myfeatures
有了這個附加的配置變量,qmake 將會搜索 myfeatures.prf 文件上面列出的位置,完成這項搜索后,qmake 才會開始解析項目文件。在 UNIX 系統(tǒng)中,他可能像下面這樣工作:
$QMAKEFEATURES/myfeatures.prf(QMAKEFEATURES環(huán)境變量中的每一個目錄)
$$QMAKEFEATURES/myfeatures.prf(QMAKEFEATURES屬性變量中的每一個目錄)
myfeatures.prf(項目的根目錄)
$QMAKEPATH/mkspecs/features/unix/myfeatures.prf和$QMAKEPATH/mkspecs/features/myfeatures.prf(QMAKEPATH環(huán)境變量中列出的每一個目錄)
$QMAKESPEC/features/unix/myfeatures.prf和 $QMAKESPEC/features/myfeatures.prf
data_install/mkspecs/features/unix/myfeatures.prf 和data_install/mkspecs/features/myfeatures.prf
$QMAKESPEC/../features/unix/myfeatures.prf以及$QMAKESPEC/../features/myfeatures.prf
注意: .prf 文件必須以小寫字母來命名。
以上,另請原諒我蹩腳的英文水平。