1
votes

I read many good things about gradle so I get impressed. Many people are enthusiastic how easy is to develop with gradle. They all emphasize the multi-project capabilies of gradle.

I already have a main project with some subprojects. The outside dependencies are defined in all the project's own ivy.xml. And the module interdependencies are defined in both eclipse's .classpath file and ant build.xml parallelly. This way i can build for IDE and can create a runtime with ant. Is there a simple way to migrate the same build structure from eclipse/ant and ivy to gradle (or gradle + ivy)?

The build process is simple:

  1. Resolve the subproject's dependencies from ivy.xml
  2. Build the subproject
  3. (repeat 1 and 2 for all the subprojects)
  4. Resolve the dependencies for main project (both from ivy and eclipse/ant config)
  5. Build main project
  6. Package everything into one jar file

Not rocket science... but it took many days to implement it in ant. Is that really a simple to migrate that to gradle? If yes, what are the starting points?

I see that there is an eclipse plugin, but I see only the possibility to generate .classpath, not to parse/read it. I see an Ivy XML plugin too. It is not clear for me how to handle dependent projects/modules?

Any help is welcome.

Regards: Bence

2

2 Answers

3
votes

If you don't have a lot of custom ant tasks and just need to convert your ivy dependencies, this will create gradle dependencies from your ivy.xml. Paste into an empty build.gradle alongside your ivy.xml and run gradle ivyToGradle. Then copy the output into your build.gradle file. Requires gradle 2.12+ due to use of the compileOnly configuration.

This will not handle all possible ivy.xml settings, you may need to tweak to your particular use of ivy.xml. It handles basics such as runtime configs, test configs, compile-only configs, global exclusions, transitive true/false, and version forcing.

task ivyToGradle {
    description "Converts dependencies in ivy.xml to gradle dependencies."
    doLast {
        def ivyModule = new XmlParser().parse(new File("$projectDir/ivy.xml"))
        if (!ivyModule.dependencies.exclude.isEmpty() || !ivyModule.dependencies.override.isEmpty()) {
            println "configurations.runtime {"
            ivyModule.dependencies.exclude.each {
                def excludeStrs = []
                if (it.@org != null) {
                    excludeStrs.add("group: '${it.@org}'")
                }
                if (it.@module != null) {
                   excludeStrs.add("module: '${it.@module}'")
                }
                if (!excludeStrs.isEmpty()) {
                    def excl = excludeStrs.join(", ")
                    println "    exclude ${excl}"
                }
            }
            def overrides = ivyModule.dependencies.override.findResults {
                if ("exact" != it.@matcher) {
                    return null
                }
                if (!it.@org || !it.@module || !it.@rev) {
                    return null
                }
                return "        '${it.@org}:${it.@module}:${it.@rev}'"
            }
            if (overrides) {
                println "    resolutionStrategy.force("
                println overrides.join(",\n")
                println "    )"
            }
            println "}"
            println ""
        }
        println("dependencies {")
        ivyModule.dependencies.dependency.each {
            def transitive = ("false" != it.@transitive)
            def force = ("true" == it.@force)
            def scope = "compileOnly" // Requires gradle 2.12 or later
            if (it.@conf?.contains("test")) {
                scope = "testCompile"
            } else if (it.@conf?.contains("runtime")) {
                scope = "compile"
            }
            def hasBlock = !it.exclude.isEmpty() || !transitive || force
            if (hasBlock) {
                println "    $scope('${it.@org}:${it.@name}:${it.@rev}') {"
                it.exclude.each {
                    def excludeStrs = []
                    if (it.@org != null) {
                        excludeStrs.add("group: '${it.@org}'")
                    }
                    if (it.@module != null) {
                       excludeStrs.add("module: '${it.@module}'")
                    }
                    if (!excludeStrs.isEmpty()) {
                        def excl = excludeStrs.join(", ")
                        println "        exclude ${excl}"
                    }
                }
                if (!transitive) {
                    println "        transitive = false"
                }
                if (force) {
                    println "        force = true"
                }
                println "    }"
            } else {
                println "    $scope '${it.@org}:${it.@name}:${it.@rev}'"
            }
        }
        println("}")
        println ""
    }
}
1
votes

You'll have to migrate the build manually, translating the build.xml's and ivy.xml's into Gradle's build language. (There is an Ant import feature, but it's not particularly useful in practice.) Where necessary you can easily reuse Ant tasks. You can import a Gradle build into Eclipse using the Eclipse Gradle plugin, or generate Eclipse files using the Gradle Eclipse plugin. A good start is to study the first several chapters of the Gradle User Guide, followed by the chapters on Ant integration and multi-project builds. The full Gradle distribution ships with many sample builds.