Awhile ago, I finally decided to bring the build process for one of my open source Java projects into the 21st century. Since I find Maven irritating, I converted the project to use Buildr, a Rake-based build tool that contains, among other things, Maven-style dependency management.
Life was good. I had a nice, simple build, with all the power of Ruby at my disposal, and without any need to edit XML, which sucks.
Then, someone reported a bug: The Buildr-generated POM did not contain dependencies. As the author of the bug report wrote:
Maybe they should be added to the POM, so my build system (I use Gradle) will be able to download all the required jars?
That, of course, is a perfectly reasonable request. As it happens, it was easier requested than accomplished.
After digging through numerous search results, as well as the Buildr source code, I finally came up with a solution. It’s a hack, requiring some local metaprogramming of Buildr’s Ruby code–a solution that is subject to breakage, when subsequent versions of Buildr are released.
But, for now, it gets the job done.
The first step was to install the buildr-resolver
gem. I chose to do that via
Bundler. That way, the Gemfile
becomes a manifest of all the third-party
gems my build requires.
1 2 3 |
|
The next step was to define some simple constants, at the top of my Buildr
Buildfile
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
Next, I created a small utility method that uses buildr-resolver
to write
the POM:
1 2 3 4 5 6 |
|
With those constants in place, it was time for some monkey patching. I
tossed this hackery, as well as make_pom
, at the bottom of my Buildfile
,
where it’s out of the way. Someday, I might get ambitious and put it in a gem.
The first patch, to Buildr::Package
, replaces the stock
Buildr::Package.package
method to rebuild the POM after the regular Buildr
package
function is run.
The second patch replaces Buildr’s ActsAsArtifact.pom_xml
method, which is
responsible for creating the XML for the POM. Ideally, I’d build the XML in-
memory, as the real pom_xml
does, instead of building my POM file and reading
its contents into memory; as it happens, Buildr will take that in-memory
XML I give it and overwrite the POM I just created. However,
buildr-resolver
, and the naether
gem it uses under the covers, want a file
path, so I can’t substitute something like StringIO
.
So, a double-write of the file, it is. I can live with that, since this solution has the advantage of actually getting the job done.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
The complete Buildfile
for the project is
here.
If there’s a cleaner, more reasonable way to get Buildr to produce a POM that contains dependencies, I’d love to hear about it. In the meantime, at least I was able to close the bug.