Build Jar With Another Configuration

Hello,

I simply wish to build a jar with another configuration and add it to my artifacts (with a classifier). Let’s say I have project foo:

// foo/build.gradle
apply: 'java'
  configurations {
  h2
// does NOT extend compile, since I wish to use alternate dependencies that are incompatible with my compile dependencies
}
  // Hadoop 1 and Hadoop 2 are binary incompatible, although this project's code is source-compatible with both for compilation
dependencies {
  compile "org.apache.hadoop:hadoop-core:1.2.1"
  h2 "org.apache.hadoop:hadoop-common:2.3.0"
}
  task h2Jar(type: Jar) {
  configuration = configurations.h2 // This doesn't seem right. How do I specify this?
  from sourceSets.main.output // Is this right?
  classifier = "h2" // this jar should have a classifier to distinguish it
}
  artifacts {
  archives h2Jar
}

It really seems like it should be this straightfoward, but I know that it’s not.

Just to be clear, I wish to have both jars built, i.e. a foo-$version.jar and a foo-$version-h2.jar, and have these both added to the ivy information. In the ivy, each artifact should have its respective dependencies, e.g. foo-$version.jar depends on the Hadoop 1 jars and foo-$version-h2.jar depends on the Hadoop 2 jars.

I’m looking through the documentation, and I think I may need to add another sourceSet and set its compileClasspath to be the h2 configuration, but I’m not sure exactly how to specify it. The h2 sourceSet would still point to src/main, since I would be compiling the same code for both the compile and h2 configurations.

I think I have the same kind of problem, even if mine somehow is also different. Until now I got no satisfying answer: Although I found a solution,I’m not happy with it. You might have a look at http://forums.gradle.org/gradle/topics/how_to_build_a_jar_from_some_other_subprojects_compiled_classes_and_ressources

Hey Alex,

The Jar task does not have ‘configuration’ property so the assignment “configuration = configurations.h2” is not going to work. Check out the Jar task DSL: http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.bundling.Jar.html

@carlo.if, I don’t think your problem is that much related.

If I understand the problem correctly, the biggest complexity is having 2 separate artifacts in an ivy module (xml), each having different set of dependencies? If that’s the case then here are your options:

  1. the most natural approach is avoid sticking both of those artifacts in a single ivy module, e.g. create a separate subproject for the other jar

  2. ivy provides ways to have different artifacts have different set of dependencies. It is implemented via configurations. E.g. artifact is declared with configuration ‘h2’, the ‘h2’ conf has also some dependencies declared. Then, the consumers that wish to consume this artifact must declare the target configuration explicitly. For example, some consumer wants to have a compile dependency on this ‘h2’ artifact (I made up the group/name/version coordinates):

dependencies {
  compile group: "org.group", name: "module-name", version: "1.0", configuration: "h2"
}

The critical part is setting the ‘target configuration’ at the dependency declaration. This instructs the Gradle’s resolution engine to download only artifacts and dependencies attached to ‘h2’ configuration. This is pretty unconventional and hence by default I recommend option #1. However, depending on your exact scenario (e.g. who/how consumes the artifact) #2 might be what you need. BTW. In gradle build files, by default you don’t have to specify the ‘target configuration’ of the dependencies because a configuration named “default” is used.

Hope that helps!

Here was my solution. This builds one code base (under src/main) twice, using two sets of compilation dependencies; produces both a regular jar artifact and an artifact with a -h2 classifier; and produces ivy that refers to both artifacts and has the correct dependencies for both.

sourceSets {
  h2 {
    java {
      srcDir 'src/main/java'
    }
  }
}
  configurations {
  sharedCompile {
    description = "Compile dependencies shared between Hadoop 1 and Hadoop 2"
  }
  sharedRuntime {
    description = "Runtime dependencies shared between Hadoop 2 and Hadoop 2"
    extendsFrom sharedCompile
  }
  compile {
    extendsFrom sharedCompile
  }
  runtime {
    extendsFrom compile, sharedRuntime
  }
  h2Compile {
    extendsFrom sharedCompile
  }
  h2Runtime {
    extendsFrom h2Compile, sharedRuntime
  }
}
  task h2Jar(type: Jar) {
  classifier = "h2"
  from sourceSets.h2.output
}
  dependencies {
  // add dependencies to sharedCompile, compile, h2Compile, runtime, h2Runtime as appropriate
}
  artifacts {
  h2Runtime h2Jar
}