主頁 >  其他 > qt creator原始碼全方面分析(3-1)

qt creator原始碼全方面分析(3-1)

2020-09-12 12:58:09 其他

目錄
  • qtcreator.pro
    • 包含qtcreator.pri
      • include(filename)
    • Qt版本判斷
      • message(string)
      • $$運算子
      • error(string)
    • 包含doc.pri
    • 原始碼組織架構
      • TEMPLATE
      • SUBDIRS
    • 指定dist檔案串列
      • DISTFILES
      • files(pattern[, recursive=false])
      • Replace Functions概述
    • qbs配置
      • exists(filename)
      • Test Functions概述
    • 指定架構和平臺
      • contains(variablename, value)
      • Scopes
    • 指定基礎名
    • 指定linux平臺安裝內容
      • INSTALLS
      • Installing Files
    • 指定其他平臺安裝內容
      • INSTALL_ROOT
      • QTC_PREFIX
      • PWD
      • OUT_PWD
      • TARGET
      • QMAKE_EXTRA_TARGETS
      • Adding Custom Targets
    • 指定安裝存檔
      • Operators
    • 指定額外構建目標

qtcreator.pro

首先我們來學習根專案檔案qtcreator.pro

包含qtcreator.pri

qtcreator.pro第一行為

include(qtcreator.pri)

include(filename)

包含filename指定的檔案內容到當前專案中, 如果filename被包含,則此函式運行成功; 否則失敗, 被包含的檔案將立即被決議,

將此函式作為某個作用域的判斷條件,可以檢查是否成功包含檔案, 例如:

include( shared.pri )
OPTIONS = standard custom
!include( options.pri ) {
 message( "No custom build options specified" )
OPTIONS -= custom
   }

我們學習過C/C++,這和#include非常相似,

qtcreator.pri中定義了很多宏和通用操作,定義在pri中的函式,必須先include后pro才能使用,qmake處理pro和pri檔案是線性從上往下決議的,對比C/C++,我們可以認為pri檔案是頭檔案,pro檔案是源檔案

如果你使用 Qt Creator 打開專案,你會發現include陳述句會在專案樹的左側顯示一個節點,這種節點只需要include不同的 pri 檔案即可,是虛擬目錄節點,使專案結構層次看起來清晰很多,

image-20200222152425946

有關qtcreator.pri的內容,請見下節,

Qt版本判斷

接下來是

\#version check qt
!minQtVersion(5, 6, 2) {
    message("Cannot build $$IDE_DISPLAY_NAME with Qt version $${QT_VERSION}.")
    error("Use at least Qt 5.6.2.")
}

minQtVersion()顧名思義是最小Qt版本的意思,函式定義在qtcreator.pri中,當 Qt 的版本低于5.6.2時,minQtVersion()回傳false,!取反則為true,因此會執行塊中的操作,

message(string)

函式運行不會失敗,并將string作為常規訊息顯示給用戶, 與error()函式不同,此函式允許qmake繼續往下處理,

message( "This is a message" )

上一行導致"This is a message"被寫入控制臺,引號的使用是可選的,但建議使用,

注意:默認情況下,訊息被寫入qmake為給定專案生成的每個Makefile中, 如果要確保訊息在每個專案中僅出現一次,在作用域中聯合使用build_pass變數測驗,用于構建時過濾掉訊息,例如:

!build_pass:message( "This is a message" )

這里輸出的是"Cannot build $$IDE_DISPLAY_NAME with Qt version $${QT_VERSION}.",其中$${QT_VERSION}是占位符,會使用QT_VERSION變數的內容進行替換,

$$運算子

Variable

專案檔案中使用的許多變數是特殊變數,用于qmake生成Makefile時使用,例如DEFINES,SOURCES和HEADERS,另外,您可以創建自己的變數,在給某個名稱賦值時,qmake使用該名稱創建新變數,例如:

MY_VARIABLE = value

您可以對自己的變數執行任何操作,因為qmake會忽略它們,除非在處理作用域時需要評估它們,

您還可以通過在變數名稱前添加$$來將當前變數的值分配給另一個變數,例如:

MY_DEFINES = $$DEFINES

現在,MY_DEFINES變數包含了此時DEFINES變數的內容,這也等效于:

MY_DEFINES = $${DEFINES}

第二種表示法允許您將變數的內容附加到另一個值,而不用空格將兩者分開,例如,以下內容將確保為最終的可執行檔案指定一個名稱,其中包括正在使用的專案模板:

TARGET = myproject_$${TEMPLATE}

Variable Expansion

$$運算子用于提取變數的內容,并可用于在變數之間傳遞值或將其提供給函式:

EVERYTHING = $$SOURCES $$HEADERS
message("The project contains the following files:")
message($$EVERYTHING)

變數可用于存盤環境變數的內容,可以在運行qmake時對其進行評估,或者包含到專案構建時生成的Makefile中進行評估,

要在運行qmake時,獲取環境變數值的內容,請使用$$(...)運算子:

DESTDIR = $$(PWD)
message(The project will be installed in $$DESTDIR)

在上述賦值中,當處理專案檔案時,PWD環境變數的值被讀取,

要在生成的Makefile被處理時,獲取環境變數值的內容,請使用$(...)運算子:

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的值被立即讀取,但是$(PWD)被賦值給生成的Makefile中的DESTDIR,這使得構建程序更加靈活,只要在處理Makefile時正確設定了環境變數,

Accessing qmake Properties

特殊的$$[...]運算子可用于訪問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])

有關更多資訊,請參見Configuring qmake,

該運算子可訪問的屬性,通常用于集成第三方插件和組件到Qt中, 例如,如果在其專案檔案中進行了以下宣告,則可以將Qt Designer自定義插件安裝到Qt Designer內置插件路徑中:

target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target

最后是error()函式,顯示錯誤資訊,并退出,

error(string)

此函式從不回傳值, qmake將字串作為錯誤訊息顯示給用戶并退出, 此功能僅應用于不可恢復的錯誤,

包含doc.pri

接下來是

include(doc/doc.pri)

doc.pri中對qdocconf進行了配置,關于qdocconf干什么用的,請看我發布的文章,

原始碼組織架構

下面是重點,涉及原始碼的整體架構和組織模式,

TEMPLATE  = subdirs
CONFIG   += ordered

SUBDIRS = src share
unix:!macx:!isEmpty(copydata):SUBDIRS += bin
!isEmpty(BUILD_TESTS):SUBDIRS += tests

TEMPLATE

指定生成專案時要使用的模板的名稱, 允許的值為:

選項 描述
app 創建用于構建應用程式的Makefile(默認), 有關更多資訊,請參見Building an Application,
lib 創建用于構建庫的Makefile, 有關更多資訊,請參見Building a Library,
subdirs 創建用于在子檔案夾中構建目標的Makefile, 子檔案夾是使用SUBDIRS變數指定的,
aux 創建一個不生成任何內容的Makefile, 如果不需要呼叫任何編譯器來創建目標,請使用此選項; 例如,因為您的專案是以解釋性語言撰寫的,
注意:此模板型別僅適用于基于Makefile的生成器, 特別是,它不適用于vcxproj和Xcode生成器,
vcapp 僅Windows系統, 為Visual Studio創建一個應用程式專案, 有關更多資訊,請參見Creating Visual Studio Project Files,
vclib 僅Windows系統, 為Visual Studio創建一個庫,

例如:

TEMPLATE = lib
SOURCES = main.cpp
TARGET = mylib

模板可以被覆寫,通過使用-t命令列選項指定新的模板型別, 覆寫模板型別在處理.pro檔案之后, 對于使用.pro檔案的模板型別來確定專案生成方式的,必須在命令列上宣告TEMPLATE,而不要使用-t選項,

SUBDIRS

此變數與subdirs模板一起使用,指定所有子檔案夾的名稱,或者包含需要構建的專案部分的專案檔案,使用此變數指定的每個子檔案夾,都必須包含其自己的專案檔案,

建議每個子目錄中的專案檔案都具有與子目錄本身相同的基本名稱,因為這樣可以省略檔案名, 例如,如果子目錄名為myapp,則該目錄中的專案檔案應名為myapp.pro,

或者,您可以在任何目錄中指定.pro檔案的相對路徑, 強烈建議您僅在當前專案的父目錄或其子目錄中指定路徑,

例如:

SUBDIRS = kernel \
       tools \
       myapp

如果需要確保以特定順序構建子目錄,請在相關的SUBDIRS元素上使用.depends修飾符,

例如:

SUBDIRS += my_executable my_library tests doc
my_executable.depends = my_library
tests.depends = my_executable

上面的配置確保my_library是在my_executable之前構建的,并且my_executable是在tests之前構建的, 但是,doc可以與其他子目錄并行構建,從而加快了構建程序,

注意:可以列出多個依賴項,并且它們都將在依賴它們的目標之前構建,

注意:不建議使用CONFIG += ordered,因為它會減慢多核并行構建,與上面的示例不同,所有構建不會并行而是依次發生,即使它們沒有依賴性,

除了定義構建順序之外,還可以通過為SUBDIRS元素提供其他修飾符來修改SUBDIRS的默認行為, 支持的修飾符是:

修飾符 效果
.subdir 使用指定的子目錄而不是SUBDIRS值,
.file 顯式指定子專案pro檔案, 不能與.subdir修飾符一起使用,
.depends 本子專案依賴指定的子專案,
.makefile 子專案的makefile, 僅在使用makefile的平臺上可用,
.target 用于與此子專案相關的makefile目標的基本字串, 僅在使用makefile的平臺上可用,

例如,定義兩個子目錄,這兩個子目錄都位于與SUBDIRS值不同的目錄中,并且其中一個子目錄必須在另一個子目錄之前構建:

SUBDIRS += my_executable my_library
my_executable.subdir = app
my_executable.depends = my_library
my_library.subdir = lib

看了上面的解釋,我們可以理解得到,使用subdirs模式依次順序構建專案,首先構建src檔案夾,然后是share檔案夾,在src檔案夾中,還可以劃分為多個子目錄,再次使用subdirs模式,

image-20200222192914349

下面解釋一下最后兩行,

  1. 對于 Unix 平臺(unix),如果不是 Mac OS(!macx),并且copydata不為空(!isEmpty(copydata)),則需要再增加一個 bin 目錄,

  2. 如果BUILD_TESTS不為空(!isEmpty(BUILD_TESTS)),則再增加一個 tests 目錄,

copydataBUILD_TESTS都是在 qtcreator.pri 中定義的宏,

指定dist檔案串列

接下來是

DISTFILES += dist/copyright_template.txt \
    README.md \
    $$files(dist/changes-*) \
    qtcreator.qbs \
    qbs/pluginjson/pluginjson.qbs \
    $$files(scripts/*.py) \
    $$files(scripts/*.sh) \
    $$files(scripts/*.pl)

DISTFILES

指定要包含在dist目標中的檔案串列, 僅UnixMake規范支持此功能,

例如:

DISTFILES += ../program.txt

files(pattern[, recursive=false])

擴展指定的通配符pattern并回傳檔案名串列, 如果recursive為true,則此函式會下降到子目錄中進行遞回,

Replace Functions概述

qmake提供了用于在配置程序中處理變數內容的函式, 這些函式稱為替換函式, 通常,它們回傳可以分配給其他變數的值, 您可以通過在函式前面加上$$運算子來獲取這些值, 替換函式可以分為內置函式和函式庫,

那么我們就可以理解$$files(dist/changes-*),就是回傳當前目錄下的 dist 檔案夾中,所有以 changes- 開頭的檔案,

qbs配置

接下來是

exists(src/shared/qbs/qbs.pro) {
    # Make sure the qbs dll ends up alongside the Creator executable.
    QBS_DLLDESTDIR = $${IDE_BUILD_TREE}/bin
    cache(QBS_DLLDESTDIR)
    ...
}

exists(filename)

測驗具有給定filename檔案名的檔案是否存在, 如果檔案存在,則函式成功;否則失敗,如果為檔案名指定了正則運算式,則只要任何一個檔案與指定的正則運算式匹配,則此函式成功,

例如:

exists( $(QTDIR)/lib/libqt-mt* ) {
      message( "Configuring for multi-threaded Qt..." )
      CONFIG += thread
}

注意:無論使用什么平臺,都應將“ /”用作目錄分隔符,

Test Functions概述

測驗函式回傳一個布林值,您可以在作用域范圍的條件部分中進行測驗, 測驗函式可以分為內置函式和函式庫,

略,

指定架構和平臺

接下來是

contains(QT_ARCH, i386): ARCHITECTURE = x86
else: ARCHITECTURE = $$QT_ARCH

macx: PLATFORM = "mac"
else:win32: PLATFORM = "windows"
else:linux-*: PLATFORM = "linux-$${ARCHITECTURE}"
else: PLATFORM = "unknown"

contains(variablename, value)

如果變數variablename包含值value,則成功; 否則失敗, 可以為引數value指定正則運算式,

您可以使用作用域范圍來檢查此函式的回傳值,

例如:

contains( drivers, network ) {
 # drivers contains 'network'
 message( "Configuring for network build..." )
 HEADERS += network.h
 SOURCES += network.cpp
}

僅當drivers變數包含值network時,才處理范圍內的內容, 在這種情況下,會將適當的檔案添加到SOURCES和HEADERS變數中,

Scopes

作用域范圍類似于程序編程語言中的if陳述句,如果滿足某個條件,則將處理域內的宣告,

Scope Syntax

作用域三部分組成,第一行為條件陳述句和在同一行上的左大括號,一系列命令和定義,以及另起一行上的右大括號:

<condition> {
    <command or definition>
    ...
}

左大括號必須與條件在同一行上, 作用域可以串聯起來,以包含多個條件,如以下各節所述,

作用域和條件
作用域由一個條件后跟一對大括號中包含的一系列宣告組成, 例如:

win32 {
    SOURCES += paintwidget_win.cpp
}

以上代碼,在Windows平臺構建時,會將paintwidget_win.cpp檔案添加到生成的Makefile中的源檔案串列中, 在其他平臺構建時,定義將被忽略,

作用域中使用的條件也可以取反,以提供多種宣告方式,可在原始條件為false時進行處理,例如,要在除Windows以外的所有平臺構建時進行處理,請對作用域取反,如下所示:

!win32 {
    SOURCES -= paintwidget_win.cpp
}

作用域可以嵌套,以聯合多個條件, 例如,要為特定平臺包括特定檔案,且僅在啟用除錯的情況下包含,請撰寫以下內容:

macx {
    CONFIG(debug, debug|release) {
        HEADERS += debugging.h
    }
}

要少寫嵌套作用域,可以使用:運算子來進行嵌套,上例中的嵌套作用域可以通過以下方式重寫:

macx:CONFIG(debug, debug|release) {
    HEADERS += debugging.h
}

您也可以使用:運算子來執行單行條件賦值, 例如:

win32:DEFINES += USE_MY_STUFF

上一行僅在Windows平臺構建時,才將USE_MY_STUFF添加到DEFINES變數中, 通常,:運算子的行為類似于邏輯AND運算子,將多個條件結合在一起,并且要求所有條件都為真,

這里還有一個|運算子,其行為類似于邏輯OR運算子,將多個條件結合在一起,并且僅要求其中一個為真,

win32|macx {
    HEADERS += debugging.h
}

如果需要混合使用兩個運算子,則可以使用if函式指定運算子優先級,

if(win32|macos):CONFIG(debug, debug|release) {
    # Do something on Windows and macOS,
    # but only for the debug configuration.
}
win32|if(macos:CONFIG(debug, debug|release)) {
    # Do something on Windows (regardless of debug or release)
    # and on macOS (only for debug).
}

該條件接受通配符,可匹配一系列CONFIG值或mkspec名稱,

win32-* {
    # Matches every mkspec starting with "win32-"
    SOURCES += win32_specific.cpp
}

注意:以前,使用通配符檢查mkspec名稱是qmake檢查平臺的方法, 如今,我們建議使用mkspec定義的QMAKE_PLATFORM變數中的值,

您還可以使用else 作用域來提供多種宣告方式, 如果前面作用域的條件為false,則處理下面的else作用域,此外,你還可以通過聯合其他作用域,撰寫復雜的測驗(如上所述,由:運算子分隔), 例如:

win32:xml {
    message(Building for Windows)
    SOURCES += xmlhandler_win.cpp
} else:xml {
    SOURCES += xmlhandler.cpp
} else {
    message("Unknown configuration")
}

[Configuration and Scopes](Configuration and Scopes)

CONFIG變數中存盤的值被qmake特殊處理, 每個可能的值都可以用作作用域的條件, 例如,可以使用opengl值擴展CONFIG的值的串列:

CONFIG += opengl

作為此操作的結果,所有測驗opengl的作用域將被處理,我們可以使用此功能為最終可執行檔案指定適當的名稱:

opengl {
    TARGET = application-gl
} else {
    TARGET = application
}

通過此功能,可以輕松更改專案的配置,而不會丟失特定配置可能需要的所有自定義設定, 在上面的代碼中,第一個作用域中的宣告被處理,最終的可執行檔案為application-gl, 但是,如果未指定opengl,則將處理第二個作用域中的宣告,最終的可執行檔案為application,

由于可以在CONFIG行上放置自己的值,因此這為您提供了一種方便的方法,來自定義專案檔案并微調生成的Makefile,

Platform Scope Values

除了在許多作用域條件中使用的win32,macx和unix值之外,還可以使用各種其他內置平臺和特定編譯器的值, 這些都基于Qt的mkspecs檔案夾中提供的平臺規范, 例如,專案檔案中的以下幾行顯示了當前使用的規范,并測驗了linux-g++規范:

message($$QMAKESPEC)

linux-g++ {
    message(Linux)
}

您可以測驗任何其他平臺-編譯器組合,只要在mkspecs檔案夾中存在針對它的規范即可,

很明顯,這里進行了判斷,并最終指定了ARCHITECTURE和PLATFORM的值,

指定基礎名

接下來是

BASENAME = $$(INSTALL_BASENAME)
isEmpty(BASENAME): BASENAME = qt-creator-$${PLATFORM}$(INSTALL_EDITION)-$${QTCREATOR_VERSION}$(INSTALL_POSTFIX)

對于BASENAME,這是是一種常見的寫法,首先,定義BASENAME宏為$$(INSTALL_BASENAME);之后,如果BASENAME為空的話(使用測驗函式isEmpty()判斷),則定義新的BASENAME的值,

這種寫法允許我們在編譯時通過命令列傳入自定義值改變默認設定(也就是說,如果之前定義了INSTALL_BASENAME,那么就會使用我們定義的值),否則就會生成一個默認值,以后我們會發現,Qt Creator 的 pro 檔案中,很多地方都使用了類似的寫法,

指定linux平臺安裝內容

接下來是

linux {
    appstream.files = dist/org.qt-project.qtcreator.appdata.xml
    appstream.path = $$QTC_PREFIX/share/metainfo/

    desktop.files = dist/org.qt-project.qtcreator.desktop
    desktop.path = $$QTC_PREFIX/share/applications/
    
    INSTALLS += appstream desktop
}

INSTALLS

指定執行make install或類似安裝命令時將安裝的資源串列, 串列中的每個專案通常都定義有屬性,這些屬性提供有關安裝位置的資訊,

例如,以下target.path定義描述了構建目標的安裝位置,并且INSTALLS賦值將構建目標添加到要安裝的現有資源串列中:

target.path += $$[QT_INSTALL_PLUGINS]/imageformats
INSTALLS += target

Installing Files

在Unix上,通常也使用構建工具來安裝應用程式和庫, 例如,通過呼叫make install, 因此,qmake具有安裝集(install set)的概念,該物件包含如何安裝專案內容的指令集,例如,可以通過以下方式描述檔案檔案的集合:

documentation.path = /usr/local/program/doc
documentation.files = docs/*

path成員通知qmake應該將檔案安裝在/usr/local/program/doc中,并且files成員指定應復制到安裝目錄的檔案, 在這種情況下,docs目錄中的所有內容都將復制到/usr/local/program/doc中,

完整描述了安裝集后,您可以使用如下行將其追加到安裝串列中:

INSTALLS += documentation

qmake確保將指定的檔案復制到安裝目錄, 如果需要對該程序進行更多控制,則還可以為物件的extra成員提供定義, 例如,下行告訴qmake為此安裝集執行一系列命令:

unix:documentation.extra = create_docs; mv master.doc toc.doc

Unix作用域可確保僅在Unix平臺上執行這些特定命令, 可以使用其他作用域規則來定義用于其他平臺的適當命令,

物件首先執行extra成員中指定的命令,再執行物件的其他成員中的指令,

如果您將內置安裝集附加到INSTALLS變數,并且不指定files或extra成員,則qmake將決定需要為您復制哪些內容, 當前,支持targetdlltarget安裝集, 例如:

target.path = /usr/local/myprogram
INSTALLS += target

在以上幾行中,qmake知道需要復制什么,并將自動處理安裝程序,

想必大家也都明白了吧,如果是linux平臺,則把.files指定的檔案拷貝到.path指定的路徑中,

指定其他平臺安裝內容

接下來是

macx {
    APPBUNDLE = "$$OUT_PWD/bin/$${IDE_APP_TARGET}.app"
    BINDIST_SOURCE = "$$OUT_PWD/bin/$${IDE_APP_TARGET}.app"
    deployqt.commands = $$PWD/scripts/deployqtHelper_mac.sh \"$${APPBUNDLE}\" \"$$[QT_INSTALL_BINS]\" \"$$[QT_INSTALL_TRANSLATIONS]\" \"$$[QT_INSTALL_PLUGINS]\" \"$$[QT_INSTALL_IMPORTS]\" \"$$[QT_INSTALL_QML]\"
    codesign.commands = codesign --deep -s \"$(SIGNING_IDENTITY)\" $(SIGNING_FLAGS) \"$${APPBUNDLE}\"
    dmg.commands = python -u \"$$PWD/scripts/makedmg.py\" \"$${BASENAME}.dmg\" \"Qt Creator\" \"$$IDE_SOURCE_TREE\" \"$$OUT_PWD/bin\"

    # dmg.depends = deployqt
    QMAKE_EXTRA_TARGETS += codesign dmg
} else {
    BINDIST_SOURCE = "$(INSTALL_ROOT)$$QTC_PREFIX"
    BINDIST_EXCLUDE_ARG = "--exclude-toplevel"
    deployqt.commands = python -u $$PWD/scripts/deployqt.py -i \"$(INSTALL_ROOT)$$QTC_PREFIX/bin/$${IDE_APP_TARGET}\" \"$(QMAKE)\"
    deployqt.depends = install
    win32 {
        deployartifacts.depends = install
        deployartifacts.commands = git clone --depth 1 -b $$BINARY_ARTIFACTS_BRANCH \
                "http://code.qt.io/qt-creator/binary-artifacts.git" \
            && xcopy /s /q /y /i "binary-artifacts\\win32" \"$(INSTALL_ROOT)$$QTC_PREFIX\" \
            && rmdir /s /q binary-artifacts
        QMAKE_EXTRA_TARGETS += deployartifacts
    }
}

INSTALL_ROOT

環境變數

make install時更改安裝目錄的位置,例如$BUILDDIR/install/qtcreator(在Mac上不使用),具體安裝到$(INSTALL_ROOT)$$QTC_PREFIX中,

QTC_PREFIX

qmake變數

用于make install安裝目錄的目錄前綴,以及make bindist打包的目錄物件,且必須以/開頭,例如/qt-creator-x.y.z,安裝到$(INSTALL_ROOT)$$QTC_PREFIX中,

PWD

指定包含正在被決議的當前檔案的目錄的完整路徑,在撰寫支持影子構建的專案檔案時,這對于參考源檔案樹中的檔案很有用,

注意:請勿嘗試覆寫此變數的值,

OUT_PWD

指定檔案夾完整路徑,qmake把生成的Makefile放到此檔案夾中,

注意:請勿嘗試覆寫此變數的值,

TARGET

指定目標檔案的名稱, 默認情況下包含專案檔案的基本名稱,

例如:

TEMPLATE = app
TARGET = myapp
SOURCES = main.cpp

上面的專案檔案將在unix上生成一個名為myapp的可執行檔案,在Windows上生成一個名為myapp.exe的可執行檔案,

QMAKE_EXTRA_TARGETS

指定額外的qmake目標的串列,

另請參閱Adding Custom Targets,

Adding Custom Targets

qmake試圖做一個跨平臺構建工具所期望的一切,當您確實需要運行特殊的平臺相關命令時,這通常不理想, 但是,這可以使用平臺特定的指令指向不同的qmake后端來實作,

自定義Makefile輸出可通過執行物件風格(object-style)的API來實作,如在qmake中的其他位置所發現的那樣,在指定成員時會自動定義物件, 例如:

mytarget.target = .buildfile
mytarget.commands = touch $$mytarget.target
mytarget.depends = mytarget2

mytarget2.commands = @echo Building $$mytarget.target

上面的定義定義了一個名為mytarget的qmake目標,目標包含一個名為.buildfile的Makefile目標,并通過touch命令生成, 最后,.depends成員指定mytarget依賴于mytarget2,后者是隨后定義的另一個目標, mytarget2是一個虛擬目標, 它僅定義為向控制臺回顯一些文本,

最后一步是使用QMAKE_EXTRA_TARGETS變數來指示qmake該物件是要構建的目標:

QMAKE_EXTRA_TARGETS += mytarget mytarget2

這是實際構建自定義目標所需要做的一切, 當然,您可能希望將這些目標的其中一個與qmake構建目標(qmake build target)聯系起來, 為此,您只需要在PRE_TARGETDEPS串列中包括Makefile目標即可,

自定義目標規范支持以下成員:

成員 描述
commands 用于生成自定義構建目標的命令,
CONFIG 自定義構建目標的特定配置選項, 可以設定為recursive,以指示應在Makefile中創建規則,以呼叫子目標特定的Makefile中的相關目標, 該成員默認為每個子目標創建一個條目,
depends 自定義構建目標所依賴的現有構建目標,
recurse 指定子目標,在Makefile中創建規則是被使用,以呼叫子目標特定的Makefile, 此成員僅當CONFIG設定為recursive時才使用, 典型值為"Debug"和"Release",
recurse_target 指定應該通過Makefile的規則對應的子目標Makefile構建的目標, 該成員添加了類似$(MAKE) -f Makefile.[subtarget] [recurse_target]的東西, 此成員僅當CONFIG設定為recursive時才使用,
target 自定義構建目標的名稱

上面的陳述句中用到了Scopes條件判斷,$$運算子,自定義目標等內容,我們在前面都已經講過了,現在我們也清楚了,首先進行了平臺判斷,然后定義了自定義構建目標,用于編譯輸出,大家感興趣,可以使用message()函式進行輸出,具體內容就不深究了,

指定安裝存檔

接下來是

INSTALLER_ARCHIVE_FROM_ENV = $$(INSTALLER_ARCHIVE)
isEmpty(INSTALLER_ARCHIVE_FROM_ENV) {
    INSTALLER_ARCHIVE = $$OUT_PWD/$${BASENAME}-installer-archive.7z
} else {
    INSTALLER_ARCHIVE = $$OUT_PWD/$$(INSTALLER_ARCHIVE)
}

INSTALLER_ARCHIVE_DEBUG = $$INSTALLER_ARCHIVE
INSTALLER_ARCHIVE_DEBUG ~= s/(.*)[.]7z/\1-debug.7z

Operators

在許多專案檔案中,賦值(=)和追加(+ =)運算子可用于包括有關專案的所有資訊, 典型的使用模式是為變數分配值串列,并根據各種測驗的結果附加更多值, 由于qmake使用默認值定義某些變數,因此有時有必要使用remove(-=)運算子過濾掉不需要的值, 以下各節描述如何使用運算子來操縱變數的內容,

Assigning Values

=運算子為變數分配一個值:

TARGET = myapp

上一行將TARGET變數設定為myapp, 這將使用myapp覆寫先前為TARGET設定的任何值,

Appending Values

+=運算子將新值附加到變數的值串列中:

DEFINES += USE_MY_STUFF

上一行將USE_MY_STUFF追加到預處理定義串列中,最后寫入生成的Makefile,

Removing Values

-=運算子從變數的值串列中洗掉一個值:

DEFINES -= USE_MY_STUFF

上一行從預處理定義串列中洗掉了USE_MY_STUFF,

Adding Unique Values

*=運算子將一個值添加到變數的值串列中,但前提是尚不存在, 這樣可以防止將值多次包含在變數中, 例如:

DEFINES *= USE_MY_STUFF

在上面的行中,如果尚未定義USE_MY_STUFF,則只會將其添加到預處理定義串列中, 請注意,unique()函式還可用于確保變數僅包含每個值的一個實體,

Replacing Values ~=

?=運算子將所有與正則運算式匹配的值替換為指定的值:

DEFINES ~= s/QT_[DT].+/QT

在上一行中,串列中以QT_D或QT_T開頭的任何值都將替換為QT,

INSTALLER_ARCHIVE的定義方式,我們在"指定基礎名"小節中就介紹過這種用法,不再贅述,對于INSTALLER_ARCHIVE_DEBUG的~=運算,就是在檔案名后面加了-debug,

指定額外構建目標

最后是


bindist.commands = python -u $$PWD/scripts/createDistPackage.py $$OUT_PWD/$${BASENAME}.7z \"$$BINDIST_SOURCE\"
bindist_installer.commands = python -u $$PWD/scripts/createDistPackage.py $$BINDIST_EXCLUDE_ARG $${INSTALLER_ARCHIVE} \"$$BINDIST_SOURCE\"
bindist_debug.commands = python -u $$PWD/scripts/createDistPackage.py --debug $$BINDIST_EXCLUDE_ARG $${INSTALLER_ARCHIVE_DEBUG} \"$$BINDIST_SOURCE\"

win32 {
    deployqt.commands ~= s,/,\\\\,g
    bindist.commands ~= s,/,\\\\,g
    bindist_installer.commands ~= s,/,\\\\,g
}

QMAKE_EXTRA_TARGETS += deployqt bindist bindist_installer bindist_debug

首先創建了bindist,bindist_installer和bindist_debug三個自定義構建目標,然后在win32平臺下進行了替換,最終添加到QMAKE_EXTRA_TARGETS進行編譯構建,

簡單解釋下上面的正則運算式,其實就是替換路徑中的分隔符,全域替換unix中的/為windows下的\\,


原創造福大家,共享改變世界

獻出一片愛心,溫暖作者心靈


轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/14289.html

標籤:其他

上一篇:使用QT顯示OpenCV讀取的圖片

下一篇:qt creator原始碼全方面分析(3)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more