In Target Dependencies in MSBuild vs. Ant I claim that Ant's model was more powerful than the file name based approach taken by make and MSBuild's target inputs/outputs dependencies.
Let me give some reasons:
The name mangling performed by a task can be quite complex.
Let's take rmic as an example. If you use RMI over IIOP, it creates
a/b/c/_D_Stub.class
fora/b/c/D.class
ifD
is an interface. If you want to express this with patterns, you have to add full regular expression support to the core of your build system (or something similar), so users can specify (.*)([^/\.]+)\.class => \1_\2_Stub.class as a transformation rule.What's even worse than this IMHO, is that the user has to specify this transformation at all. With Ant's <rmic>, the user doesn't have to care for the name mangling rules.
Name mangling may depend on the value of an attribute.
Continuing with the rmic example, the above rules apply only if you use
iiop=true
, otherwise it would be the same resulting class but without the leading underscore.If the user decides to switch from IIOP to JRMP as transport, she will also have to modify the pattern in the build file. No need to do so in Ant.
Name mangling may even depend on the content of the file.
Once again rmic. If you use IIOP and the class is a concrete class and not an interface, you get two files. One is
a/b/c/_D_Tie.class
and an additional_Stub
class for the interface implemented byD
.If you want to capture this upfront, you have to state the dependency explicitly. No pattern matching is going to work. You end up with one target per concrete class that way - and the user has to keep it up to date. Ant's rmic uses reflection on
D
to find the correct names.The same applies to source files generated from Corba IDL (in case Java's RMI is too esoteric). The file name of the generated source doesn't have to be related to the name of the IDL file at all. You can hard-code the file names or you can write a smart task for this purpose.
Name mangling depends on a concrete implementation of an abstract, vendor-neutral task.
Again rmic. Ant supports pluggable back-ends for this, and one of them is the rmic compiler of Weblogic which uses a different name mangling scheme. So the user will have to know which tool is going to be used and adapt the patterns in the build file to it. The same is true for <jspc> for example where the generated names depend on the container.
I understand that vendor-neutral tasks are not that important for MSBuild. ;-)
Non-local dependencies.
What if your source or target is a file reached via ftp or scp? Build ftp, WebDAV, ssh, cvs, VSS and what-not support into the core of the tool?
Non-file dependencies.
<jar> allows users to specify the manifest in-line.
The task reads the original manifest of an existing archive and compares it to the manifest it would create now. If they are different, the archive gets recreated. To achieve the same with file dependencies, the archiving target must use the build file itself as an input file - and may end up recreating the archive much more often than necessary.
What if you want to do something based on interactive user input?
Sometimes you want to get around dependency checking.
See Ant <copy>'s overwrite attribute for example, it will copy files even when the target is newer than the source.
Tasks that delete files.
How do you specify that the result of a target is the removal of input files?
Complex class dependencies
Say class
A
extends classB
and they end up in two different assemblies. Now you changeB
, changing its public or protected API, you should recompileA
as well.Ant's <javac> doesn't catch this, neither can a simplistic input/output dependency. Possible solutions are (1) hard-coding the dependencies, creating targets for each such dependency. (2) write a smart task that removes the assembly that contains
A
, this is what Ant's <depend> task does - see the previous point, how do you express this? (3) write an even smarter task that understands the programming language, sorts out what needs to be recompiled and then invokes the compiler, here it is for Ant and Java.
Like I previously said, you can create smart tasks in MSBuild as well. But if you start out with the target input/output checking in your build file, switching to smarter tasks may become a steep learning curve. You may even have to implement them yourself when the shipped tasks are not smart enough.
path: /en/dotNet/msbuild | #