6

I have a gradle project with multiple packages. After the build, each package generates its jar files in build/libs. The external jar dependencies are pulled into ~/.gradle. I would now like to run the service locally from the commandline with the appropriate classpath. For this purpose, I am writing a script that constructs the classpath. The problem is that the script does not understand all the external dependencies and hence cannot construct the classpath. Is there a way for gradle to help with this? Ideally, I would like to dump all the dependencies into a folder at the end of the build.

Sriram Subramanian
  • 2,623
  • 5
  • 32
  • 35

2 Answers2

15

Firstly, i would suggest using the application plugin if you can, since it takes care of this already.

If you want to dump the classpath to a file yourself, the simplest way is something like:

task writeClasspath << {
    buildDir.mkdirs()
    new File(buildDir, "classpath.txt").text = configurations.runtime.asPath + "\n"
}

If you want to actually copy all the libraries on the classpath into a directory, you can do:

task copyDependencies(type: Copy) {
    from configurations.runtime
    into new File(buildDir, "dependencies")
}
Tom Anderson
  • 46,189
  • 17
  • 92
  • 133
  • Thanks for the answer. How do I control the JVM settings if I use the application plugin? I would like to start the JVM with specific settings passed in the commandline. If application plugin can help me configure this, it would be useful. – Sriram Subramanian Nov 20 '13 at 22:16
  • 1
    I found this -http://www.gradle.org/docs/current/dsl/org.gradle.api.Project.html#N13953. Let me play around with this and see if I can have it do what I want. – Sriram Subramanian Nov 20 '13 at 22:21
  • I have not been successful in getting it to work. I added the application plugin and specified the main class name. On running gradle run I get class not found error. Also the classes and resources folder are not created and hence the error I assume. The command gradle run issues is - /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/bin/java -Dfile.encoding=UTF-8 -cp /Users/name/gradleproject/build/classes/main:/Users/name/gradleproject/build/resources/main MainClass – Sriram Subramanian Nov 20 '13 at 23:39
  • I found what the issue is. I have a project with multiple packages. Each package does have a build/classes and build/resources folder but the main project does not have one. I am not sure where to run this command from – Sriram Subramanian Nov 21 '13 at 00:22
  • When you say "project with multiple packages", you mean multiple subprojects, right? The situation there is that the subprojects' configurations (runtime, compile, etc) are independent of those of the parent project; neither includes the other. So, indeed, simply building an application at the root won't work. However, you should be able to add dependencies on the child projects to the root project, which should make this work. – Tom Anderson Nov 21 '13 at 14:02
  • I have one build.gradle file at the root level that refers to all the sub projects and the dependencies between them. So the dependencies are all there in the build.gradle file in the root project. I do not have any build.gradle files in the sub projects. I build the root but have the individual jars drop in the appropriate sub projects. I would like to run the entire project using application plugin and wondering how to do that. – Sriram Subramanian Nov 21 '13 at 17:22
  • If you're using the application plugin, you can run `gradle distTar`. You'll then get a tar file in `./build/dist` which you can untar and get dependencies in the shell script in `./bin/projectName`. It's not perfect since you have to re-create it regularly during development, but it does work... – Loren Oct 12 '17 at 19:07
2

You could try something like this in your build script:

// add an action to the build task that creates a startup shell script
build << {
    File script = file('start.sh')

    script.withPrintWriter {
        it.println '#!/bin/sh'
        it.println "java -cp ${getRuntimeClasspath()} com.example.Main \"\$@\""
    }

    // make it executable
    ant.chmod(file: script.absolutePath, perm: 'u+x')
}

String getRuntimeClasspath() {
    sourceSets.main.runtimeClasspath.collect { it.absolutePath }.join(':')
}
zagyi
  • 17,223
  • 4
  • 51
  • 48
  • Thank you. That looks promising. Can I add it anywhere in the build.gradle file? Also I would like to ideally dump the class path somewhere and let the script refer to contents in the file. That enables me to have a script that does a bunch of things and need not be part of the gradle script. – Sriram Subramanian Nov 20 '13 at 20:53
  • I updated the question to show what I tried and what errors I saw. – Sriram Subramanian Nov 20 '13 at 20:59
  • `sourceSets.main.runtimeClasspath` is basically a [`FileCollection`](http://www.gradle.org/docs/current/javadoc/org/gradle/api/file/FileCollection.html) that contains File objects referring to 1) build output folders (`build/classes/main`, `build/references/main`, etc.) and 2) external jar dependencies in whatever repositories they are in. You could easily iterate over this collection and copy the jars in an aribtrary folder. – zagyi Nov 20 '13 at 20:59
  • 1
    This is exactly what the [application plugin](http://www.gradle.org/docs/current/userguide/application_plugin.html) does, except it does it in rather more luxury - it generates a very portable unix shell script, plus a Windows batch script, and it copies all the dependencies into a directory so that the scripts and libraries can be distributed together. – Tom Anderson Nov 20 '13 at 21:44
  • @TomAnderson, thanks for pointing that out. The application plugin slipped my attention, when I've recently had this requirement, hence I wrote the above script manually. I've learned something new today too, so I +1'd your answer. :) – zagyi Nov 20 '13 at 21:57
  • It's definitely one of the more obscure plugins, and easy not to be aware of! It's also worth knowing there's a list of community plugins on the Gradle wiki: http://wiki.gradle.org/display/GRADLE/Plugins . – Tom Anderson Nov 20 '13 at 22:15