But Gradle is worse
So, one of the first goals in building MinimalBible was getting the underlying library building correctly. I’m using jSword to drive most of the underlying functionality of the app – downloading Bibles, searching Bibles, displaying the text, etc. I have incredibly little experience with Java build systems, but in my experience prior, I had worked with Maven a bit. So when I noticed a pom.xml file, I thought I had it made. Turns out the pom.xml was outdated, and for an old build of the library.
Looking at And-bible was one of the things that first clued me in that I was approaching this the wrong way (the fact that the build was producing a jsword-1.6.jar when I knew the build was at least at version 2.1 was the other). The build.xml file also looked important, so I decided to do some more research. Here’s what I’ve learned.
There are a lot of different systems to build Java projects (I come from Python/C). The three most prevalent are Gradle, Ant, and Maven. By default, Android projects (using Android Development Tools in Eclipse) use none of these. Small-scale Android apps that don’t rely on a lot of extra libraries or other projects simply don’t need the level of functionality provided by any of these. But for the apps that do need extra functionality, you’re going to need to put a build system in place.
I’ll start with Maven, since it seems to be the least used in the Android world. There’s a tutorial and a plugin for doing it, but on the whole I didn’t see a whole lot of information on how to use it. That being said, the Maven project retains a central repository of Java libraries that all the other build systems rely on. This way, you can declare dependencies on other libraries, and have the build system automatically download and install them. Lovely.
Ant seems to be the most well-used (if soon to be phased-out) build system in use with Android. ADT has support for generating an Ant build file, and Google has info on how to use Ant with ADT online. However, Ant in and of itself does not have the dependency management that Maven and Gradle do. For that, we rely on a different library known as Ivy. This way, while Ant handles the build process, Ant can invoke Ivy to fetch all the needed libraries before actually compiling. This build system is what is in use by jSword, and they have a fairly nice build set up.
Gradle is the final build toolkit I’ll talk about. First things first, Gradle is powerful. Their manifesto even says so: “Make the impossible possible, make the possible easy and make the easy elegant.” Gradle is also the build system used by Android Studio, the IDE that will eventually replace ADT. So starting as a new project, I thought it would be a good idea to give Android Studio/Gradle a spin. This is eventually going to be the way of the future.
Getting the initial Eclipse project imported wasn’t too complicated, the documentation for doing that is pretty simple. I generated my build.gradle file, and imported the project. And that’s about as far as I got.
The first order of business was making sure that I could build the jSword project using the new Gradle system. Building the Android project itself I’m sure is incredibly simple, I can get to that later. I wanted to first make sure it would be possible to even get the underlying library working first. To that end, I started doing some research and playing around with getting Ant to work with Gradle. Theoretically, Ant build tasks are first-class citizens in Gradle world. The problem is, Gradle has no way of namespacing the imported Ant tasks. That means if there’s a naming conflict, the build fails (there’s a patch to fix this coming up). While this isn’t an issue if you’re just migrating from Ant to Gradle, if you’re trying to use both Gradle and Ant at the same time, this will cause catastrophic problems. Since I don’t intend to fork jSword for Gradle alone, I needed to come up with something different.
For a while I tried to hack together namespacing by putting the jSword Ant tasks into another project. You can find an example (that I assume worked for the author) over here. This didn’t really work for me. By this time, I had been checking the And-bible build script trying to see how its author solved this problem. Without having any actual knowledge of how to write Ant tasks, what I learned by just looking at the code was that he copied over the original source, merged in his modified code, and then compiled the entire thing. And to be honest, I didn’t even try to attempt this with Gradle. While I’m sure Gradle is more than capable of doing this, it wasn’t worth the effort to figure it out; I had a build I could imitate and use as a starting point.
And so, using the And-bible build.xml as a starting point, I wrote my own build script, which is now available over here. I’ll have more information about actually writing the build script in another post!