如何在gradle插件中添加自定义依赖关系处理程序?

时间:2014-08-08 20:39:43

标签: gradle

我想为gradle插件的用户提供添加所有必需依赖项的简单方法。像gradleApi()localGroovy()之类的东西。

我发现gradleApi和localGroovy都在DependencyHandler中定义并在DefaultDependencyHandler中实现。我可以在我的插件中提供Dependencyhandler的自定义实现,扩展DefaultDependencyHandler吗?或者是否有更简单的方法来实现我想要的目标?

提前thx。

3 个答案:

答案 0 :(得分:10)

一种解决方案是让插件在dependencies容器上安装额外的方法:

def jarDir = ...

project.dependencies.ext.pluginDeps = { 
    project.fileTree(jarDir) // filter file tree if necessary 
}

用户可以这样做:

dependencies {
    compile pluginDeps()
}

额外的属性/方法通常仅用于构建脚本(因为它们不受可以发现和推理的模型的支持),但在这种特殊情况下(从Gradle 2.1开始)我无法想出一个明显更好的解决方案。

PS:请记住,对于基于文件(而非基于存储库)的依赖项,不会发生版本冲突解决。

答案 1 :(得分:0)

看看这在某种程度上是否有帮助。我们假设您创建了一个自定义插件/类并使用它在Gradle中的工件(在GRADLE_HOME / init.d / common.gradle文件级别内)。

自定义插件项目的java / groovy文件看起来像

// Your custom plugin class file will look like
// Your custom plugin's source code will reside at: com.mycustom.plugin.gradle under src/main/java folder tree. 
package com.mycustom.plugin.gradle
import org.gradle.api.*
import org.gradle.api.file.*

import java.io.File;

public class myCustomFileUtil {
    /**
     * Default constructor
     */
   public myCustomFileUtil() {
   }

   /**
    * Read file returning list of lines. Double slash (//) at start of line
    * defines a comment.
    * @param fileName File to read.
    * @return List of lines.
    */
    public static List readIntoList( String fileName ) {
      def fname = new File( fileName )
        def listFinal = []
        def listLines = fname.readLines()
        listLines.each { it ->
            def str = it.trim();
            if( str.length() > 0 ) {
                if( ! str.startsWith( "//" ) ) listFinal.add( str );
            }
      }
        return listFinal
    }
}

在build.gradle中

// The following funcationality is coming from a custom plugin that you'll write which will read a text file and create a list.
// It'll also ignore any lines that start with "//"
import com.mycustom.plugin.gradle.myCustomFileUtil

sourceSets {

   //if you have any
   //main
   //test
   //acceptanceTest
   //etc

}

// Read dependency lists from external files
List depListCompile = myCustomFileUtil.readIntoList( "$projectDir/dep-compile.txt" )
List depListTest = myCustomFileUtil.readIntoList( "$projectDir/dep-testArtifacts.txt" )
List depListWar = myCustomFileUtil.readIntoList( "$projectDir/dep-war.txt" )
List depListJibx = myCustomFileUtil.readIntoList( "$projectDir/dep-jibx.txt" )
List depListSomeOperationINeed = myCustomFileUtil.readIntoList( "$projectDir/dep-someoperationineed.txt" )


// Define dependencies
dependencies {
   // Compilation
   compile  depListCompile

   // If dependencies already exist on the local folder / in some workspace
   compile  fileTree(srcDir: "somefolder/whichcontain/myjar", include: "*.jar")
   compile  fileTree(srcDir: "/path/xx/yy/somefolder/whichcontain/myotherartifacts", include: "*.[zw]*")
   compile  fileTree(srcDir: "C:/zzz/somefolder/whichcontain", include: "myotherartifacts/*.[pj]*")

   // Unit Tests
   testCompile depListTest

   // Acceptance tests
   // Everything from compile and testCompile targets
   acceptanceTestCompile configurations.compile
   acceptanceTestCompile configurations.testCompile

   // Output of compiling "main" files
   acceptanceTestCompile sourceSets.main.output

   // Additional dependencies from war and others
   acceptanceTestCompile depListTest, depListWar

   // All configuration files
   acceptanceTestRuntime files( 'conf' )
}
// ... and more code here to do other operations

在dep-compile.txt中,您可以输入

等条目
com.mycompany.project:oneofmycompanyartifact1:1.1.1
com.mycompany.project:oneofmycompanyartifact2:1.0.1@zip

httpunit:httpunit:1.6
jibx:jibx-bind:0.10.3.3
jibx:jibx-extras:0.10.3.3
jibx:jibx-run:0.10.3.3

cactus:cactus:1.7.2
selenium:selenium:0.9.2

同样,在dep-testArtifacts.txt中,您可以拥有以下条目(并根据所需的Gradle阶段/功能创建类似的dep-XXXX文件:compile,test,war,doingSomeOperation等)。

cactus:cactus:1.7.2
jackson-all:jackson-all:1.9.9
jibx:jibx-bind:0.10.3.3
jibx:jibx-extras:0.10.3.3
jibx:jibx-run:0.10.3.3
//junit:junit:4.10
junit:junit:4.11
mockito-all:mockito-all:1.9.5

答案 2 :(得分:0)

我找到了另一种方法。您可以依靠约定机制来做到这一点。首先定义一个约定类:

class CustomDepsPluginConvention {
    // here you can return anything which configuration methods in the
    // `dependencies` block would accept, e.g. a string or a map
    fun customDependency(): Map<String, String> {
        return mapOf(
            "group" to "com.whatever",
            "name" to "whatever",
            "version" to "1.2.3"
        )
    }
}

然后使用插件apply()方法将此约定对象添加到项目中:

open class CustomDepsPlugin : Plugin<Project> {
    override fun apply(project: Project) {
        // the identifier of the convention object does not matter,
        // as long as it is unique
        project.convention.plugins["customDeps"] = CustomDepsPluginConvention()
    }
}

应用此插件后,约定对象将被添加到项目对象,将其所有方法和属性公开在项目对象上,从而使它们可直接在构建脚本中使用:

apply plugin: CustomDepsPlugin

dependencies {
    compile customDependency()
}

可以说这种方法更清洁;唯一的潜在缺点是约定对象已被“弃用”,不建议使用。同样,这可能会导致Kotlin DSL出现问题(据我所知,Kotlin DSL并不真正支持约定对象);但是,如果您想支持Kotlin DSL,则可以将这些依赖关系生成功能公开为可导入的顶级功能,并将其导入到您的构建脚本中。