AUTOMOC

是否應使用自動 moc 處理目標(用於 Qt 專案)。

AUTOMOC 是一個布林值,指定 CMake 是否會自動處理 Qt moc 預處理器,也就是說,無需使用像 QT4_WRAP_CPP()qt5_wrap_cpp() 等命令。目前支援 Qt 版本 4 到 6。

此屬性由 CMAKE_AUTOMOC 變數的值初始化,如果在建立目標時已設定該變數。

當此屬性設定為 ON 時,CMake 將在建置時掃描標頭和原始碼檔案,並相應地調用 moc

標頭檔案處理

在組態時,應由 AUTOMOC 掃描的標頭檔案清單是從目標的原始碼計算得出的。

  • 目標原始碼中的所有標頭檔案都會新增到掃描清單中。

  • 對於目標原始碼中所有 C++ 原始碼檔案 <source_base>.<source_extension>,CMake 會搜尋

    • 具有相同基本名稱的常規標頭檔案 (<source_base>.<header_extention>) 和

    • 具有相同基本名稱和 _p 字尾的私有標頭檔案 (<source_base>_p.<header_extention>)

    並將其新增至掃描清單中。

在建置時,CMake 會掃描清單中每個未知或修改過的標頭檔案,並搜尋

  • 來自 AUTOMOC_MACRO_NAMES 的 Qt 巨集,

  • Q_PLUGIN_METADATA 巨集的 FILE 引數中的其他檔案相依性,以及

  • AUTOMOC_DEPEND_FILTERS 中定義的篩選器偵測到的其他檔案相依性。

如果找到 Qt 巨集,則標頭將由 moc 編譯為輸出檔案 moc_<base_name>.cpp。完整的輸出檔案路徑會在 輸出檔案位置 一節中說明。

如果其他檔案相依性中的檔案發生變更,則會再次 moc 編譯標頭。

標頭 moc 輸出檔案 moc_<base_name>.cpp 可以包含在原始碼檔案中。在 在原始碼中包含標頭 moc 檔案 一節中有更多關於該主題的資訊。

原始碼檔案處理

在建置時,CMake 會從目標原始碼中掃描每個未知或修改過的 C++ 原始碼檔案,以尋找

如果找到 Qt 巨集,則 C++ 原始碼檔案 <base>.<source_extension> 也應包含 include 陳述式

#include <<base>.moc> // or
#include "<base>.moc"

然後,原始碼檔案將由 moc 編譯為輸出檔案 <base>.moc。完整輸出檔案路徑的說明位於 輸出檔案位置 一節中。

如果其他檔案相依性中的檔案發生變更,則會再次 moc 編譯原始碼。

在原始碼中包含標頭 moc 檔案

原始碼檔案可以使用 <header_base>.<header_extension> 形式的 include 陳述式,包含標頭的 moc 輸出檔案。

#include <moc_<header_base>.cpp> // or
#include "moc_<header_base>.cpp"

如果標頭的 moc 輸出檔案包含在原始碼中,則它將在與未包含時不同的位置產生。這會在 輸出檔案位置 一節中說明。

輸出檔案位置

包含的 moc 輸出檔案

原始碼檔案包含的 moc 輸出檔案將會在

  • 單一組態產生器中 <AUTOGEN_BUILD_DIR>/include

  • 多重組態產生器的 <AUTOGEN_BUILD_DIR>/include_<CONFIG> 中產生。

其中 <AUTOGEN_BUILD_DIR> 是目標屬性 AUTOGEN_BUILD_DIR 的值。

include 目錄會自動新增至目標的 INCLUDE_DIRECTORIES

未包含的 moc 輸出檔案

未包含在原始碼檔案中的 moc 輸出檔案將會在

  • 單一組態產生器的 <AUTOGEN_BUILD_DIR>/<SOURCE_DIR_CHECKSUM>

  • 多重組態產生器的 <AUTOGEN_BUILD_DIR>/include_<CONFIG>/<SOURCE_DIR_CHECKSUM> 中產生。

其中 <SOURCE_DIR_CHECKSUM> 是從 moc 輸入檔案的相對父目錄路徑計算得出的檢查總和。此方案允許在不同目錄中擁有相同名稱的 moc 輸入檔案。

所有未包含的 moc 輸出檔案都將由 CMake 產生的檔案自動包含

  • <AUTOGEN_BUILD_DIR>/mocs_compilation.cpp,或

  • <AUTOGEN_BUILD_DIR>/mocs_compilation_$<CONFIG>.cpp,

它會新增至目標的原始碼。

Qt 版本偵測

已啟用 AUTOMOC 的目標需要知道它們正在使用的 Qt 主要和次要版本。主要版本通常由目標連結到的 Qt[456]Core 程式庫的 INTERFACE_QT_MAJOR_VERSION 屬性提供。若要尋找次要版本,CMake 會從以下項目建置可用的 Qt 版本清單

  • Qt6Core_VERSION_MAJORQt6Core_VERSION_MINOR 變數 (通常由 find_package(Qt6...) 設定)

  • Qt6Core_VERSION_MAJORQt6Core_VERSION_MINOR 目錄屬性

  • Qt5Core_VERSION_MAJORQt5Core_VERSION_MINOR 變數 (通常由 find_package(Qt5...) 設定)

  • Qt5Core_VERSION_MAJORQt5Core_VERSION_MINOR 目錄屬性

  • QT_VERSION_MAJORQT_VERSION_MINOR 變數 (通常由 find_package(Qt4...) 設定)

  • QT_VERSION_MAJORQT_VERSION_MINOR 目錄屬性

add_executable()add_library() 呼叫的內容中。

假設 INTERFACE_QT_MAJOR_VERSION 是有效的數字,則會採用清單中具有相符主要版本的第一個項目。如果找不到相符的主要版本,則會產生錯誤。如果 INTERFACE_QT_MAJOR_VERSION 不是有效數字,則會採用清單中的第一個項目。

呼叫 find_package(Qt[456]...) 會設定 QT/Qt[56]Core_VERSION_MAJOR/MINOR 變數。如果呼叫的位置與 add_executable()add_library() 呼叫的位置不同,例如在函式中,則版本變數可能無法用於啟用 AUTOMOC 的目標。在這種情況下,可以將版本變數從呼叫 find_package(Qt[456]...) 的上下文,以目錄屬性的形式轉發到呼叫 add_executable()add_library() 的上下文。以下 Qt5 範例展示了這個流程。

function (add_qt5_client)
  find_package(Qt5 REQUIRED QUIET COMPONENTS Core Widgets)
  ...
  set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
    PROPERTY Qt5Core_VERSION_MAJOR "${Qt5Core_VERSION_MAJOR}")
  set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
    PROPERTY Qt5Core_VERSION_MINOR "${Qt5Core_VERSION_MAJOR}")
  ...
endfunction ()
...
add_qt5_client()
add_executable(myTarget main.cpp)
target_link_libraries(myTarget Qt5::QtWidgets)
set_property(TARGET myTarget PROPERTY AUTOMOC ON)

修改器

AUTOMOC_EXECUTABLEmoc 可執行檔會自動偵測,但可以使用這個目標屬性強制指定到特定的二進制檔。

AUTOMOC_MOC_OPTIONS:可以在這個目標屬性中設定 moc 的其他命令列選項。

AUTOMOC_MACRO_NAMES:可以擴充此 Qt 巨集名稱列表,以便在標頭和原始碼中搜尋其他巨集。

AUTOMOC_DEPEND_FILTERS:可以透過在這個目標屬性中定義檔名篩選器,從標頭或原始碼中提取 moc 的依賴檔名。

AUTOMOC_COMPILER_PREDEFINESmoc 的編譯器預定義會寫入到 moc_predefs.h 檔案。可以在這個目標屬性中啟用或停用此檔案的產生。

SKIP_AUTOMOC:可以透過設定這個原始檔屬性,將原始碼和標頭排除在 AUTOMOC 處理之外。

SKIP_AUTOGEN:可以透過設定這個原始檔屬性,將原始檔排除在 AUTOMOCAUTOUICAUTORCC 處理之外。

AUTOGEN_SOURCE_GROUP:可以使用這個全域屬性,將 AUTOMOCAUTORCC 產生的檔案,在 IDE 中(例如在 MSVS 中)分組在一起。

AUTOGEN_TARGETS_FOLDER:可以使用這個全域屬性,將 AUTOMOCAUTOUICAUTORCC 目標,在 IDE 中(例如在 MSVS 中)分組在一起。

CMAKE_GLOBAL_AUTOGEN_TARGET:當此變數為 ON 時,將會產生一個全域 autogen 目標,該目標依賴專案中所有 AUTOMOCAUTOUIC 產生的 The <ORIGIN>_autogen target 目標。

AUTOGEN_PARALLEL:此目標屬性控制在建置期間並行啟動的 mocuic 程序數量。

AUTOGEN_COMMAND_LINE_LENGTH_MAX:此目標屬性控制在 Windows 上使用回應檔處理 mocuic 程序的限制。

請參閱 cmake-qt(7) 手冊,以取得更多關於將 CMake 與 Qt 搭配使用的資訊。