http://blog.csdn.net/column/details/gradle-translation.html
翻譯項目請關注Github上的地址:
https://github.com/msdx/gradledoc
本文翻譯所在分支:
https://github.com/msdx/gradledoc/tree/1.12。
直接瀏覽雙語版的文檔請訪問:
http://gradledoc.qiniudn.com/1.12/userguide/userguide.html。
另外,Android 手機用戶可通過我寫的一個程序瀏覽文檔,帶緩存功能的,目前0.5版本兼容 Android 2.3以上系統,項目地址如下:
https://github.com/msdx/gradle-doc-apk
翻譯不易,轉載請注明本文在CSDN博客上的出處:
http://blog.csdn.net/maosidiaoxian/article/details/55683474
關于我對Gradle的翻譯,以Github上的項目及http://gradledoc.qiniudn.com 上的文檔為準。如發現翻譯有誤的地方,將首先在以上兩個地方更新。因時間精力問題,博客中發表的譯文基本不會同步修改。
另外,目前Gradle1.12版本的文檔進入校稿階段,校稿的方式可以為到該項目https://github.com/msdx/gradledoc 提交issue或是pull request。校稿的結果不只是在此版本更新,也會用于改善Gradle下一版本(2.0)文檔的翻譯。
第五十四章. 構建原生二進制文件
Gradle 對構建原生二進制文件的支持目前還是孵化階段。請務必注意,在以后的 Gradle 版本中,相關的 DSL 和其他配置可能會有所改變。
不同的原生二進制插件添加了對從C++,C,Objective-C,Objective-C++以及匯編源文件構建原生軟件組件的支持。雖然對于這種軟件開發的空間,已經有許多優秀的構建工具存在,但是Gradle 向開發人員提供的是它的強大特征和靈活性,以及在依賴管理實踐上,在JVM開發空間上更為傳統的發現。
Gradle 提供了使用不同的工具鏈執行相同的構建的能力。你可以通過更改操作系統的PATH讓其包含所需的工具鏈編譯器,來控制使用哪個工具鏈。或者,你可以直接配置工具鏈,就如下面的“原生二進制變種”中描述的。
支持以下的工具鏈:
操作系統 | 工具鏈 | 備注 |
Linux | GCC | ? |
Linux | Clang | ? |
Mac OS X | GCC | 使用 XCode 中的 GCC。 |
Mac OS X | Clang | 使用 XCode 中的 Clang。 |
Windows | Visual C++ | Windows XP及以上,Visual C++ 2010 及以上版本。 |
Windows | GCC | Windows XP及以上,使用Cygwin的GCC。 |
Windows | MinGW | Windows XP 及以上。 |
一個原生二進制project定義了一組Executable
和Library
組件,每一個的 Gradle 都映射大量的NativeBinary
輸出。對于每個定義的executable
或library
,Gradle 添加了具有相同名稱的FunctionalSourceSet
?。這些功能源碼集將為project所支持的每一種語言包含指定語言的源碼集。
為構建一個靜態或共享的原生庫二進制文件,一個Library
組件將添加到libraries
容器中。每個library
組件可以產生至少一個SharedLibraryBinary
和至少一個StaticLibraryBinary
。
為構建一個可執行的二進制,Executable
組件添加到executables
容器中,并與源碼集相關聯。
在許多情況下,一個組件可以產生超過一個的原生二進制文件。基于構建所使用的工具鏈,提供的編譯器/鏈接器標志,提供的依賴或其他源文件,這些二進制文件可能會發生變化。組件所產生的每個原生二進制稱為variant
。下面將詳細討論二進制 variant。
針對由構建所產生的每一個?NativeBinary
,我們構造了一個生命周期任務用于創建二進制,以及一系統的其他做實際工作,如編譯,鏈接或者是裝配二進制文件的任務。
組件類型 | 原生二進制文件類型 | 生命周期任務 | 創建二進制文件的位置 |
Executable | ExecutableBinary |
|
|
Library | SharedLibraryBinary |
|
|
Library | StaticLibraryBinary |
|
|
目前,Gradle 支持從C++,C,Assembler,Objective-C 和 Objective-C++源碼的任意組合中構建原生二進制文件。一個原生二進制project 將包含一個或多個叫做FunctionalSourceSet
的實例(如"main","test"等),其中每一個都可以包含含有C++,C,Assembler,Objective-C或Objective-C++源代碼的LanguageSourceSet
s。
'cpp'
?插件提供了C++ 語言的支持。
把 C++ 源碼包含到原生二進制文件中,是通過一個?CppSourceSet
來實現的,它定義了一個C++源文件集以及(可選的)一個可導出的頭文件(用于library)集默認情況下,對于任何命名的組件,CppSourceSet
包含了在src/${name}/cpp
中的.cpp
源文件,和在src/${name}/headers
中的頭文件。
而cpp
插件為每個CppSourceSet
定義了這些默認的位置,且可以擴展或重寫這些默認值使能夠成為不同的項目布局。
示例 54.4.?C++ 源代碼集
build.gradle
sources {main {cpp {source {srcDir "src/source"include "**/*.cpp"}}} }
對于名字為“main”的library,?src/main/headers
中的文件都被視為"公共"或"導出"的頭文件。不應該被導出(而是內部使用)的頭文件,應該放在?src/main/cpp
?目錄(不過要注意,這樣的文件應該總是以相對于包含它們的文件這樣的一種方式被引用)。
'c'
?插件提供了C 語言的支持。
把 C 源碼包含到原生二進制文件中,是通過一個?CSourceSet
來實現的,它定義了一個C源文件集以及(可選的)一個可導出的頭文件(用于library)集默認情況下,對于任何命名的組件,CSourceSet
包含了在src/${name}/c
中的.c
源文件,和在src/${name}/headers
中的頭文件。
而c
插件為每個CSourceSet
定義了這些默認的位置,且可以擴展或重寫這些默認值使能夠成為不同的項目布局。
示例 54.4.?C 源代碼集
build.gradle
sources {hello {c {source {srcDir "src/source"include "**/*.c"}exportedHeaders {srcDir "src/include"}}} }
對于名字為“main”的library,?src/main/headers
中的文件都被視為"公共"或"導出"的頭文件。不應該被導出(而是內部使用)的頭文件,應該放在?src/main/c
?目錄(不過要注意,這樣的文件應該總是以相對于包含它們的文件這樣一種方式被引用)。
“assembler”
?插件提供了匯編語言的支持。
把匯編源碼包含到原生二進制文件中,是通過一個?AssemblerSourceSet
來實現的,它定義了一個匯編源文件集。默認情況下,對于任何命名的組件,AssemblerSourceSet
包含了在src/${name}/asm
中的.s
源文件。
'objective-c'
?插件提供了Objective-C 語言的支持。
把Objective-C源碼包含到原生二進制文件中,是通過一個?ObjectiveCSourceSet
來實現的,它定義了一個Objective-C源文件集。默認情況下,對于任何命名的組件,ObjectiveCSourceSet
包含了在src/${name}/objectiveC
中的.m
源文件。
每一個產生的二進制文件都和一系列的編譯器和鏈接器設置相關聯,這些設置包含了命令行參數,以及宏定義。這些設置可以應用于所有的二進制文件,單個二進制文件,或選擇性地應用于基于某些條件的一組二進制文件。
示例 54.10. 應用于所有二進制文件的設置
build.gradle
binaries.all {// Define a preprocessor macro for every binarycppCompiler.define "NDEBUG"// Define toolchain-specific compiler and linker optionsif (toolChain in Gcc) {cppCompiler.args "-O2", "-fno-access-control"linker.args "-Xlinker", "-S"}if (toolChain in VisualCpp) {cppCompiler.args "/Zi"linker.args "/DEBUG"} }
每個二進制文件與特定的ToolChain
關聯,允許設置基于此值進行針對性的配置。
讓設置應用于指定類型的所有二進制文件很簡單:
示例 54.11. 應用于所有共享庫的設置
build.gradle
// For any shared library binaries built with Visual C++, define the DLL_EXPORT macro binaries.withType(SharedLibraryBinary) {if (toolChain in VisualCpp) {cCompiler.args "/Zi"cCompiler.define "DLL_EXPORT"} }
此外,還可以指定設置應用于某個特定的executable
?或?library
?組件 產生的所有二進制文件:
示例 54.12. 應用于“main”可執行組件所產生的所有二進制文件的設置
build.gradle
executables {main {binaries.all {if (toolChain in VisualCpp) {assembler.args "/Zi"} else {assembler.args "-g"}}} }
上面的例子將會把提供的配置應用到所有構建的?executable
二進制文件。
同樣,也可以為某種特定類型的組件,把設置指向目標二進制文件:例如所有main library
組件的shared libraries
。
當使用VisualCpp
工具鏈時,Gradle 時能夠編譯Window Resource (rc
) 文件并將它們鏈接到本地的二進制文件。這個功能是由'windows-resources'
?插件所提供的。
將 Windows 資源包含進本機二進制文件中,是通過一個WindowsResourceSet
提供的,它定義了一組Windows Resource源文件。默認情況下,WindowsResourceSet
為所有的命名組件包含了在src/${name}/rc
下的.rc
源文件。
與其他源文件類型一樣,您可以配置把windows 資源的位置包含進二進制文件中。
示例 54.15. 配置 Windows 資源源文件的位置
build-resource-only-dll.gradle
sources {helloRes {rc {source {srcDirs "src/hello/rc"}exportedHeaders {srcDirs "src/hello/headers"}}} }
你能夠通過提供沒有任何其他語言來源的 Windows Resource 源文件,來構造純資源庫,并適當地配置鏈接器︰
示例 54.16. 構建一個純資源 dll
build-resource-only-dll.gradle
libraries {helloRes {binaries.all {rcCompiler.args "/v"linker.args "/noentry", "/machine:x86"}} }
上面的示例還演示了將額外的命令行參數傳遞給資源編譯器的機制。rcCompiler
擴展是PreprocessingTool
類型。
C++ 項目的依賴是導出頭文件的二進制庫。這些頭文件在編譯期間使用,而編譯的二進制依賴則在鏈接過程中使用。
一組源文件可能依賴于在同一個項目中由另一個二進制組件提供的頭文件。一個常見的例子是一個本地可執行組件,使用了由一個單獨的本地庫組件提供的功能。
這樣的庫依賴可以很方便地提供給source set關聯上executable
組件。
另外,一個庫依賴項可以直接提供給ExecutableBinary
的executable
。
對于每個定義的可執行文件或庫,Gradle 能夠構建多個不同的本機二進制變種。這樣的例子包括debug及release的二進制文件,32位及64位的二進制文件,以及使用不同的自定義預處理標志生成的二進制文件。
Gradle 產生的二進制文件可以區分?構建類型,?平臺以及?flavor。對于這里的每一個“變種維度”,它可以指定一組可用的值,并且針對每個組件使用這里的一個或多個或全部的值。例如,一個插件可以定義一系列的支持平臺,但你可以選擇某個特定組件只構建Windows-x86平臺。
一個?build type
?確定了一個二進制文件的各種非功能性方面,比如是否包含調試信息,或者使用什么樣的優化級別來編譯二進制文件。典型的構建類型是“debug”和“release”,但一個project可以自由定義任意的構建類型。
如果在project中沒有定義任何構建類型,那么會有一個默認的“debug”構建類型被加進去。
對于一個構建類型,Gradle project 通常會定義一組每個工具鏈的編譯器/鏈接器標志。
示例 54.21. 配置debug二進制文件
build.gradle
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'} }
通過為每個平臺生成一個變種,能夠使一個可執行文件或庫構建為可以運行在不同的操作系統及CPU架構上。Gradle 把每一個系統架構組合定義為一個?Platform
,一個project可以定義多個platforms。如果在project里沒有定義任何平臺,那么會添加一個默認的“current”平臺。
Platform
由一個定義的操作系統和架構構成。隨著我們繼續開發 Gradle 的本地二進制支持,將擴展Platform的概念,包括 C-runtime版本,Windows SDK,ABI,等等。復雜的構建,可能使用 Gradle 的擴展性來把附加屬性應用到每個platform中,然后可以查詢為一個本地二進制包含了哪些特別指定的預處理器或者是編譯器參數。示例 54.22. 定義platform
build.gradle
model {platforms {x86 {architecture "x86"}x64 {architecture "x86_64"}itanium {architecture "ia-64"}} }
對于給定的變種,Gradle 將嘗試查找能夠構建目標平臺的ToolChain
。可用的工具鏈將按照定義的順序進行查找。更多的細節請參閱下面的工具鏈部分。
每個組件都可以有一組flavors
,并且能為每一個flavor生成一個單獨的二進制變種。在Gradle中?build type
?和?target platform
?變種維度是有一個確定的定義的,而每一個project都可以自由地定義數量的flavor并且用任何方式去應用它們的意義。
一個關于組件flavor的例子是可以區分組件的“demo”,“paid”和“enterprise”版本,它們都用同樣的源碼來生成不同功能的二進制文件。
示例 54.23. 定義flavors
build.gradle
model {flavors {englishfrench} }libraries {hello {binaries.all {if (flavor == flavors.french) {cppCompiler.define "FRENCH"}}source sources.lib} }
在上面的示例中,library 定義了“english”和“french”兩個flavor。當編譯“french”變種時,會定義一個單獨的宏,以產生不同的二進制文件。
如果一個組件沒有定義任何的flavor,那么會使用一個默認的“default”的flavor。
對于一個默認的組件, Gradle會嘗試為這個project所定義的每一個buildType
,?platform
?和?flavor
,以及它們的每一種組合,創建一個本地二進制變種。通過指定的?targetBuildTypes
,?targetPlatforms
?或?targetFlavors
,是可以在每一個組件的基礎上進行重寫的。
在這里你可以看到?TargetedNativeComponent.targetPlatforms()
?方法被用于為?executables.main
選擇一組平臺。
在選擇?TargetedNativeComponent.targetBuildTypes()
?and和TargetedNativeComponent.targetFlavors()
上也有類似的機制。
當為一個組件定義了一組構建類型,目標平臺,以及flavor時,將會為它們的每一種可能的組合創建一個NativeBinary
?模型元素。然而,在許多情況下是不可能構建一個特定的變種的,可能的原因是某個特定的平臺沒有可用的工具鏈。
如果一個二進制變種因為某些原因不能構建,那么與之關聯的NativeBinary
將不會是buildable
。可以用這個屬性來創建一個任務,生成在某一特定計算機上所有可能的變種。
一個構建可以使用不同的工具鏈來構建不同平臺的變種。為此,核心的“native-binary”將嘗試查找并使支持的工具鏈可用。不過,一個項目里的一組工具鏈也可以被顯示地定義,允許配置額外的交叉編譯器以及指定安裝目錄。
支持的工具鏈類型有︰
Gcc
Clang
VisualCpp
示例 54.26.?定義工具鏈
build.gradle
model {toolChains {visualCpp(VisualCpp) {// Specify the installDir if Visual Studio cannot be located by default// 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 將嘗試查找能夠構建目標平臺的ToolChain
。可用的工具鏈將按照定義的順序進行查找。
operatingSystem
定義一個值的話,Gradle 將會找到第一個可以用來構建這個指定architecture
的工具鏈。核心 Gradle 工具鏈針對以下的架構能夠開箱即用。在每種情況中,工具鏈將針對當前的操作系統。關于其他操作系統的交叉編譯的信息,可以參考下一節。
工具鏈 | 架構 |
GCC | x86, x86_64 |
Clang | x86, x86_64 |
Visual C++ | x86, x86_64, ia-64 |
所以對于linux上運行的GCC,支持的目標平臺是“linux/x86”和“linux/x86_64”。對于通過Cygwin運行在Windows上的GCC,則支持“windows/x86”和“windows/x86_64”。(Cywgin運行時還不能模擬為Platform的一部分,但以后將會實現。)
如果在project里沒有定義任何平臺,那么所有的二進制文件會針對一個默認平臺“current”進行構建。該默認平臺不指定任何architecture
或operatingSystem
的值,因此會使用第一個可用的工具鏈的默認值。
Gradle 可以為在你的構建中定義的本地組件生成生成 Visual Studio 項目及解決方案文件。這個功能是通過?visual-studio
?插件添加的。對于多項目構建,所有帶有本地組件的project都應該應用這個插件。
當應用?visual-studio
?插件后,會為每一個定義的組件創建一個名為?${component.name}VisualStudio
?的任務。這個任務會為所命名的組件生成一個 Visual Studio Solution 文件。這個方案包含了一個該組件的 Visual Studio Project ,并且為每一個依賴的二進制文件鏈接到項目文件中。
通過由visualStudio
?提供的編程hook,可以修改所生成的visual studio文件的內容, 更詳細的信息,可以參考“visual-studio”例子,或者參閱?VisualStudioExtension.getProjects()
?及?VisualStudioExtension.getSolutions()
?。
Gradle?cunit
?插件向你的native-binary項目提供了編譯及執行CUnit 測試的支持。對于在你的項目中定義的每一個?Executable
?和?Library
,Gradle將創建一個匹配的?CUnitTestSuite
?組件,名字為${component.name}Test
。
Gradle將為項目中的每一個?CUnitTestSuite
?組件創建一個名字為“cunit”的CSourceSet
。這個源碼集應包含組件源碼的 cunit 測試文件。源文件可以位于約定的位置(src/${component.name}Test/cunit
),或者是像其他源集一樣配置到別的地方。
初始化 CUnit 測試注冊以及執行這些測試的工作,都由 Gradle 通過一些生成的 CUnit 啟動器源碼來執行。Gradle 將認定和調用一個void gradle_cunit_register()
?函數,這個函數你可以用于配置實際的CUnit套件以及要執行的測試。
示例 54.27. 注冊 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); }
main
方法,因為這會與 Gradle 所提供的方法產生沖突。一個?CUnitTestSuite
?組件會有一個相關聯的?Executable
?或?Library
?組件。對于為main 組件配置的每一個ProjectNativeBinary
,在測試套件組件上都會配置一個匹配的?TestSuiteExecutableBinary
?。這些測試套件二進制文件可以以一種類似的方式配置到任何其他二進制的實例︰
示例 54.28. 注冊 CUnit 測試
build.gradle
binaries.withType(TestSuiteExecutableBinary) {lib library: "cunit", linkage: "static"if (flavor == flavors.failing) {cCompiler.define "PLUS_BROKEN"} }
TestSuiteExecutableBinary
提供。對于每個TestSuiteExecutableBinary
,Gradle 將創建一個任務來執行此二進制文件,這項任務將運行所有注冊的 CUnit 測試。生成的測試結果將位于
目錄。${build.dir}
/test-results
示例 54.29. 運行 CUnit 測試
build.gradle
apply plugin: "c" apply plugin: "cunit"model {flavors {passingfailing}repositories {libs(PrebuiltLibraries) {cunit {headers.srcDir "lib/cunit/2.1-2/include"binaries.withType(StaticLibraryBinary) {staticLibraryFile = file("lib/cunit/2.1-2/lib/" + findCUnitLibForPlatform(targetPlatform))}}}} }libraries {operators {} } binaries.withType(TestSuiteExecutableBinary) {lib library: "cunit", linkage: "static"if (flavor == flavors.failing) {cCompiler.define "PLUS_BROKEN"} }
注意︰?此示例的代碼可以在Gradle 的 binary 或 source 分發包的samples/native-binaries/cunit
中找到。。
> gradle -q runFailingOperatorsTestCUnitExeThere were test failures:1. /home/user/gradle/samples/native-binaries/cunit/src/operatorsTest/cunit/test_plus.c:6 - plus(0, -2) == -22. /home/user/gradle/samples/native-binaries/cunit/src/operatorsTest/cunit/test_plus.c:7 - plus(2, 2) == 4:runFailingOperatorsTestCUnitExe FAILEDBUILD FAILEDTotal time: 1 secs
當前對 CUnit 的支持還是相當簡陋。未來的集成計劃包括:
允許測試聲明為 javadoc 風格的注解。
改進 HTML 報告,類似于 JUnit 提供的那樣。
測試執行的的實時反饋。
支持另外的測試框架。