Question

I have a java project that is built with buildr and that has some external dependencies:

repositories.remote << "http://www.ibiblio.org/maven2"
repositories.remote << "http://packages.example/"

define "myproject" do
  compile.options.target = '1.5'
  project.version = "1.0.0"
  compile.with 'dependency:dependency-xy:jar:1.2.3'
  compile.with 'dependency2:dependency2:jar:4.5.6'

  package(:jar)
end

I want this to build a single standalone jar file that includes all these dependencies.

How do I do that?

(there's a logical followup question: How can I strip all the unused code from the included dependencies and only package the classes I actually use?)

Was it helpful?

Solution

This is what I'm doing right now. This uses autojar to pull only the necessary dependencies:

def add_dependencies(pkg)
  tempfile = pkg.to_s.sub(/.jar$/, "-without-dependencies.jar")
  mv pkg.to_s, tempfile

  dependencies = compile.dependencies.map { |d| "-c #{d}"}.join(" ")
  sh "java -jar tools/autojar.jar -baev -o #{pkg} #{dependencies} #{tempfile}"
end

and later:

package(:jar)
package(:jar).enhance { |pkg| pkg.enhance { |pkg| add_dependencies(pkg) }}

(caveat: I know little about buildr, this could be totally the wrong approach. It works for me, though)

OTHER TIPS

I'm also learning Buildr and currently I'm packing Scala runtime with my application this way:

package(:jar).with(:manifest => _('src/MANIFEST.MF')).exclude('.scala-deps')
  .merge('/var/local/scala/lib/scala-library.jar')

No idea if this is inferior to autojar (comments are welcome), but seems to work with a simple example. Takes 4.5 minutes to package that scala-library.jar thought.

I'm going to use Cascading for my example:

cascading_dev_jars = Dir[_("#{ENV["CASCADING_HOME"]}/build/cascading-{core,xml}-*.jar")]
#...
package(:jar).include cascading_dev_jars, :path => "lib"

Here is how I create an Uberjar with Buildr, this customization of what is put into the Jar and how the Manifest is created:

assembly_dir = 'target/assembly'
main_class = 'com.something.something.Blah'

artifacts = compile.dependencies

artifacts.each do |artifact|
    Unzip.new( _(assembly_dir) => artifact ).extract
end

# remove dirs from assembly that should not be in uberjar
FileUtils.rm_rf( "#{_(assembly_dir)}/example/package" )
FileUtils.rm_rf( "#{_(assembly_dir)}/example/dir" )

# create manifest file
File.open( _("#{assembly_dir}/META-INF/MANIFEST.MF"), 'w') do |f| 
    f.write("Implementation-Title: Uberjar Example\n")
    f.write("Implementation-Version: #{project_version}\n") 
    f.write("Main-Class: #{main_class}\n")
    f.write("Created-By: Buildr\n")                 
end

present_dir = Dir.pwd
Dir.chdir _(assembly_dir)
puts "Creating #{_("target/#{project.name}-#{project.version}.jar")}" 
`jar -cfm #{_("target/#{project.name}-#{project.version}.jar")} #{_(assembly_dir)}/META-INF/MANIFEST.MF .`
Dir.chdir present_dir

There is also a version that supports Spring, by concatenating all the spring.schemas

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top