识别Gradle约定
通過約定進行配置具有許多優點,尤其是在簡潔方面,因為開發人員不需要顯式配置通過約定隱式配置的內容。 但是,在利用約定進行配置時,需要了解約定。 這些約定可能已經記錄在案,但是當我可以編程方式確定約定時,我總是喜歡它,因為文檔可能會過時(代碼背后的相同原理總是正確的,而注釋有時是正確的)。 我通過查看如何識別與Gradle Java Plugin關聯的特定約定開始本文。 然后,我對該方法進行一般化,以識別與與Gradle構建的根項目相關聯的所有任務相關聯的所有屬性。
Gradle插件上的Gradle文檔說明了以下有關Gradle插件的重要性以及它們對Gradle構建的補充:
Gradle的核心故意為現實世界的自動化提供了很少的有用功能。 插件添加了所有有用的功能,例如編譯Java代碼的功能。 插件添加新任務(例如JavaCompile),域對象(例如SourceSet),約定(例如主Java源位于src / main / java),以及擴展核心對象和其他插件的對象。
這篇文章介紹了Java插件為Gradle構建帶來的一些任務,域對象和約定。 首先,我需要一個非常簡單的Gradle構建文件。 它僅由應用Java插件的一行組成。 接下來顯示在Gradle構建文件build-java-plugin.gradle 。
build-java-plugin.gradle
apply plugin: 'java'有了該單行的Gradle構建文件,可以通過運行gradle -b build-java-plugin.gradle tasks命令輕松查看插件提供的Gradle gradle -b build-java-plugin.gradle tasks 。 接下來的兩個屏幕快照顯示了運行空的Gradle構建文件的輸出,以及僅使用Java插件的應用程序運行Gradle構建文件的輸出。
通過將運行Gradle“任務”的輸出與空構建文件的輸出與運行Gradle“任務”的構建文件與應用Java插件的輸出進行比較,我們可以看到Gradle具有相同的“ Build Setup Tasks”集。和“幫助任務”,無論是否應用了插件。 更重要的是,我們看到Java插件添加了許多新任務,這些任務分類為“構建任務”(匯編,構建,buildDependents,buildNeeded,類,clean,jar,testClasses),“文檔任務”(javadoc),“驗證任務”(檢查,測試)和“規則”。
我在Gradle 1.10中享受的一項功能是Gradle 1.8 (我使用的較早版本)沒有的功能是,可以在命令行中查詢特定Gradle任務的詳細信息 。 下一個屏幕快照展示了Java插件任務compileJava , jar和javadoc 。 通過在命令行上使用help --task <task_name>命令,所有這三個任務都有寫入標準輸出的詳細信息。 有關Java插件任務的這些詳細信息,也可以在Gradle用戶指南中找到 。
由于Gradle基于Groovy構建,因此使用“蠻力”確定Java插件的特性相當容易。 下一個代碼清單( build-java-plugin-properties.gradle )演示了如何使用Groovy確定Gradle屬性(可以用-P指定的那些,而不是用-D指定的系統屬性 ),該屬性可在構建腳本之前和之后使用。在應用Java插件之后,然后使用Groovy的高度方便的重寫減法運算符來查找差異。 Java插件添加到Gradle腳本的所有屬性的名稱和值(屬性“ properties”除外)按字母順序顯示。
// build-java-plugin-properties.gradle // // Displays properties that Gradle Java Plugin adds beyond properties already // specified for any Gradle build.def propertiesBefore = this.propertiesapply plugin: 'java'def propertiesAfter = this.propertiesdef extraProperties = propertiesAfter - propertiesBeforedef extraPropertiesKeys = new TreeSet<String>() extraProperties.each { property ->if (property.key != "properties"){extraPropertiesKeys.add(property.key)} }extraPropertiesKeys.each { key ->println "${key} : ${extraProperties.get(key)}" }下圖顯示了屏幕快照,其中包含運行此腳本的輸出。 屏幕快照未顯示完整的輸出,但是在圖像后的文本中顯示了較大的一部分輸出(所有屬性)。
從Gradle腳本上方運行以查看Java插件屬性的輸出
apiDocTitle : gradleExample API archivesBaseName : gradleExample assemble : task ':assemble' binaries : [classes 'main', classes 'test'] build : task ':build' buildDependents : task ':buildDependents' buildNeeded : task ':buildNeeded' buildTasks : [build] check : task ':check' classes : task ':classes' clean : task ':clean' compileJava : task ':compileJava' compileTestJava : task ':compileTestJava' defaultArtifacts : org.gradle.api.internal.plugins.DefaultArtifactPublicationSet_Decorated@bc80d8 dependencyCacheDir : C:\java\examples\groovyExamples\gradleExample\build\dependency-cache dependencyCacheDirName : dependency-cache distsDir : C:\java\examples\groovyExamples\gradleExample\build\distributions distsDirName : distributions docsDir : C:\java\examples\groovyExamples\gradleExample\build\docs docsDirName : docs inheritedScope : org.gradle.api.internal.ExtensibleDynamicObject$InheritedDynamicObject@c10304 jar : task ':jar' javadoc : task ':javadoc' libsDir : C:\java\examples\groovyExamples\gradleExample\build\libs libsDirName : libs manifest : org.gradle.api.java.archives.internal.DefaultManifest@1ad3677 metaInf : [] module : org.gradle.api.internal.artifacts.ProjectBackedModule@d2eead processResources : task ':processResources' processTestResources : task ':processTestResources' rebuildTasks : [clean, build] reporting : org.gradle.api.reporting.ReportingExtension_Decorated@33ab8f reportsDir : C:\java\examples\groovyExamples\gradleExample\build\reports reportsDirName : reports runtimeClasspath : file collection sourceCompatibility : 1.7 sourceSets : sources : [, ] status : integration targetCompatibility : 1.7 test : task ':test' testClasses : task ':testClasses' testReportDir : C:\java\examples\groovyExamples\gradleExample\build\reports\tests testReportDirName : tests testResultsDir : C:\java\examples\groovyExamples\gradleExample\build\test-results testResultsDirName : test-resultsGradle使用命令gradle properties可以輕松查看所有Gradle屬性,但是此命令行操作將顯示所有屬性,無論其來源(Gradle本身還是插件)。
Java插件添加到構建中的每個Gradle任務都有其自己的屬性集。 這些屬性可以在Gradle Build Language Reference中找到 。 該文檔的“ 任務類型”部分具有指向每種任務類型的鏈接。 每個任務類型的鏈接到頁面均包含該任務類型支持的屬性的詳細信息。 例如,任務類型JavaCompile在其頁面上列出為具有諸如classpath , destinationDir和source之 類的屬性。
以下相當廣泛的腳本顯示了compileJava,jar和javadoc Gradle Java Plugin任務的屬性設置。 該腳本演示了將Groovy應用于識別Gradle構建設置的強大功能。 如果使用更多的反射,該腳本可能會更短,但是明確地調用任務的屬性確實在讀取方面和作為每個任務可用屬性的參考方面具有優勢。
build-java-plugin-metadata.gradle
// build-java-plugin-metadata.gradle // // Displays the properties associated with the Gradle Java Plugin tasks // of "compileJava", "jar", and "javadoc".import groovy.transform.Fieldapply plugin: 'java'@Field int MAX_COLUMNS = 80 @Field String headerSeparator = "=".multiply(MAX_COLUMNS)printCompileJavaProperties() printJarProperties() printJavadocProperties()def printCompileJavaProperties() {printHeader("compileJava Task")println "compileJava.classpath:\n${extractStringRepresentation(compileJava.classpath)}"println "compileJava.destinationDir:\n${extractStringRepresentation(compileJava.destinationDir)}"println "compileJava.source:\n${extractStringRepresentation(compileJava.source)}"println "compileJava.options:\n${extractStringRepresentation(compileJava.options)}"println "compileJava.includes:\n${extractStringRepresentation(compileJava.includes)}"println "compileJava.excludes:\n${extractStringRepresentation(compileJava.excludes)}"println "compileJava.sourceCompatibility:\n${extractStringRepresentation(compileJava.sourceCompatibility)}"println "compileJava.targetCompatibility:\n${extractStringRepresentation(compileJava.targetCompatibility)}" }def printJarProperties() {printHeader("jar Task")println "jar.appendix:\n${extractStringRepresentation(jar.appendix)}"println "jar.archiveName:\n${extractStringRepresentation(jar.archiveName)}"println "jar.archivePath:\n${extractStringRepresentation(jar.archivePath)}"println "jar.baseName:\n${extractStringRepresentation(jar.baseName)}"println "jar.caseSensitive:\n${extractStringRepresentation(jar.caseSensitive)}"println "jar.classifier:\n${extractStringRepresentation(jar.classifier)}"println "jar.destinationDir:\n${extractStringRepresentation(jar.destinationDir)}"println "jar.dirMode:\n${extractStringRepresentation(jar.dirMode)}"println "jar.duplicatesStrategy:\n${extractStringRepresentation(jar.duplicatesStrategy)}"println "jar.entryCompression:\n${extractStringRepresentation(jar.entryCompression)}"println "jar.excludes:\n${extractStringRepresentation(jar.excludes)}"println "jar.extension:\n${extractStringRepresentation(jar.extension)}"println "jar.fileMode:\n${extractStringRepresentation(jar.fileMode)}"println "jar.includeEmptyDirs:\n${extractStringRepresentation(jar.includeEmptyDirs)}"println "jar.includes:\n${extractStringRepresentation(jar.includes)}"println "jar.manifest:\n${extractStringRepresentation(jar.manifest)}"println "jar.source:\n${extractStringRepresentation(jar.source)}"println "jar.version:\n${extractStringRepresentation(jar.version)}" }def printJavadocProperties() {printHeader("javadoc Task")println "javadoc.classpath:\n${extractStringRepresentation(javadoc.classpath)}"println "javadoc.destinationDir:\n${extractStringRepresentation(javadoc.destinationDir)}"println "javadoc.excludes:\n${extractStringRepresentation(javadoc.excludes)}"println "javadoc.executable:\n${extractStringRepresentation(javadoc.executable)}"println "javadoc.failOnError:\n${extractStringRepresentation(javadoc.failOnError)}"println "javadoc.includes:\n${extractStringRepresentation(javadoc.includes)}"println "javadoc.maxMemory:\n${extractStringRepresentation(javadoc.maxMemory)}"println "javadoc.options:\n${extractStringRepresentation(javadoc.options)}"println "javadoc.source:\n${extractStringRepresentation(javadoc.source)}"println "javadoc.title:\n${extractStringRepresentation(javadoc.title)}" }def String extractStringRepresentation(Object object) {String returnStringif (object in String){returnString = "\t${object}\n"}else if (object in File){returnString = "\t${object.canonicalPath}\n"}else if (object in FileCollection) // FileTree is a FileCollection{StringBuilder filesStr = new StringBuilder()def files = object.filesfiles.each{ file ->filesStr << "\t" << file.canonicalPath << "\n" }returnString = filesStr.toString()}else if (object in CompileOptions){StringBuilder compileOptionsStr = new StringBuilder()def compileProperties = object.propertiescompileProperties.each{ compileProperty ->if (compileProperty.value in DebugOptions){compileOptionsStr << "\t" << compileProperty.key << ": " << extractStringRepresentation(compileProperty.value) << "\n"}else if (compileProperty.value in DependOptions){compileOptionsStr << "\t" << compileProperty.key << ": " << extractStringRepresentation(compileProperty.value) << "\n"}else if (compileProperty.value in ForkOptions){compileOptionsStr << "\t" << compileProperty.key << ": " << extractStringRepresentation(compileProperty.value) << "\n"}else if (compileProperty.key != "class"){compileOptionsStr << "\t" << compileProperty.key << ": " << compileProperty.value << "\n"} }returnString = compileOptionsStr.toString()}else if (object in DebugOptions){returnString = "\t${object.debugLevel}"}else if (object in DependOptions){returnString = "\t${object.classpath}"}else if (object in ForkOptions){returnString = "\t${object.executable} executable with ${object.tempDir} temp directory" }else if (object in Set || object in Boolean || object in Number || object in Enum){returnString = "\t${object.toString()}\n"}else if (object in Manifest){StringBuilder manifestStr = new StringBuilder()def manifestAttributes = object.getAttributes()manifestAttributes.each{ manifestAttribute ->manifestStr << "\t" << manifestAttribute.key << ": " << manifestAttribute.value << "\n" }returnString = manifestStr.toString()}else if (object in MinimalJavadocOptions){returnString = extractJavadocOptionsAsString(object)}else if (object == null){returnString = "\tnull\n"}else{returnString = "\t${object?.class} was unexpected type.\n"}return returnString }def String extractJavadocOptionsAsString(MinimalJavadocOptions javadocOptions) {StringBuilder javadocOptionsStr = new StringBuilder()javadocOptionsStr << "\tjavadoc.bootClasspath:"def bootClasspathFiles = javadocOptions.bootClasspathbootClasspathFiles.each{ bootClasspathFile ->javadocOptionsStr << "\t\t" << bootClasspathFile.canonicalName << "\n" }javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.classpath:"def classpathFiles = javadocOptions.classpathclasspathFiles.each{ classpathFile ->javadocOptionsStr << "\t\t" << classpathFile.canonicalName << "\n"}javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.destinationDirectory: " << javadocOptions.destinationDirectory?.canonicalName << "\n"javadocOptionsStr << "\tjavadocOptions.doclet: " << javadocOptions.doclet << "\n"javadocOptionsStr << "\tjavadocOptions.docletpath:"def docletpath = javadocOptions.docletpathdocletpath.each{ docletEntry ->javadocOptionsStr << "\t\t" << docletEntry.canonicalName << "\n"}javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.encoding: " << javadocOptions.encoding << "\n"javadocOptionsStr << "\tjavadocOptions.extDirs:"def extDirs = javadocOptions.extDirsextDirs.each{ extDir ->javadocOptionsStr << "\t\t" << extDir.canonicalName << "\n"}javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.header: " << javadocOptions.header << "\n"javadocOptionsStr << "\tjavadocOptions.JFlags:"def jflags = javadocOptions.JFlagsjflags.each{ jflag ->javadocOptionsStr << "\t\t" << jflag << "\n"}javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.locale: " << javadocOptions.locale << "\n"javadocOptionsStr << "\tjavadocOptions.memberLevel: " << javadocOptions.memberLevel << "\n"javadocOptionsStr << "\tjavadocOptions.optionFiles:"def optionFiles = javadocOptions.optionFilesoptionFiles.each{ optionFile ->javadocOptionsStr << "\t\t" << optionFile.canonicalName << "\n"}javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.outputLevel: " << javadocOptions.outputLevel << "\n"javadocOptionsStr << "\tjavadocOptions.overview: " << javadocOptions.overview << "\n"javadocOptionsStr << "\tjavadocOptions.source: " << javadocOptions.source << "\n"javadocOptionsStr << "\tjavadocOptions.sourceNames:"def sourceNames = javadocOptions.sourceNamessourceNames.each{ sourceName ->javadocOptionsStr << "\t\t" << sourceName << "\n"}javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.windowTitle: " << javadocOptions.windowTitle << "\n"return javadocOptionsStr.toString() }def printHeader(String headerText) {println headerSeparatorprintln "= ${headerText.center(MAX_COLUMNS-4)} ="println headerSeparator }我在此構建文件中使用了Groovy @Field批注 ,以使對其應用到的變量可用于構建文件中的方法。 @Field注釋直到Groovy 1.8才可用,這使我想起了有關Gradle和Groovy的其他重要信息:Gradle使用其自己的預包裝Groovy,而不是可能在自己的計算機上安裝的任何其他版本的Groovy。 您可以使用gradle --version命令確定哪個版本的Groovy。 下一個屏幕快照展示了我的Groovy版本( 2.1.6 ) 與我的Gradle安裝(版本1.10)使用的Groovy版本(1.8.6)不同。 因為Gradle 1.10隨Groovy 1.8.6一起提供 ,所以我可以使用@Field注釋 。
由于最后一個腳本的輸出太長了,因此我在這里將其顯示為文本而不是圖像。
在build-java-plugin-metadata.gradle上運行Running Gradle的輸出
================================================================================ = compileJava Task = ================================================================================ compileJava.classpath:compileJava.destinationDir:C:\java\examples\groovyExamples\gradleExample\build\classes\maincompileJava.source:C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main2.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main3.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main4.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Temperature.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureScale.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureUnit.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureUnit2.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureUnit3.javacompileJava.options:bootClasspath: nullfork: falseencoding: nulldeprecation: falsewarnings: trueforkOptions: null executable with null temp directoryfailOnError: trueuseDepend: falseincludeJavaRuntime: falseuseAnt: falsecompilerArgs: []debug: trueextensionDirs: nullcompiler: nulldebugOptions: nullverbose: falseoptimize: falsedependOptions: listFiles: falsecompileJava.includes:[]compileJava.excludes:[]compileJava.sourceCompatibility:1.7compileJava.targetCompatibility:1.7================================================================================ = jar Task = ================================================================================ jar.appendix:nulljar.archiveName:gradleExample.jarjar.archivePath:C:\java\examples\groovyExamples\gradleExample\build\libs\gradleExample.jarjar.baseName:gradleExamplejar.caseSensitive:truejar.classifier:jar.destinationDir:C:\java\examples\groovyExamples\gradleExample\build\libsjar.dirMode:nulljar.duplicatesStrategy:INCLUDEjar.entryCompression:DEFLATEDjar.excludes:[]jar.extension:jarjar.fileMode:nulljar.includeEmptyDirs:truejar.includes:[]jar.manifest:Manifest-Version: 1.0jar.source:C:\java\examples\groovyExamples\gradleExample\build\tmp\jar\MANIFEST.MFjar.version:null================================================================================ = javadoc Task = ================================================================================ javadoc.classpath:C:\java\examples\groovyExamples\gradleExample\build\classes\mainC:\java\examples\groovyExamples\gradleExample\build\resources\mainjavadoc.destinationDir:C:\java\examples\groovyExamples\gradleExample\build\docs\javadocjavadoc.excludes:[]javadoc.executable:nulljavadoc.failOnError:truejavadoc.includes:[]javadoc.maxMemory:nulljavadoc.options:javadoc.bootClasspath:javadocOptions.classpath:javadocOptions.destinationDirectory: nulljavadocOptions.doclet: nulljavadocOptions.docletpath:javadocOptions.encoding: nulljavadocOptions.extDirs:javadocOptions.header: nulljavadocOptions.JFlags:javadocOptions.locale: nulljavadocOptions.memberLevel: nulljavadocOptions.optionFiles:javadocOptions.outputLevel: QUIETjavadocOptions.overview: nulljavadocOptions.source: nulljavadocOptions.sourceNames:javadocOptions.windowTitle: nulljavadoc.source:C:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main2.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main3.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Main4.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\Temperature.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureScale.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureUnit.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureUnit2.javaC:\java\examples\groovyExamples\gradleExample\src\main\java\dustin\examples\TemperatureUnit3.javajavadoc.title:gradleExample API:helpWelcome to Gradle 1.10.To run a build, run gradle ...To see a list of available tasks, run gradle tasksTo see a list of command-line options, run gradle --helpBUILD SUCCESSFULTotal time: 14.041 secs上面顯示的示例可以很好地識別與Java Gradle插件關聯的特定屬性。 這很好用,但是它的局限性包括需要為每個需要其值的屬性編寫顯式代碼。 這意味著沒有必要知道所有可用屬性的進一步限制(我使用文檔在上面的示例中顯式輸出了值)。 進一步暗示的限制是,上面的腳本將來將不會顯示添加到這些任務的任何屬性值。 下一個Gradle構建示例基于先前的示例,但是此示例未明確聲明要顯示的任務和屬性。 而是查找與根項目關聯的所有任務,然后打印與每個任務關聯的所有屬性。
構建java插件元數據反射.gradle
// build-java-plugin-metadata-reflection.gradle // // Displays the properties associated with the tasks associated with the Gradle // root project. //import groovy.transform.Fieldapply plugin: 'java'@Field int MAX_COLUMNS = 80 @Field String headerSeparator = "=".multiply(MAX_COLUMNS)def rootProject = getRootProject() def tasks = rootProject.tasks tasks.each { task ->printTaskProperties(task) }def printTaskProperties(Task task) {printHeader("Task " + task.name)def taskProperties = task.propertiestaskProperties.each{ taskProperty ->println "${task.name}.${taskProperty.key}=${extractStringRepresentation(taskProperty.value)}"} }def String extractStringRepresentation(Object object) {String returnStringif (object in String){returnString = "\t${object}\n"}else if (object in File){returnString = "\t${object.canonicalPath}\n"}else if (object in FileCollection) // FileTree is a FileCollection{StringBuilder filesStr = new StringBuilder()def files = object.filesfiles.each{ file ->filesStr << "\t" << file.canonicalPath << "\n" }returnString = filesStr.toString()}else if (object in CompileOptions){StringBuilder compileOptionsStr = new StringBuilder()def compileProperties = object.propertiescompileProperties.each{ compileProperty ->if (compileProperty.value in DebugOptions){compileOptionsStr << "\t" << compileProperty.key << ": " << extractStringRepresentation(compileProperty.value) << "\n"}else if (compileProperty.value in DependOptions){compileOptionsStr << "\t" << compileProperty.key << ": " << extractStringRepresentation(compileProperty.value) << "\n"}else if (compileProperty.value in ForkOptions){compileOptionsStr << "\t" << compileProperty.key << ": " << extractStringRepresentation(compileProperty.value) << "\n"}else if (compileProperty.key != "class"){compileOptionsStr << "\t" << compileProperty.key << ": " << compileProperty.value << "\n"} }returnString = compileOptionsStr.toString()}else if (object in DebugOptions){returnString = "\t${object.debugLevel}"}else if (object in DependOptions){returnString = "\t${object.classpath}"}else if (object in ForkOptions){returnString = "\t${object.executable} executable with ${object.tempDir} temp directory" }else if (object in Set || object in List || object in Boolean || object in Number || object in Enum || object in Class){returnString = "\t${object.toString()}\n"}else if (object in Manifest){StringBuilder manifestStr = new StringBuilder()def manifestAttributes = object.getAttributes()manifestAttributes.each{ manifestAttribute ->manifestStr << "\t" << manifestAttribute.key << ": " << manifestAttribute.value << "\n" }returnString = manifestStr.toString()}else if (object in MinimalJavadocOptions){returnString = extractJavadocOptionsAsString(object)}else if (object in Convention){StringBuilder conventionStr = new StringBuilder()object.plugins.each?.keyset{ plugin ->conventionStr << "\t" << plugin << "\n"}returnString = conventionStr.toString()}else if (object in LoggingManager){returnString = "\n\tCurrent Log Level: ${object.level}\n\tStandard Error: ${object.standardErrorCaptureLevel}\n\tStandard Output: ${object.standardOutputCaptureLevel}\n"}else if (object == null){returnString = "\tnull\n"}else{returnString = "\t${object?.class} was unexpected type with value of ${object}.\n"}return returnString }def String extractJavadocOptionsAsString(MinimalJavadocOptions javadocOptions) {StringBuilder javadocOptionsStr = new StringBuilder()javadocOptionsStr << "\tjavadoc.bootClasspath:"def bootClasspathFiles = javadocOptions.bootClasspathbootClasspathFiles.each{ bootClasspathFile ->javadocOptionsStr << "\t\t" << bootClasspathFile.canonicalName << "\n" }javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.classpath:"def classpathFiles = javadocOptions.classpathclasspathFiles.each{ classpathFile ->javadocOptionsStr << "\t\t" << classpathFile.canonicalName << "\n"}javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.destinationDirectory: " << javadocOptions.destinationDirectory?.canonicalName << "\n"javadocOptionsStr << "\tjavadocOptions.doclet: " << javadocOptions.doclet << "\n"javadocOptionsStr << "\tjavadocOptions.docletpath:"def docletpath = javadocOptions.docletpathdocletpath.each{ docletEntry ->javadocOptionsStr << "\t\t" << docletEntry.canonicalName << "\n"}javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.encoding: " << javadocOptions.encoding << "\n"javadocOptionsStr << "\tjavadocOptions.extDirs:"def extDirs = javadocOptions.extDirsextDirs.each{ extDir ->javadocOptionsStr << "\t\t" << extDir.canonicalName << "\n"}javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.header: " << javadocOptions.header << "\n"javadocOptionsStr << "\tjavadocOptions.JFlags:"def jflags = javadocOptions.JFlagsjflags.each{ jflag ->javadocOptionsStr << "\t\t" << jflag << "\n"}javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.locale: " << javadocOptions.locale << "\n"javadocOptionsStr << "\tjavadocOptions.memberLevel: " << javadocOptions.memberLevel << "\n"javadocOptionsStr << "\tjavadocOptions.optionFiles:"def optionFiles = javadocOptions.optionFilesoptionFiles.each{ optionFile ->javadocOptionsStr << "\t\t" << optionFile.canonicalName << "\n"}javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.outputLevel: " << javadocOptions.outputLevel << "\n"javadocOptionsStr << "\tjavadocOptions.overview: " << javadocOptions.overview << "\n"javadocOptionsStr << "\tjavadocOptions.source: " << javadocOptions.source << "\n"javadocOptionsStr << "\tjavadocOptions.sourceNames:"def sourceNames = javadocOptions.sourceNamessourceNames.each{ sourceName ->javadocOptionsStr << "\t\t" << sourceName << "\n"}javadocOptionsStr << "\n"javadocOptionsStr << "\tjavadocOptions.windowTitle: " << javadocOptions.windowTitle << "\n"return javadocOptionsStr.toString() }def printHeader(String headerText) {println headerSeparatorprintln "= ${headerText.center(MAX_COLUMNS-4)} ="println headerSeparator }因為此輸出是針對與Gradle構建的根項目相關聯的所有Tasks相關的所有屬性,所以輸出太長而無法在此處包含。 并非所有的屬性值實例都具有extractStringRepresentation(Object object)方法準備處理的類,但是可以將這些情況添加到該方法的if-else if結構中以進行處理。 此版本的Gradle構建比早期版本更通用,并打印出與Task關聯的屬性,這些屬性按Task分組。
由于Gradle構建與Groovy緊密耦合,因此可以使用Groovy語法和功能來了解有關Gradle構建的更多信息。 這篇文章中的示例利用了許多Groovy的優點。 上面的Gradle構建代碼之所以如此冗長,是因為大多數用于屬性值的Gradle類都沒有重寫toString()方法,因此,如果沒有特殊的代碼來調用特定的方法來獲得有用的表示,就不會顯示出真正有用的輸出 。 在本文的示例中我沒有這樣做,但是要解決缺少覆蓋的toString()方法的另一種方法是使用Groovy的攔截功能 ( metaClass.invokeMethod )攔截對toString()調用并提供覆蓋的版本。 那將基本上與上面使用的代碼相同,但是將被封裝在攔截對象中,而不是包含在腳本代碼中。
結論
Gradle確實有很好的文檔(特別是Gradle用戶指南和Gradle構建語言參考 ),并且可以從該文檔中輕松訪問與Java Plugin for Gradle(和其他插件)相關的大多數任務和屬性。 但是,我想知道如何以編程方式識別重要的約定,以防萬一文檔被誤解,或者我使用的版本與文檔所支持的版本不同。 這篇文章的另一個目的是演示與Gradle合作時了解Groovy的有用性。 出于這個原因,我相信Gradle日益重要的地位不免會增加對Groovy的興趣。
翻譯自: https://www.javacodegeeks.com/2014/01/identifying-gradle-conventions.html
總結
以上是生活随笔為你收集整理的识别Gradle约定的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux网络命令详解(linux网络
- 下一篇: 项目学生:业务层