Last week I wrote about fixing a build issue in Bitrise. This time, I have a story about debugging gradle files.
My current project uses an internal software library that recently released a new version. Unfortunately, I ran into some issues when trying to import a local copy of this library that didn't make sense. Gradle reported an array index out of bounds exception. However, the library compiled fine on its own (when building it from its own project).
Upon closer exception, I found that this Gradle script was running an external
git command using an
Exec task. For some unknown reason this was failing when importing the library, but was working fine when built standalone.
Like most programmers, my first instinct was to try to print out the value of the array to see what was being returned. With a build script though, this proved to be a little difficult as Android Studio doesn't show you the output of any
println statements in build scripts. It is possible to run Gradle from the command line and see the output from
println commands, but it can sometimes be a little tricky to figure out exactly what command(s) to run, arguments you need to pass, etc.
I wanted to have a quick way to see some kind of debugging information while running the build the way I'm used to (from within the Android Studio IDE). Then I had an idea that I've sometimes used in Java/Kotlin to print a stack trace - what if I threw an exception? By purposefully throwing an exception, I can put any variables I'm interested in seeing into the message for the exception itself. It's pretty simple to use:
val output = <output of some command> throw new Exception("Output: $output")
Thankfully, this worked like a charm! Android Studio dutifully displayed the exception (and its message containing my debug information), so now I was up and running!
What I was able to see is that there were different values being returned by that
git command when building the library on its own versus importing it into the app project. This command was expecting the git tag to be in a particular format, and when run from inside the app project, it wasn't the format that was expected.
So, I expanded on my debugging idea a little bit and executed a command-line
pwd command to find out what directory the build script was being run from. Lo and behold, when building just the library, the directory was the one for the library itself. However, when building my app project, this directory was the directory of my app!
Looking just a little more closely at the Gradle script, I discovered that the
workingDir of the
Exec task was being set to
project.rootProject.projectDir. Hence the difference in behavior - when the library is imported, the root project corresponds to my app's project directory, not that of the library. So, simply changing this to
project.projectDir resolved the issue!
I hope you learned a few things about debugging Gradle files! What's your favorite strategy for debugging them? Let me know in the comments below! And, please follow me on Medium if you're interested in being notified of future tidbits.
This tidbit was discovered on December 16, 2020.