這個章節提到的 軟體模型 已停止使用,而且外掛程式最終會被棄用並移除。我們建議新的專案使用較新的 替代外掛程式 來建置 C++ 應用程式和函式庫。
本章節中描述的原生外掛程式與 組態快取 不相容。

原生軟體外掛程式新增了支援,可從 C++、C 和其他語言撰寫的程式碼中建置原生軟體元件,例如可執行檔或共用函式庫。雖然有許多優秀的建置工具可用於這個軟體開發空間,但 Gradle 提供開發人員其商標力量和彈性,以及在 JVM 開發空間中更傳統的相依項管理實務。

原生軟體外掛程式使用 Gradle 軟體模型。

功能

原生軟體外掛程式提供

  • 在 Windows、Linux、macOS 和其他平台上建置原生函式庫和應用程式的支援。

  • 支援多種原始語言。

  • 支援為不同的架構、作業系統或任何目的建立不同變體的相同軟體。

  • 遞增式平行編譯、預編譯標頭。

  • 原生軟體元件之間的相依性管理。

  • 單元測試執行。

  • 產生 Visual Studio 解决方案和專案檔案。

  • 與各種工具鏈深度整合,包括已安裝工具鏈的偵測。

支援的語言

目前支援下列原始碼語言

  • C

  • C++

  • Objective-C

  • Objective-C++

  • 組合語言

  • Windows 資源

工具鏈支援

Gradle 提供使用不同工具鏈執行相同建置的功能。當您建置原生二進位檔案時,Gradle 會嘗試在您的機器上找到可以建置二進位檔案的已安裝工具鏈。您可以微調確切的運作方式,請參閱 工具鏈支援 以取得詳細資料。

支援下列工具鏈

作業系統 工具鏈 備註

Linux

GCC

Linux

Clang

macOS

XCode

使用與 XCode 捆綁的 Clang 工具鏈。

Windows

Visual C++

Windows XP 及更新版本,Visual C++ 2010/2012/2013/2015/2017/2019。

Windows

GCC 搭配 Cygwin 32 和 Cygwin 64

Windows XP 及更新版本。

Windows

GCC 搭配 MinGWMinGW64

Windows XP 及更新版本。

下列工具鏈未經官方支援。它們通常運作良好,但未持續測試

作業系統 工具鏈 備註

macOS

GCC 來自 Macports

macOS

Clang 來自 Macports

類 UNIX

GCC

類 UNIX

Clang

工具鏈安裝

請注意,如果您使用 GCC,則目前需要安裝 C++ 支援,即使您不是從 C++ 原始碼建置。此限制將在未來的 Gradle 版本中移除。

若要建置原生軟體,您需要安裝相容的工具鏈

Windows

若要在 Windows 上建置,請安裝相容版本的 Visual Studio。原生外掛程式會偵測 Visual Studio 安裝並選取最新版本。無需使用環境變數或批次指令碼。這在 Cygwin shell 或 Windows 命令列中都能正常運作。

或者,您可以使用 GCC 或 MinGW 安裝 Cygwin。目前不支援 Clang。

macOS

要在 macOS 上進行建置,您應該安裝 XCode。原生外掛程式會使用系統路徑來偵測 XCode 安裝。

原生外掛程式也可以搭配 Macports 內建的 GCC 和 Clang 使用。若要使用其中一個 Macports 工具鏈,您需要使用 port select 指令將該工具鏈設為預設值,並將 Macports 加入系統路徑。

Linux

要在 Linux 上進行建置,請安裝相容版本的 GCC 或 Clang。原生外掛程式會使用系統路徑來偵測 GCC 或 Clang。

原生軟體模型

原生軟體模型建置於 Gradle 基本軟體模型上。

若要使用 Gradle 建置原生軟體,您的專案應該定義一個或多個原生元件。每個元件代表 Gradle 應該建置的可執行檔或函式庫。一個專案可以定義任意數量的元件。Gradle 預設不會定義任何元件。

對於每個元件,Gradle 會針對元件可以建置的每種語言定義一個來源組。來源組基本上只是一個包含來源檔案的來源目錄集。例如,當您套用 c 外掛程式並定義一個稱為 helloworld 的函式庫時,Gradle 會預設定義一個包含 src/helloworld/c 目錄中的 C 來源檔案的來源組。它會使用這些來源檔案來建置 helloworld 函式庫。這會在下方更詳細地說明。

對於每個元件,Gradle 會定義一個或多個二進位檔作為輸出。若要建置二進位檔,Gradle 會取得為元件定義的來源檔案,針對來源語言適當地編譯它們,並將結果連結到二進位檔檔案中。對於可執行元件,Gradle 可以產生可執行二進位檔檔案。對於函式庫元件,Gradle 可以產生靜態和共用函式庫二進位檔檔案。例如,當您定義一個稱為 helloworld 的函式庫並在 Linux 上建置時,Gradle 會預設產生 libhelloworld.solibhelloworld.a 二進位檔。

在許多情況下,一個元件可以產生多個二進位檔。這些二進位檔可能會根據用於建置的工具鏈、提供的編譯器/連結器旗標、提供的相依性或提供的額外原始檔而有所不同。為元件產生的每個原生二進位檔稱為變體。二進位檔變體在下面詳細討論。

平行編譯

預設情況下,Gradle 使用單一建置工作者池來同時編譯和連結原生元件。不需要任何特殊設定即可啟用同時建置。

預設情況下,工作者池大小由建置機器上的可用處理器數量決定 (如報告給建置 JVM)。若要明確設定工作者數量,請使用 --max-workers 命令列選項或 org.gradle.workers.max 系統屬性。通常不需要變更此設定的預設值。

建置工作者池會在所有建置工作中共享。這表示在使用 平行專案執行 時,同時個別編譯作業的最大數量不會增加。例如,如果建置機器有 4 個處理器核心,且有 10 個專案平行編譯,Gradle 只會使用 4 個工作者,而不是 40 個。

建置函式庫

若要建置靜態或共用原生函式庫,請在 components 容器中定義函式庫元件。下列範例定義一個稱為 hello 的函式庫

範例:定義函式庫元件

build.gradle
model {
    components {
        hello(NativeLibrarySpec)
    }
}

函式庫元件使用 NativeLibrarySpec 表示。每個函式庫元件至少可以產生一個共用函式庫二進位檔 (SharedLibraryBinarySpec) 和至少一個靜態函式庫二進位檔 (StaticLibraryBinarySpec).

建置可執行檔

若要建置原生可執行檔,請在 components 容器中定義可執行檔元件。下列範例定義一個稱為 main 的可執行檔

範例:定義可執行檔元件

build.gradle
model {
    components {
        main(NativeExecutableSpec) {
            sources {
               c.lib library: "hello"
            }
        }
    }
}

可執行檔元件使用 NativeExecutableSpec 表示。每個可執行檔元件至少可以產生一個可執行檔二進位檔 (NativeExecutableBinarySpec).

對於定義的每個元件,Gradle 會新增一個具有相同名稱的 FunctionalSourceSet。這些功能性原始檔集中的每個都會包含專案支援的每種語言的語言特定原始檔集。

組裝或建置相依項

有時,您可能需要組建(編譯和連結)或建置(編譯、連結和測試)元件或二進位檔及其依賴項(依賴於元件或二進位檔的事項)。原生軟體模式提供可啟用此功能的任務。首先,依賴元件報告提供有關各元件之間關係的深入資訊。其次,建置和組建依賴項任務讓您能一步驟組建或建置元件及其依賴項。

在以下範例中,建置檔案定義 OpenSSLlibUtil 的依賴項,而 libUtilLinuxAppWindowsApp 的依賴項。測試套件的處理方式類似。依賴項可視為反向依賴項。

nativeDependents
圖 1. 依賴元件範例
藉由反向追蹤依賴項,您可以看到 LinuxAppWindowsApplibUtil依賴項。當 libUtil 變更時,Gradle 將需要重新編譯或重新連結 LinuxAppWindowsApp

當您組建元件的依賴項時,將編譯和連結元件及其所有依賴項,包括任何測試套件二進位檔。Gradle 的最新檢查用於僅在有變更時編譯或連結。例如,如果您以不會影響專案標頭的方式變更原始檔,Gradle 將能夠略過依賴元件的編譯,而只需要重新連結新函式庫。組建元件時不會執行測試。

當您建置元件的依賴項時,將編譯、連結並檢查元件及其所有依賴二進位檔。檢查元件表示執行任何檢查任務,包括執行任何測試套件,因此建置元件時執行測試。

在以下各節中,我們將示範使用 assembleDependents*buildDependents*dependentComponents 任務,並使用包含 CUnit 測試套件的範例建置。範例的建置指令碼如下

範例:範例建置

build.gradle
plugins {
    id 'c'
    id 'cunit-test-suite'
}

model {
    flavors {
        passing
        failing
    }
    platforms {
        x86 {
            if (operatingSystem.macOsX) {
                architecture "x64"
            } else {
                architecture "x86"
            }
        }
    }
    components {
        operators(NativeLibrarySpec) {
            targetPlatform "x86"
        }
    }
    testSuites {
        operatorsTest(CUnitTestSuiteSpec) {
            testing $.components.operators
        }
    }
}

依賴元件報告

Gradle 提供一份報告,您可以從命令列執行,以顯示專案中元件的圖表,以及依賴於這些元件的元件。以下是對範例專案執行 gradle dependentComponents 的範例

範例:依賴元件報告

gradle dependentComponents 的輸出
> gradle dependentComponents

> Task :dependentComponents

------------------------------------------------------------
Root project 'cunit'
------------------------------------------------------------

operators - Components that depend on native library 'operators'
+--- operators:failingSharedLibrary
+--- operators:failingStaticLibrary
+--- operators:passingSharedLibrary
\--- operators:passingStaticLibrary

Some test suites were not shown, use --test-suites or --all to show them.

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
請參閱 DependentComponentsReport API 文件以取得更多詳細資訊。

預設情況下,非可建置二進位檔和測試套件會從報告中隱藏。dependentComponents 任務提供選項,讓你能夠使用 --all 選項查看所有依賴項

範例:依賴項組件報告

gradle dependentComponents --all 的輸出
> gradle dependentComponents --all

> Task :dependentComponents

------------------------------------------------------------
Root project 'cunit'
------------------------------------------------------------

operators - Components that depend on native library 'operators'
+--- operators:failingSharedLibrary
+--- operators:failingStaticLibrary
|    \--- operatorsTest:failingCUnitExe (t)
+--- operators:passingSharedLibrary
\--- operators:passingStaticLibrary
     \--- operatorsTest:passingCUnitExe (t)

operatorsTest - Components that depend on Cunit test suite 'operatorsTest'
+--- operatorsTest:failingCUnitExe (t)
\--- operatorsTest:passingCUnitExe (t)

(t) - Test suite binary

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

以下是 operators 組件的對應報告,顯示其所有二進位檔的依賴項

範例:依賴於 operators 組件的組件報告

gradle dependentComponents --component operators 的輸出
> gradle dependentComponents --component operators

> Task :dependentComponents

------------------------------------------------------------
Root project 'cunit'
------------------------------------------------------------

operators - Components that depend on native library 'operators'
+--- operators:failingSharedLibrary
+--- operators:failingStaticLibrary
+--- operators:passingSharedLibrary
\--- operators:passingStaticLibrary

Some test suites were not shown, use --test-suites or --all to show them.

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

以下是 operators 組件的對應報告,顯示其所有二進位檔的依賴項,包括測試套件

範例:依賴於 operators 組件的組件報告,包括測試套件

gradle dependentComponents --test-suites --component operators 的輸出
> gradle dependentComponents --test-suites --component operators

> Task :dependentComponents

------------------------------------------------------------
Root project 'cunit'
------------------------------------------------------------

operators - Components that depend on native library 'operators'
+--- operators:failingSharedLibrary
+--- operators:failingStaticLibrary
|    \--- operatorsTest:failingCUnitExe (t)
+--- operators:passingSharedLibrary
\--- operators:passingStaticLibrary
     \--- operatorsTest:passingCUnitExe (t)

(t) - Test suite binary

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

此外,--non-binaries 選項會在報告中顯示非可建置二進位檔,--no-non-buildable 則會隱藏它們。類似地,--test-suites 選項會顯示測試套件,而 --no-test-suites 則會隱藏它們。--no-all 選項會從報告中隱藏非可建置二進位檔和測試套件。

組建依賴項

對於每個 NativeBinarySpec,Gradle 會建立一個名為 assembleDependents${component.name}${binary.variant} 的任務,用於組建(編譯和連結)二進位檔及其所有依賴二進位檔。

對於每個 NativeComponentSpec,Gradle 會建立一個名為 assembleDependents${component.name} 的任務,用於組建組件的所有二進位檔及其所有依賴二進位檔。

例如,要組建「operators」組件的「static」函式庫二進位檔的「passing」風味的依賴項,你會執行 assembleDependentsOperatorsPassingStaticLibrary 任務

範例:組建依賴於 operators 組件的 passing/static 二進位檔的組件

gradle assembleDependentsOperatorsPassingStaticLibrary --max-workers=1 的輸出
> gradle assembleDependentsOperatorsPassingStaticLibrary --max-workers=1
> Task :compileOperatorsTestPassingCUnitExeOperatorsC
> Task :operatorsTestCUnitLauncher
> Task :compileOperatorsTestPassingCUnitExeOperatorsTestC
> Task :compileOperatorsTestPassingCUnitExeOperatorsTestCunitLauncher
> Task :linkOperatorsTestPassingCUnitExe
> Task :operatorsTestPassingCUnitExe
> Task :assembleDependentsOperatorsTestPassingCUnitExe
> Task :compileOperatorsPassingStaticLibraryOperatorsC
> Task :createOperatorsPassingStaticLibrary
> Task :operatorsPassingStaticLibrary
> Task :assembleDependentsOperatorsPassingStaticLibrary

BUILD SUCCESSFUL in 0s
7 actionable tasks: 7 executed

在以上的輸出中,目標二進位檔會組建,依賴於它的測試套件二進位檔也會組建。

你也可以使用對應的組件任務(例如 assembleDependentsOperators)組建組件的所有依賴項(即其所有二進位檔/變異)。如果你有許多建置類型、風味和平台的組合,而且想要組建所有這些組合,這會很有用。

建置依賴項

對於每個 NativeBinarySpec,Gradle 會建立一個名為 buildDependents${component.name}${binary.variant} 的工作,用於建置(編譯、連結和檢查)二進位檔及其所有相依的二進位檔。

對於每個 NativeComponentSpec,Gradle 會建立一個名為 buildDependents${component.name} 的工作,用於建置該元件的所有二進位檔及其所有相依的二進位檔。

例如,若要建置「operators」元件的「static」程式庫二進位檔的「passing」風味的相依項,您會執行 buildDependentsOperatorsPassingStaticLibrary 工作

範例:建置相依於 operators 元件的 passing/static 二進位檔的元件

gradle buildDependentsOperatorsPassingStaticLibrary --max-workers=1 的輸出
> gradle buildDependentsOperatorsPassingStaticLibrary --max-workers=1
> Task :compileOperatorsTestPassingCUnitExeOperatorsC
> Task :operatorsTestCUnitLauncher
> Task :compileOperatorsTestPassingCUnitExeOperatorsTestC
> Task :compileOperatorsTestPassingCUnitExeOperatorsTestCunitLauncher
> Task :linkOperatorsTestPassingCUnitExe
> Task :operatorsTestPassingCUnitExe
> Task :installOperatorsTestPassingCUnitExe
> Task :runOperatorsTestPassingCUnitExe
> Task :checkOperatorsTestPassingCUnitExe
> Task :buildDependentsOperatorsTestPassingCUnitExe
> Task :compileOperatorsPassingStaticLibraryOperatorsC
> Task :createOperatorsPassingStaticLibrary
> Task :operatorsPassingStaticLibrary
> Task :buildDependentsOperatorsPassingStaticLibrary

BUILD SUCCESSFUL in 0s
9 actionable tasks: 9 executed

在以上的輸出中,目標二進位檔以及相依於它的測試套件二進位檔已建置完成,且測試套件已執行完畢。

您也可以使用對應的元件工作建置元件的所有相依項(也就是它的所有二進位檔/變異),例如 buildDependentsOperators

工作

對於每個建置中可以產生的 NativeBinarySpec,會建構一個單一的生命週期工作,可用於建立該二進位檔,以及一組執行編譯、連結或組裝二進位檔實際工作的其他工作。

${component.name}Executable
元件類型

NativeExecutableSpec

原生二進位檔類型

NativeExecutableBinarySpec

已建立二進位檔的位置

${project.layout.buildDirectory}/exe/${component.name}/${component.name}

${component.name}SharedLibrary
元件類型

NativeLibrarySpec

原生二進位檔類型

SharedLibraryBinarySpec

已建立二進位檔的位置

${project.layout.buildDirectory}/libs/${component.name}/shared/lib${component.name}.so

${component.name}StaticLibrary
元件類型

NativeLibrarySpec

原生二進位檔類型

StaticLibraryBinarySpec

已建立二進位檔的位置

${project.layout.buildDirectory}/libs/${component.name}/static/${component.name}.a

檢查工作

對於每個建置中可以產生的 NativeBinarySpec,會建構一個單一的檢查工作,可用於組裝和檢查該二進位檔。

check${component.name}Executable
元件類型

NativeExecutableSpec

原生二進位檔類型

NativeExecutableBinarySpec

check${component.name}SharedLibrary
元件類型

NativeLibrarySpec

原生二進位檔類型

SharedLibraryBinarySpec

check${component.name}StaticLibrary
元件類型

NativeLibrarySpec

原生二進位檔類型

SharedLibraryBinarySpec

內建的 check 工作相依於專案中所有二進位檔的檢查工作。在沒有 CUnitGoogleTest 外掛的情況下,二進位檔檢查工作只會相依於組裝二進位檔的生命週期工作,請參閱 原生工作

當套用 CUnitGoogleTest 外掛程式時,執行元件測試套件的任務會自動連接到適當的檢查任務

您也可以新增自訂檢查任務,如下所示

範例:新增自訂檢查任務

build.gradle
plugins {
    id "cpp"
}
// You don't need to apply the plugin below if you're already using CUnit or GoogleTest support
apply plugin: TestingModelBasePlugin

tasks.register('myCustomCheck') {
    doLast {
        println 'Executing my custom check'
    }
}

model {
    components {
        hello(NativeLibrarySpec) {
            binaries.all {
                // Register our custom check task to all binaries of this component
                checkedBy $.tasks.myCustomCheck
            }
        }
    }
}

現在,執行 check 或任何 hello 二進位檔的檢查任務,都會執行自訂檢查任務

範例:執行給定二進位檔的檢查

gradle checkHelloSharedLibrary 的輸出
> gradle checkHelloSharedLibrary

> Task :myCustomCheck
Executing my custom check

> Task :checkHelloSharedLibrary

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

使用共用函式庫

對於產生的每個可執行二進位檔,cpp 外掛程式會提供一個 install${binary.name} 任務,用來建立可執行檔的開發安裝,以及它需要的共用函式庫。這讓您可以在不需將共用函式庫安裝在最終位置的情況下執行可執行檔。

找出更多關於專案的資訊

Gradle 提供一個報告,您可以從命令列執行,顯示專案產生的元件和二進位檔的一些詳細資訊。若要使用此報告,只要執行 gradle components。以下是執行此報告的一個範例,針對其中一個範例專案

範例:元件報告

gradle components 的輸出
> gradle components

> Task :components

------------------------------------------------------------
Root project 'cpp'
------------------------------------------------------------

Native library 'hello'
----------------------

Source sets
    C++ source 'hello:cpp'
        srcDir: src/hello/cpp

Binaries
    Shared library 'hello:sharedLibrary'
        build using task: :helloSharedLibrary
        build type: build type 'debug'
        flavor: flavor 'default'
        target platform: platform 'current'
        tool chain: Tool chain 'clang' (Clang)
        shared library file: build/libs/hello/shared/libhello.dylib
    Static library 'hello:staticLibrary'
        build using task: :helloStaticLibrary
        build type: build type 'debug'
        flavor: flavor 'default'
        target platform: platform 'current'
        tool chain: Tool chain 'clang' (Clang)
        static library file: build/libs/hello/static/libhello.a

Native executable 'main'
------------------------

Source sets
    C++ source 'main:cpp'
        srcDir: src/main/cpp

Binaries
    Executable 'main:executable'
        build using task: :mainExecutable
        install using task: :installMainExecutable
        build type: build type 'debug'
        flavor: flavor 'default'
        target platform: platform 'current'
        tool chain: Tool chain 'clang' (Clang)
        executable file: build/exe/main/main

Note: currently not all plugins register their components, so some components may not be visible here.

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

語言支援

目前,Gradle 支援從下列任何組合的原始語言建立原生軟體。原生二進位檔專案將包含一個或多個已命名 FunctionalSourceSet 實例(例如「main」、「test」等),每個實例都可以包含 LanguageSourceSet,其中包含原始檔案,每個語言一個。

  • C

  • C++

  • Objective-C

  • Objective-C++

  • 組合語言

  • Windows 資源

C++ 原始檔

C++ 語言支援是透過 'cpp' 外掛程式提供的。

範例:'cpp' 外掛程式

build.gradle
plugins {
    id 'cpp'
}

要包含在原生二進位檔中的 C++ 原始檔是透過 CppSourceSet 提供的,它定義一組 C++ 原始檔,並選擇性地定義一組匯出的標頭檔(用於函式庫)。預設情況下,對於任何已命名元件,CppSourceSet 都包含 src/${name}/cpp 中的 .cpp 原始檔,以及 src/${name}/headers 中的標頭檔。

雖然 cpp 外掛程式為每個 CppSourceSet 定義這些預設位置,但可以延伸或覆寫這些預設值,以允許不同的專案配置。

範例:C++ 原始檔組

build.gradle
sources {
    cpp {
        source {
            srcDir "src/source"
            include "**/*.cpp"
        }
    }
}

對於名為「main」的函式庫,src/main/headers 中的標頭檔會被視為「公開」或「匯出」標頭檔。不應匯出的標頭檔應放置在 src/main/cpp 目錄中(但請注意,此類標頭檔應始終以相對於包含它們的檔案的方式參照)。

C 來源

C 語言支援是透過 'c' 外掛程式來提供的。

範例:'c' 外掛程式

build.gradle
plugins {
    id 'c'
}

要包含在原生二進位檔中的 C 來源是透過 CSourceSet 提供的,它定義一組 C 來源檔案,並可選擇一組匯出的標頭檔 (用於函式庫)。預設情況下,對於任何命名元件,CSourceSet 都包含 src/${name}/c 中的 .c 來源檔案,以及 src/${name}/headers 中的標頭檔。

雖然 c 外掛程式為每個 CSourceSet 定義了這些預設位置,但可以延伸或覆寫這些預設值,以允許不同的專案配置。

範例:C 來源組

build.gradle
sources {
    c {
        source {
            srcDir "src/source"
            include "**/*.c"
        }
        exportedHeaders {
            srcDir "src/include"
        }
    }
}

對於名為 'main' 的函式庫,src/main/headers 中的標頭檔會被視為「公開」或「匯出」標頭。不應匯出的標頭檔應放置在 src/main/c 目錄中 (但請注意,此類標頭檔應始終以相對於包含它們的檔案的方式參照)。

組譯器來源

組譯語言支援是透過 'assembler' 外掛程式來提供的。

範例:'assembler' 外掛程式

build.gradle
plugins {
    id 'assembler'
}

要包含在原生二進位檔中的組譯器來源是透過 AssemblerSourceSet 提供的,它定義一組組譯器來源檔案。預設情況下,對於任何命名元件,AssemblerSourceSet 都包含 src/${name}/asm 中的 .s 來源檔案。

Objective-C 來源

Objective-C 語言支援是透過 'objective-c' 外掛程式來提供的。

範例:'objective-c' 外掛程式

build.gradle
plugins {
    id 'objective-c'
}

要包含在原生二進位檔中的 Objective-C 來源是透過 ObjectiveCSourceSet 提供的,它定義一組 Objective-C 來源檔案。預設情況下,對於任何命名元件,ObjectiveCSourceSet 都包含 src/${name}/objectiveC 中的 .m 來源檔案。

Objective-C++ 來源

Objective-C++ 語言支援是透過 'objective-cpp' 外掛程式提供的。

範例:'objective-cpp' 外掛程式

build.gradle
plugins {
    id 'objective-cpp'
}

要包含在原生二進位檔中的 Objective-C++ 來源是透過 ObjectiveCppSourceSet 提供的,它定義了一組 Objective-C++ 來源檔案。預設情況下,對於任何已命名元件,ObjectiveCppSourceSet 都包含 src/${name}/objectiveCpp 底下的 .mm 來源檔案。

設定編譯器、組譯器和連結器

每個要產生的二進位檔都與一組編譯器和連結器設定相關聯,其中包括命令列引數和巨集定義。這些設定可以套用至所有二進位檔、個別二進位檔,或根據某些準則選擇性地套用至一群二進位檔。

範例:套用至所有二進位檔的設定

build.gradle
model {
    binaries {
        all {
            // Define a preprocessor macro for every binary
            cppCompiler.define "NDEBUG"

            // Define toolchain-specific compiler and linker options
            if (toolChain in Gcc) {
                cppCompiler.args "-O2", "-fno-access-control"
                linker.args "-Xlinker", "-S"
            }
            if (toolChain in VisualCpp) {
                cppCompiler.args "/Zi"
                linker.args "/DEBUG"
            }
        }
    }
}

每個二進位檔都與特定的 NativeToolChain 相關聯,允許根據此值設定目標設定。

很容易將設定套用至特定類型的所有二進位檔

範例:套用至所有共用函式庫的設定

build.gradle
// For any shared library binaries built with Visual C++,
// define the DLL_EXPORT macro
model {
    binaries {
        withType(SharedLibraryBinarySpec) {
            if (toolChain in VisualCpp) {
                cCompiler.args "/Zi"
                cCompiler.define "DLL_EXPORT"
            }
        }
    }
}

此外,可以指定套用至為特定 executablelibrary 元件產生的所有二進位檔的設定

範例:套用至為 'main' 可執行元件產生的所有二進位檔的設定

build.gradle
model {
    components {
        main(NativeExecutableSpec) {
            targetPlatform "x86"
            binaries.all {
                if (toolChain in VisualCpp) {
                    sources {
                        platformAsm(AssemblerSourceSet) {
                            source.srcDir "src/main/asm_i386_masm"
                        }
                    }
                    assembler.args "/Zi"
                } else {
                    sources {
                        platformAsm(AssemblerSourceSet) {
                            source.srcDir "src/main/asm_i386_gcc"
                        }
                    }
                    assembler.args "-g"
                }
            }
        }
    }
}

上述範例會將提供的設定套用至所有建置的 executable 二進位檔。

類似地,可以指定設定以鎖定特定類型的元件二進位檔:例如主函式庫元件的所有共用函式庫。

範例:僅套用至為 'main' 函式庫元件產生的共用函式庫的設定

build.gradle
model {
    components {
        main(NativeLibrarySpec) {
            binaries.withType(SharedLibraryBinarySpec) {
                // Define a preprocessor macro that only applies to shared libraries
                cppCompiler.define "DLL_EXPORT"
            }
        }
    }
}

Windows 資源

在使用 VisualCpp 工具鏈時,Gradle 能夠編譯 Windows 資源 (rc) 檔案,並將它們連結到原生二進位檔中。此功能是由 'windows-resources' 外掛程式提供的。

範例:'windows-resources' 外掛程式

build.gradle
plugins {
    id 'windows-resources'
}

要包含在原生二進位檔中的 Windows 資源是透過 WindowsResourceSet 提供,其中定義一組 Windows 資源原始檔。預設情況下,對於任何命名元件,WindowsResourceSet 會包含在 src/${name}/rc 底下的 .rc 原始檔。

與其他原始檔類型一樣,您可以設定要包含在二進位檔中的 Windows 資源位置。

範例:設定 Windows 資源來源位置

build-resource-only-dll.gradle
sources {
    rc {
        source {
            srcDirs "src/hello/rc"
        }
        exportedHeaders {
            srcDirs "src/hello/headers"
        }
    }
}

您可以透過提供沒有其他語言來源的 Windows 資源來源來建構僅資源的程式庫,並適當地設定連結器

範例:建構僅資源的 dll

build-resource-only-dll.gradle
model {
    components {
        helloRes(NativeLibrarySpec) {
            binaries.all {
                rcCompiler.args "/v"
                linker.args "/noentry", "/machine:x86"
            }
            sources {
                rc {
                    source {
                        srcDirs "src/hello/rc"
                    }
                    exportedHeaders {
                        srcDirs "src/hello/headers"
                    }
                }
            }
        }
    }
}

上述範例也示範傳遞額外命令列引數給資源編譯器的機制。rcCompiler 擴充功能的類型為 PreprocessingTool

程式庫相依性

原生元件的相依性是匯出標頭檔的二進位程式庫。標頭檔會在編譯期間使用,而編譯的二進位相依性會在連結和執行期間使用。標頭檔應組織成子目錄,以防止常見標頭名稱發生衝突。例如,如果您的 mylib 專案有一個 logging.h 標頭,如果您將它包含為 "mylib/logging.h" 而不是 "logging.h",則較不容易使用錯誤的標頭。

同一個專案中的相依性

一組來源可能會相依於同一個專案中另一個二進位元件提供的標頭檔。常見的範例是使用由獨立原生程式庫元件提供的函式的原生可執行元件元件。

此類程式庫相依性可以新增到與 executable 元件關聯的來源組

範例:提供程式庫相依性給來源組

build.gradle
sources {
    cpp {
        lib library: "hello"
    }
}

或者,程式庫相依性可以直接提供給 executableNativeExecutableBinarySpec

範例:提供二進位檔的函式庫相依性

build.gradle
model {
    components {
        hello(NativeLibrarySpec) {
            sources {
                c {
                    source {
                        srcDir "src/source"
                        include "**/*.c"
                    }
                    exportedHeaders {
                        srcDir "src/include"
                    }
                }
            }
        }
        main(NativeExecutableSpec) {
            sources {
                cpp {
                    source {
                        srcDir "src/source"
                        include "**/*.cpp"
                    }
                }
            }
            binaries.all {
                // Each executable binary produced uses the 'hello' static library binary
                lib library: 'hello', linkage: 'static'
            }
        }
    }
}

專案相依性

對於在不同 Gradle 專案中產生的元件,符號類似。

範例:宣告專案相依性

lib/build.gradle
plugins {
    id 'cpp'
}

model {
    components {
        main(NativeLibrarySpec)
    }

    // For any shared library binaries built with Visual C++,
    // define the DLL_EXPORT macro
    binaries {
        withType(SharedLibraryBinarySpec) {
            if (toolChain in VisualCpp) {
                cppCompiler.define "DLL_EXPORT"
            }
        }
    }
}
exe/build.gradle
plugins {
    id 'cpp'
}

model {
    components {
        main(NativeExecutableSpec) {
            sources {
                cpp {
                    lib project: ':lib', library: 'main'
                }
            }
        }
    }
}

預編譯標頭

預編譯標頭是一種效能最佳化,可降低編譯廣泛使用的標頭多次的成本。此功能會預編譯標頭,讓編譯的物件檔案可在編譯每個原始檔時重複使用,而非每次都重新編譯標頭。此支援適用於 C、C++、Objective-C 和 Objective-C++ 建置。

若要設定預編譯標頭,首先需要定義一個標頭檔案,其中包含所有應該預編譯的標頭。它必須指定為每個原始檔中第一個包含的標頭,其中應該使用預編譯標頭。假設這個標頭檔案和它包含的任何標頭都使用標頭防護,以便它們可以以冪等方式包含。如果標頭檔案中未使用標頭防護,標頭可能會被編譯多次,並可能導致建置中斷。

範例:建立預編譯標頭檔案

src/hello/headers/pch.h
#ifndef PCH_H
#define PCH_H
#include <iostream>
#include "hello.h"
#endif

範例:在原始檔中包含預編譯標頭檔案

src/hello/cpp/hello.cpp
#include "pch.h"

void LIB_FUNC Greeter::hello () {
    std::cout << "Hello world!" << std::endl;
}

預編譯標頭會在原始檔集上指定。只有一個預編譯標頭檔案可以在給定的原始檔集上指定,並會套用至所有宣告它為第一個包含的原始檔。如果原始檔未將這個標頭檔案包含為第一個標頭,檔案將會以一般方式編譯(不使用預編譯標頭物件檔案)。提供的字串應該與原始檔中「#include」指令中使用的相同。

範例:設定預編譯標頭

build.gradle
model {
    components {
        hello(NativeLibrarySpec) {
            sources {
                cpp {
                    preCompiledHeader "pch.h"
                }
            }
        }
    }
}

使用預編譯標頭的所有檔案都必須以相同方式包含它。通常,這表示標頭檔案應該存在於原始檔集「標頭」目錄或包含在編譯器包含路徑的目錄中。

原生二進制變體

對於每個已定義的可執行檔或函式庫,Gradle 能夠建置許多不同的原生二進制變體。不同變體的範例包括偵錯與發布二進制檔案、32 位元與 64 位元二進制檔案,以及使用不同自訂預處理器旗標產生的二進制檔案。

Gradle 產生的二進制檔案可以在 建置類型平台風味 中區分。對於這些「變體維度」中的每一個,都可以指定一組可用值,以及將每個元件鎖定在這些值中的其中一個、幾個或全部。例如,外掛程式可以定義支援平台的範圍,但您可能選擇只針對特定元件鎖定 Windows-x86。

建置類型

build type 決定二進制檔案的各種非功能性面向,例如是否包含偵錯資訊,或二進制檔案編譯時使用哪個最佳化層級。典型的建置類型為「偵錯」和「發布」,但專案可以自由定義任何建置類型組。

範例:定義建置類型

build.gradle
model {
    buildTypes {
        debug
        release
    }
}

如果專案中未定義任何建置類型,則會新增一個稱為「偵錯」的單一預設建置類型。

對於建置類型,Gradle 專案通常會針對每個工具鏈定義一組編譯器/連結器旗標。

範例:設定偵錯二進制檔案

build.gradle
model {
    binaries {
        all {
            if (toolChain in Gcc && buildType == buildTypes.debug) {
                cppCompiler.args "-g"
            }
            if (toolChain in VisualCpp && buildType == buildTypes.debug) {
                cppCompiler.args '/Zi'
                cppCompiler.define 'DEBUG'
                linker.args '/DEBUG'
            }
        }
    }
}
在此階段,建置指令碼完全負責設定每個建置類型的相關編譯器/連結器旗標。Gradle 的未來版本會自動為任何「偵錯」建置類型包含適當的偵錯旗標,並且可能也會知道各種最佳化層級。

平台

可建置可執行檔或函式庫在不同的作業系統和 CPU 架構上執行,並為每個平台產生一個變體。Gradle 將每個作業系統/架構組合定義為 NativePlatform,而且專案可以定義任意數量的平台。如果專案中未定義任何平台,則會新增一個稱為「目前」的單一預設平台。

目前,Platform 包含已定義的作業系統和架構。隨著我們持續在 Gradle 中開發原生二進制支援,Platform 的概念將會擴充,以包含 C 執行時間版本、Windows SDK、ABI 等項目。精密的建置可以使用 Gradle 的可擴充性,將其他屬性套用至每個平台,然後可以查詢這些屬性,以指定原生二進制檔案的特定包含、預處理器巨集或編譯器引數。

範例:定義平台

build.gradle
model {
    platforms {
        x86 {
            architecture "x86"
        }
        x64 {
            architecture "x86_64"
        }
        itanium {
            architecture "ia-64"
        }
    }
}

對於給定的變體,Gradle 會嘗試尋找一個 NativeToolChain,它能夠針對目標平台進行建置。會依據定義的順序搜尋可用的工具鏈。請參閱下方 工具鏈 區段以取得更多詳細資料。

風味

每個元件都可以有一組名為 flavors 的風味,而且可以針對每個風味產生一個獨立的二進制變體。雖然 build typetarget platform 變體維度在 Gradle 中有定義的意義,但每個專案都可以自由定義任意數量的風味,並以任何方式套用意義。

元件風味的範例可能是區分元件的「示範」、「付費」和「企業」版本,其中使用同一組來源產生具有不同功能的二進制檔案。

範例:定義風味

build.gradle
model {
    flavors {
        english
        french
    }
    components {
        hello(NativeLibrarySpec) {
            binaries.all {
                if (flavor == flavors.french) {
                    cppCompiler.define "FRENCH"
                }
            }
        }
    }
}

在上述範例中,定義了一個具有「英文」和「法文」風味的函式庫。在編譯「法文」變體時,會定義一個獨立的巨集,這會產生一個不同的二進制檔案。

如果未針對元件定義風味,則會使用一個名為「預設」的單一預設風味。

選擇元件的建置類型、平台和風味

對於預設元件,Gradle 會嘗試針對專案定義的每個 buildTypeflavor 組合建立一個原生二進制變體。可以透過指定 targetBuildTypes 和/或 targetFlavors 組合,針對每個元件覆寫這個設定。預設情況下,Gradle 會針對預設平台建置,請參閱 上方,除非透過指定 targetPlatforms 組合針對每個元件明確指定。

範例:將元件鎖定在特定平台

build.gradle
model {
    components {
        hello(NativeLibrarySpec) {
            targetPlatform "x86"
            targetPlatform "x64"
        }
        main(NativeExecutableSpec) {
            targetPlatform "x86"
            targetPlatform "x64"
            sources {
                cpp.lib library: 'hello', linkage: 'static'
            }
        }
    }
}

在這裡,您可以看到 TargetedNativeComponent.targetPlatform(java.lang.String) 方法用於指定 NativeExecutableSpec 名為 main 的平台,它應該針對該平台建置。

建置所有可能的變體

當為元件定義一組建置類型、目標平台和風味時,會為這些元素的每一個可能的組合建立一個 NativeBinarySpec 模型元素。然而,在許多案例中,無法建置特定變異,可能是因為沒有工具鏈可用來為特定平台建置。

如果無法基於任何原因建置二進位變異,則與該變異關聯的 NativeBinarySpec 將不會是 buildable。可以使用此屬性來建立一個任務,以在特定機器上產生所有可能的變異。

範例:建置所有可能的變異

build.gradle
model {
    tasks {
        buildAllExecutables(Task) {
            dependsOn $.binaries.findAll { it.buildable }
        }
    }
}

工具鏈

單一建置可以使用不同的工具鏈來為不同平台建置變異。為此,核心「原生二進位」外掛程式將嘗試尋找並提供支援的工具鏈。然而,專案的工具鏈組也可以明確定義,允許額外的交叉編譯器進行組態,並允許指定安裝目錄。

定義工具鏈

支援的工具鏈類型為

範例:定義工具鏈

build.gradle
model {
    toolChains {
        visualCpp(VisualCpp) {
            // Specify the installDir if Visual Studio cannot be located
            // installDir "C:/Apps/Microsoft Visual Studio 10.0"
        }
        gcc(Gcc) {
            // Uncomment to use a GCC install that is not in the PATH
            // path "/usr/bin/gcc"
        }
        clang(Clang)
    }
}

每個工具鏈實作允許一定程度的組態(請參閱 API 文件以取得更多詳細資料)。

使用工具鏈

不需要或無法指定應使用哪個工具鏈來建置。對於給定的變異,Gradle 將嘗試尋找一個 NativeToolChain,能夠為目標平台建置。可用的工具鏈會按照定義的順序進行搜尋。

當平台未定義架構或作業系統時,會假設工具鏈的預設目標。因此,如果平台未定義 operatingSystem 的值,Gradle 將會尋找第一個可用的工具鏈,該工具鏈能夠為指定的 architecture 建置。

核心 Gradle 工具鏈能夠立即針對下列架構。在每種情況下,工具鏈將針對目前的作業系統。請參閱下一節,以取得關於為其他作業系統進行交叉編譯的資訊。

工具鏈 架構

GCC

x86、x86_64、arm64(僅限 macOS)

Clang

x86、x86_64、arm64(僅限 macOS)

Visual C++

x86、x86_64、ia-64

因此,對於在 Linux 上執行的 GCC,支援的目標平台為「linux/x86」和「linux/x86_64」。對於透過 Cygwin 在 Windows 上執行的 GCC,支援的平台為「windows/x86」和「windows/x86_64」。(Cygwin POSIX 執行時間目前尚未建模為平台的一部分,但未來會納入。)

如果未針對專案定義任何目標平台,則所有二進位檔都會建置為目標為名為「current」的預設平台。此預設平台未指定任何 architectureoperatingSystem 值,因此使用第一個可用工具鏈的預設值。

Gradle 提供一個 hook,讓建置作者可以控制傳遞給工具鏈可執行檔的精確參數組。這讓建置作者可以解決 Gradle 中的任何限制,或 Gradle 做出的任何假設。參數 hook 應視為「最後手段」機制,優先考慮真正建模基礎網域。

範例:重新設定工具參數

build.gradle
model {
    toolChains {
        visualCpp(VisualCpp) {
            eachPlatform {
                cppCompiler.withArguments { args ->
                    args << "-DFRENCH"
                }
            }
        }
        clang(Clang) {
            eachPlatform {
                cCompiler.withArguments { args ->
                    Collections.replaceAll(args, "CUSTOM", "-DFRENCH")
                }
                linker.withArguments { args ->
                    args.remove "CUSTOM"
                }
                staticLibArchiver.withArguments { args ->
                    args.remove "CUSTOM"
                }
            }
        }
    }
}

使用 GCC 進行交叉編譯

透過新增對其他目標平台的支援,可以使用 GccClang 工具鏈進行交叉編譯。這可透過為工具鏈指定目標平台來完成。針對每個目標平台,都可以指定自訂設定檔。

範例:定義目標平台

build.gradle
model {
    toolChains {
        gcc(Gcc) {
            target("arm"){
                cppCompiler.withArguments { args ->
                    args << "-m32"
                }
                linker.withArguments { args ->
                    args << "-m32"
                }
            }
            target("sparc")
        }
    }
    platforms {
        arm {
            architecture "arm"
        }
        sparc {
            architecture "sparc"
        }
    }
    components {
        main(NativeExecutableSpec) {
            targetPlatform "arm"
            targetPlatform "sparc"
        }
    }
}

Visual Studio IDE 整合

Gradle 能為建置中定義的原生元件產生 Visual Studio 專案和解決方案檔案。此功能是由 visual-studio 外掛程式新增的。對於多專案建置,所有包含原生元件的專案 (以及根專案) 都應套用此外掛程式。

visual-studio 外掛程式套用於根專案時,會建立一個名為 visualStudio 的工作,它會產生一個 Visual Studio 解決方案檔案,其中包含建置中的所有元件。此解決方案會包含每個元件的 Visual Studio 專案,以及設定每個元件使用 Gradle 建置。

當專案為根專案時,visual-studio 外掛程式也會建立一個名為 openVisualStudio 的工作。此工作會產生 Visual Studio 解決方案,然後在 Visual Studio 中開啟解決方案。這表示您可以從根專案執行 gradlew openVisualStudio,以一個方便的步驟產生並開啟 Visual Studio 解決方案。

可以透過 visualStudio 擴充功能提供的 API hook 修改產生之 Visual Studio 檔案的內容。請參閱「visual-studio」範例,或在 API 文件中參閱 VisualStudioExtension.getProjects()VisualStudioRootExtension.getSolution() 以取得更多詳細資料。

CUnit 支援

Gradle cunit 外掛提供支援,可在原生二進位專案中編譯和執行 CUnit 測試。對於專案中定義的每個 NativeExecutableSpecNativeLibrarySpec,Gradle 會建立一個相符的 CUnitTestSuiteSpec 元件,命名為 ${component.name}Test

CUnit 來源

對於專案中的每個 CUnitTestSuiteSpec 元件,Gradle 會建立一個名為「cunit」的 CSourceSet。此來源組應包含受測元件的 CUnit 測試檔案。來源檔案可以位於慣例位置 (src/${component.name}Test/cunit),或可以像任何其他來源組一樣進行設定。

Gradle 會初始化 CUnit 測試登錄檔並執行測試,利用一些產生的 CUnit 啟動器來源。Gradle 會期待並呼叫具有簽章 void gradle_cunit_register() 的函式,您可以使用此函式來設定要執行的實際 CUnit 組合和測試。

範例:註冊 CUnit 測試

suite_operators.c
#include <CUnit/Basic.h>
#include "gradle_cunit_register.h"
#include "test_operators.h"

int suite_init(void) {
    return 0;
}

int suite_clean(void) {
    return 0;
}

void gradle_cunit_register() {
    CU_pSuite pSuiteMath = CU_add_suite("operator tests", suite_init, suite_clean);
    CU_add_test(pSuiteMath, "test_plus", test_plus);
    CU_add_test(pSuiteMath, "test_minus", test_minus);
}
由於這個機制,您的 CUnit 來源可能不包含 main 方法,因為這會與 Gradle 提供的方法發生衝突。

建立 CUnit 可執行檔

CUnitTestSuiteSpec 元件具有相關聯的 NativeExecutableSpecNativeLibrarySpec 元件。對於為主要元件設定的每個 NativeBinarySpec,會在測試組件上設定相符的 CUnitTestSuiteBinarySpec。這些測試組件二進位檔可以設定的方式與任何其他二進位檔執行個體類似

範例:設定 CUnit 測試

build.gradle
model {
    binaries {
        withType(CUnitTestSuiteBinarySpec) {
            lib library: "cunit", linkage: "static"

            if (flavor == flavors.failing) {
                cCompiler.define "PLUS_BROKEN"
            }
        }
    }
}
專案提供的 CUnit 來源和產生的啟動器都需要核心 CUnit 標頭和函式庫。目前,此函式庫相依性必須由您的專案提供,以供每個 CUnitTestSuiteBinarySpec 使用。

執行 CUnit 測試

對於每個 CUnitTestSuiteBinarySpec,Gradle 會建立一個任務來執行這個二進位檔,這將執行所有已註冊的 CUnit 測試。測試結果會顯示在 ${build.dir}/test-results 目錄中。

範例:執行 CUnit 測試

build.gradle
plugins {
    id 'c'
    id 'cunit-test-suite'
}

model {
    flavors {
        passing
        failing
    }
    platforms {
        x86 {
            if (operatingSystem.macOsX) {
                architecture "x64"
            } else {
                architecture "x86"
            }
        }
    }
    repositories {
        libs(PrebuiltLibraries) {
            cunit {
                headers.srcDir "libs/cunit/2.1-2/include"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile =
                        file("libs/cunit/2.1-2/lib/" +
                             findCUnitLibForPlatform(targetPlatform))
                }
            }
        }
    }
    components {
        operators(NativeLibrarySpec) {
            targetPlatform "x86"
        }
    }
    testSuites {
        operatorsTest(CUnitTestSuiteSpec) {
            testing $.components.operators
        }
    }
}
model {
    binaries {
        withType(CUnitTestSuiteBinarySpec) {
            lib library: "cunit", linkage: "static"

            if (flavor == flavors.failing) {
                cCompiler.define "PLUS_BROKEN"
            }
        }
    }
}
gradle -q runOperatorsTestFailingCUnitExe 的輸出
> gradle -q runOperatorsTestFailingCUnitExe

There were test failures:
  1. /home/user/gradle/samples/src/operatorsTest/c/test_plus.c:6  - plus(0, -2) == -2
  2. /home/user/gradle/samples/src/operatorsTest/c/test_plus.c:7  - plus(2, 2) == 4

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':runOperatorsTestFailingCUnitExe'.
> There were failing tests. See the results at: file:///home/user/gradle/samples/build/test-results/operatorsTest/failing/

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 0s

目前對 CUnit 的支援相當基本。未來整合的計畫包括

  • 允許使用 Javadoc 式註解來宣告測試。

  • 改善 HTML 報告,類似於 JUnit 可用的報告。

  • 測試執行時的即時回饋。

  • 支援其他測試架構。

GoogleTest 支援

Gradle google-test 外掛程式提供在原生二進位專案中編譯和執行 GoogleTest 測試的支援。對於專案中定義的每個 NativeExecutableSpecNativeLibrarySpec,Gradle 會建立一個相符的 GoogleTestTestSuiteSpec 元件,命名為 ${component.name}Test

GoogleTest 來源

Gradle 會為專案中的每個 GoogleTestTestSuiteSpec 元件建立一個名為「cpp」的 CppSourceSet。這個來源組應該包含要測試元件的 GoogleTest 測試檔案。來源檔案可以放在傳統位置 (src/${component.name}Test/cpp) 或可以像任何其他來源組一樣進行組態。

建立 GoogleTest 可執行檔

GoogleTestTestSuiteSpec 元件有一個相關聯的 NativeExecutableSpecNativeLibrarySpec 元件。對於為主要元件組態的每個 NativeBinarySpec,會在測試套件元件上組態一個相符的 GoogleTestTestSuiteBinarySpec。這些測試套件二進位檔可以像任何其他二進位執行個體一樣進行組態

範例:註冊 GoogleTest 測試

build.gradle
model {
    binaries {
        withType(GoogleTestTestSuiteBinarySpec) {
            lib library: "googleTest", linkage: "static"

            if (flavor == flavors.failing) {
                cppCompiler.define "PLUS_BROKEN"
            }

            if (targetPlatform.operatingSystem.linux) {
                cppCompiler.args '-pthread'
                linker.args '-pthread'

                if (toolChain instanceof Gcc || toolChain instanceof Clang) {
                    // Use C++03 with the old ABIs, as this is what the googletest binaries were built with
                    cppCompiler.args '-std=c++03', '-D_GLIBCXX_USE_CXX11_ABI=0'
                    linker.args '-std=c++03'
                }
            }
        }
    }
}
專案提供的 GoogleTest 來源需要核心 GoogleTest 標頭和函式庫。目前,這個函式庫相依性必須由專案提供給每個 GoogleTestTestSuiteBinarySpec

執行 GoogleTest 測試

對於每個 GoogleTestTestSuiteBinarySpec,Gradle 會建立一個任務來執行此二進位檔,這將執行所有已註冊的 GoogleTest 測試。測試結果會出現在 ${build.dir}/test-results 目錄中。

目前對 GoogleTest 的支援相當基本。未來整合計畫包括

  • 改善 HTML 報告,類似於 JUnit 可用的報告。

  • 測試執行時的即時回饋。

  • 支援其他測試架構。