0

I have a project with a number of compile-time dependencies on other projects (of the same code-base). So the compile classpath is defined somewhat like the following:

<path id = "compile.classpath">
  <fileset dir="${dependency-a.dist.dir}">
    <include name ="*.jar"/>
  </fileset>
  <fileset dir="${dependency-b.dist.dir}">
    <include name ="*.jar"/>
  </fileset>
  <fileset dir="${dependency-c.dist.dir}">
    <include name ="*.jar"/>
  </fileset>
  <fileset dir="${dependency-d.dist.dir}">
    <include name ="*.jar"/>
  </fileset>
</path>

Also, you can image the corresponding build targets for the dependencies and so on. To reduce repetition I need to somehow generate those structures dynamically.

I thought that one Ant-friendly way to capture those dependencies might be to create a deps directory and add sym-links to all the compile-time dependencies of my project.

So the question is: is there an Ant way to write a macrodef or a custom Ant task that would scan that directory (or, alternatively, read a configuration file) and expand into/generate the necessary filesets / build targets automatically, in effect changing the XML nodes of the build.xml file at runtime? I am looking for a generic Ant way to do that (if such exist) so I don't have to use the more disruptive way of generating myself the build.xml file in its entirety from some other configuration. I am not asking how to use subant etc. as I am wondering whether there might exist a more sweeping capability of extending/enriching the Ant build file at runtime that would also apply to other cases not involving building dependencies.

Marcus Junius Brutus
  • 26,087
  • 41
  • 189
  • 331

2 Answers2

3

Writing a task that builds the paths would be pretty easy, but Ant targets are fixed once the build file has been parsed. Ant builds a directed graph of the targets and then executes them.

It is possible to add new targets via a task that is outside of any target itself. include is such a task. It might be possible to generate a build file snippet containing the paths and targets you need via a custom task later include it. Unfortunately include won't allow you to embed it in a macrodef so the two steps had to appear in pairs.

Of course you can use Ant's API rather than include in order to add the paths and targets. You'd get hold of an existing Path using getReference on the Project instance you've received and add you filesets to it. Completely new data types use addReference, addTarget is for targets.

Stefan Bodewig
  • 3,260
  • 15
  • 22
0

Have you considered using ivy? It's a dependency manager that provides a set of ANT tasks that can be used control classpaths but it can also download jars from managed repositories (like Maven).

The following answers can give your a flavour of how ivy is used:

Ivy provides a more powerful solution because it also prevents conflicting versions of the same jar. For example where several dependencies all contain a copy of a common jar like log4j.

In conclusion ivy may appear complex at first glance, but I can assure you that it's solving a complex problem.

Community
  • 1
  • 1
Mark O'Connor
  • 76,015
  • 10
  • 139
  • 185
  • I am using IVY only for external dependencies; for dependencies within the same code base I prefer not to publish them as IVY artifacts but rather directly reference the relative path to where the produced `jar` is located. – Marcus Junius Brutus Feb 22 '15 at 13:15
  • 1
    @MarcusJuniusBrutus "publish" jars from other builds to a "shared" repository (by default is located "~/.ivy2/shared"). Allows other ivy builds, on the same machine, to pull these in as dependencies. Better still push all jars to a managed Maven repository (like Nexus) and use this as a source of all dependencies. Sounds complicated but ends up being the best solution as it also allows you to shared binaries with other build technologies. In conclusion I'm a big fan of storing the binaries created by my builds. Tagging SCM is fine, but not possible to exactly reproduce a binary. – Mark O'Connor Feb 22 '15 at 14:55