Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managing project dependencies with Gradle and IntelliJ

I am looking to use Gradle to build my Groovy / Grails based project for which we are using IntelliJ Idea as the IDE.

I am using IntelliJ version 11.1.4, Gradle version 1.2.

My project is a configured as a multi project build with various Groovy & Grails subprojects.

I was hoping that this would give me the same kind of IDE support that I would get if managing the build through Maven, such as:

  • Automatic dependency management (import new dependencies to IntelliJ when added to various build.gradle)
  • Build DSL support
  • Execution of build tasks
  • Use of the underlying build system (gradle) by the IDE when performing builds\

I have imported my project into IntelliJ by opening the root build.gradle file.

So far I am coming up against a few annoying problems:

  1. IntelliJ is not recognising (or recognising randomly) changes to dependencies in the build.gradle files and therefore dependencies are not being updated.
  2. The gradle "idea" plugin doesn't seem to work with multi module projects.

How are people working with Gradle inside IntelliJ? Are you managing dependencies manually within IntelliJ??

like image 827
Chris Prior Avatar asked Nov 05 '12 16:11

Chris Prior


People also ask

How do I sync a project with Gradle files in IntelliJ?

If you have some custom plugins that require you to import your project from the IntelliJ IDEA model, press Ctrl+Shift+A and search for the Project from Existing Sources action. In the dialog that opens, select a directory containing a Gradle project and click OK. IntelliJ IDEA opens and syncs the project in the IDE.

How do I sync Gradle with dependencies?

Simply open the gradle tab (can be located on the right) and right-click on the parent in the list (should be called "Android"), then select "Refresh dependencies".

What is Gradle dependency management?

In most cases, a project relies on reusable functionality in the form of libraries or is broken up into individual components to compose a modularized system. Dependency management is a technique for declaring, resolving and using dependencies required by the project in an automated fashion.

Is Gradle a dependency management tool?

Gradle has built-in support for dependency management and lives up to the task of fulfilling typical scenarios encountered in modern software projects.


2 Answers

I have been using Gradle "idea" plugin for some time now and it works very well. Since "idea" plugin simply generates IntelliJ project configuration files it is somewhat limited in what you can do with it, but nevertheless, I have had more success with it compared to the IntelliJ gradle support (JetGradle thing).

Gradle "idea" plugin does work with multi-module projects, never had a problem with that. I always put parent project configuration in master folder (see Initialization chapter), which seems to work. Never tried the nested structure though.

In order to do additional IntelliJ configuration you can do some .ipr and .iml tinkering from gradle, or alternatively try using one of my plugins (see Utilities plugin) which will do most of the tinkering for you.

like image 179
rodion Avatar answered Nov 03 '22 02:11

rodion


In the end I went with rodion's suggestion above and used the idea plugin. It turns out I had not configured it properly first time I tried it (only applied the plugin to the master project, not subprojects).

I only found this out after writing my own task to update the dependencies for an IntelliJ project (based on the .idea directory layout project structure). I am going to use the plugin as there will be less maintenance, but here is my solution for posterity and in case it is useful to anyone:

ext {
    intelliJLibraryDir = "$gradle.rootProject.rootDir/.idea/libraries"
    userHomeDir = gradle.gradleUserHomeDir.parent
}


task cleanIntelliJLibraries << {
    ant.delete (includeEmptyDirs: 'true') { 
        fileset(dir: intelliJLibraryDir, includes: '*.xml') 
    }
}


task createIntelliJLibraries(dependsOn: cleanIntelliJLibraries) << {

    // The unique set of dependency artifacts across all subprojects
    def uniqueProjectArtifacts = subprojects.collectMany {
        if (it.configurations.compile) {
            it.configurations.compile.resolvedConfiguration.resolvedArtifacts.findAll { 
                it.moduleVersion.id.group != "my.project" 
            }
        }
        else { [] }
    }.unique()

    // Output a library xml file for each of the dependency artifacts
    uniqueProjectArtifacts.each { artifact ->

        def artifactPath = artifact.file.path                       
        def artifactName = artifact.moduleVersion.id.with { "$group:$name:$version" }

        def intelliJLibraryPath = artifactPath.replace(userHomeDir, '$USER_HOME$')                  
        def intelliJLibraryFileName = "Gradle__$artifactName".replace(':', '_').replace('.','_') + ".xml"

        new File("$intelliJLibraryDir/$intelliJLibraryFileName").withWriter { writer ->

            def dependencyXML = new MarkupBuilder( writer )

            dependencyXML.component (name: "libraryTable") {
                library (name: "Gradle: $artifactName") {
                    CLASSES {
                        root (url: "jar://$intelliJLibraryPath!/")
                    }
                    JAVADOC {}
                    SOURCES {}
                }
            }
        }
    }           
}


task updateIntelliJModules(dependsOn: createIntelliJLibraries) << {

    subprojects.each { project ->

        def root = new XmlSlurper().parse(new File("${project.name}.iml"))

        // Remove the existing dependencies
        root.component.orderEntry.findAll { it.@type == "library" && it.@level == "project" }.replaceNode {}

        // Add in the new dependencies
        if (project.configurations.compile) {

            project.configurations.compile.resolvedConfiguration.resolvedArtifacts.findAll {
                it.moduleVersion.id.group != "my.project"
            }.each { artifact ->
                def artifactName = artifact.moduleVersion.id.with { "Gradle: $group:$name:$version" }

                root.component.appendNode {
                    orderEntry (type: "library", exported: "", name: artifactName, level: "project")
                }
            }

        }

        def outputBuilder = new StreamingMarkupBuilder()

        new File("${project.name}.iml").withWriter { writer ->
            groovy.xml.XmlUtil.serialize(outputBuilder.bind{ mkp.yield root }, writer)
        }
    }
}
like image 41
Chris Prior Avatar answered Nov 03 '22 00:11

Chris Prior