How do I programmatically create executable Jar?

I want to create two types of executable Jar by command both of them reference same code and external Jar, only diff thing is including xml file when they are built When I input command “dev” after input “gradle start” I want to create executable jar including xml file(where at ‘/src/env/dev’)

Here’s my gradle source, I have tried various way to create Jar but it couldn’t include source or find main class is there something wrong in my source?

apply plugin: 'java'
  sourceSets {
    main{
        java.srcDir 'src'
    }
}
  dependencies {
 compile fileTree(dir: 'lib', include: '*.jar')
}
    task start <<{
 def buildType = System.console().readLine("\nSelect Build Type (live, dev)\n")
        if(buildType == 'live'){
        tasks.live.execute()
    }else if(buildType == 'dev'){
        tasks.dev.execute()
    }else{
     println 'Selected Wrong Type!!'
    }
      }
  task dev(type: Jar){
 destinationDir = file('build/dev')
    from('/src/env/dev'){
  include('*.cfg.xml')
 }
   manifest {
     attributes (
      'Main-Class': 'com.ServerManager',
       'Class-Path': '. '+configurations.compile.collect { './lib/'+it.getName() }.join(' ')
   )
 }
      }
  task live(type: Jar){
 destinationDir = file('build/live')
   from('/src/env/live'){
  include('*.cfg.xml')
 }
       manifest {
     attributes (
      'Main-Class': 'com.ServerManager',
       'Class-Path': '. '+configurations.compile.collect { './lib/'+it.getName() }.join(' ')
   )
 }
      }

Some general remarks about your build script:

  • it’s general a bad idea to call task#execute() programatically as it is ‘internal’ api and this way you can’t use the goodness gradle general offers (like task dependencies, up-to-date checks, …) - I wouldn’t recommend to use interactive inputs in your build. This means that you can’t run the build automatically from a ci server without interaction

Why do you need the ‘start’ task. couldn’t you just run the dev and/or the live task without the detour with using your start task

you can avoid copy paste issues by using some groovy in your code. The following snippet creates two tasks of type jar. The parameter taskName is used to point to the build destination and the source for the cfg files.

To have the classes of the actual project in the jar I added from ‘sourceSets.main.classes’ to the task definition.

['dev', 'live'].each{ taskName ->
 task(taskName, type: Jar){
     destinationDir = file("build/$taskName")
        from sourceSets.main.output
     from("/src/env/$taskName"){
         include('*.cfg.xml')
     }
     manifest {
         attributes (
             'Main-Class': 'com.ServerManager',
              'Class-Path': '. '+configurations.compile.collect { './lib/'+it.getName() }.join(' ')
          )
     }
 }
}

hope that helps!

A few things

  1. A don’t know what you are trying to achieve with your ‘start’ task - why not just call ‘gradle dev’ or ‘gradle live’? In general it is a bad idea to call task.execute().

  2. Your Manifest Class-Path entries seem to be trying to reference libraries in your project’s ‘lib’ directory. Remember these paths are relative to the location of the jar when you run it, not your project.