sschuberth
sschuberth

Reputation: 29811

Why does resolving dependencies using Ivy not work in Android's "-pre-build" Ant target?

As Android Java projects use Ant as a build tool, using Ivy for dependency management seems like a natural choice to me. However, while the basic setup works fine, I'm running into a strange issue. I've created a fork of an existing example on GitHub to easily reproduce the problem.

The point is, dependencies get downloaded into the "libs" directory just fine, but the build process as invoked by ant debug does not seem to find the JARs. However, it works fine if I call the "resolve" target not as part of my overloaded "-pre-build" target, but manually like in ant resolve debug.

I have verified that the libraries are really in "libs" just before "-pre-build" finishes (by listing the files in "libs" as part of the "-pre-build" target), so I'm really wondering why they cannot be found.

To reproduce, it's important to delete the libraries from "libs" before running ant. Any ideas what's going wrong here?

resolve:
[ivy:retrieve] :: Apache Ivy 2.3.0-rc1 - 20120416000235 :: http://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: file = /Users/seschube/development/IvyAndroidExample/ivysettings.xml
[ivy:retrieve] :: resolving dependencies :: com.example#ivy-android-example;0.1
[ivy:retrieve]  confs: [default]
[ivy:retrieve]  found org.acra#acra;4.2.3 in acra
[ivy:retrieve]  found com.google.inject#guice;2.0-no_aop in maven2
[ivy:retrieve]  found com.google.zxing.core#core;1.6 in zxing
[ivy:retrieve] :: resolution report :: resolve 115ms :: artifacts dl 5ms
    ---------------------------------------------------------------------
    |                  |            modules            ||   artifacts   |
    |       conf       | number| search|dwnlded|evicted|| number|dwnlded|
    ---------------------------------------------------------------------
    |      default     |   3   |   0   |   0   |   0   ||   4   |   0   |
    ---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: com.example#ivy-android-example
[ivy:retrieve]  confs: [default]
[ivy:retrieve]  4 artifacts copied, 0 already retrieved (1195kB/76ms)

-pre-build:
     [echo] The "libs" directory contains: acra-4.2.3.jar;core-1.6.jar;guice-2.0-no_aop-javadoc.jar;guice-2.0-no_aop.jar

-code-gen:
[mergemanifest] Merging AndroidManifest files into one.
[mergemanifest] Manifest merger disabled. Using project manifest only.
     [echo] Handling aidl files...
     [aidl] No AIDL files to compile.
     [echo] ----------
     [echo] Handling RenderScript files...
[renderscript] No RenderScript files to compile.
     [echo] ----------
     [echo] Handling Resources...
     [aapt] Generating resource IDs...
     [echo] ----------
     [echo] Handling BuildConfig class...
[buildconfig] Generating BuildConfig class.

-pre-compile:

-compile:
    [javac] Compiling 3 source files to /Users/seschube/development/IvyAndroidExample/bin/classes
    [javac] /Users/seschube/development/IvyAndroidExample/src/com/example/IvyAndroidExampleActivity.java:7: error: package org.acra does not exist
    [javac] import org.acra.*;
    [javac] ^
    [javac] /Users/seschube/development/IvyAndroidExample/src/com/example/IvyAndroidExampleActivity.java:8: error: package com.google.inject does not exist
    [javac] import com.google.inject.*;
    [javac] ^
    [javac] /Users/seschube/development/IvyAndroidExample/src/com/example/IvyAndroidExampleActivity.java:9: error: package com.google.zxing does not exist
    [javac] import com.google.zxing.*;
    [javac] ^
    [javac] 3 errors

BUILD FAILED

Upvotes: 1

Views: 1306

Answers (2)

sschuberth
sschuberth

Reputation: 29811

I've found out what's going on: The Android SDK's build.xml adds all JARs from the libs directory to the project.all.jars.path property as part of the -build-setup target. But this is too early if Ivy's retrieve target is called as part of -pre-build, because -build-setup is called before -pre-build. So -pre-build, although meant to be overridden, is the wrong place. As there seems to be no other "dummy" target meant to be overridden before -build-setup is called, I'm now overriding -build-setup in my build.xml file with a version that depends on retrieve and the original -build-setup like this:

<target name="-build-setup" depends="retrieve,android_rules.-build-setup" />.

Upvotes: 4

David W.
David W.

Reputation: 107040

It's hard to say without looking at the build.xml itself.

However, when you use <ivy:resolve> to do your resolution, it doesn't automatically put the libraries in your project. Most likely, they're in $HOME/.ivy2/cache. What you need to do is before you use your <javac> task is to run <ivy:cachepath> to create a path reference you can use in your compile:

You can see I've created the required classpath called main.classpath with my <ivy:cachepath> task. I can then use this to include it in my <javac> task.

If you want to actually download the libraries to your project, you'll need to do <ivy:retrieve/> and then put that directory into your classpath:

Does this help you?

By the way, you might want to take a look at my Ivy setup project on Github. If you have a lot of people sharing your project, it makes it easy to include Ivy. Even if you simply create a ivy.dir sub directory and not make it an included subproject. This way, no one has to install Ivy because it's already installed in your project.

Upvotes: 0

Related Questions