MSBuild like NAnt allows conditions to be placed on all tasks, targets and the grouping elements for properties and items. Ant allows conditions on targets and a very small subset of tasks (basically <fail> and nothing else).

MSBuild and NAnt conditions can test for String (in)equality and file existence/absence. NAnt adds a couple of more conditions and supports boolean AND when multiple attributes are used. In Ant, the only condition you can test at the task/target level is whether a property has been set or not.

So Ant looks quite limited in comparison. Ant makes up for much of this via the condition task. With this, you can set properties based on conditions, those conditions can do all of the things that NAnt and MSBuild can do plus try to access HTTP URLs, connect to arbitrary sockets, compare file checksums, ... . On top of that, and/or/not are supported as boolean operations.

The Ant-Contrib project adds an <if> task that leverages Ant's condition framework, and I would rather add <if> to Ant than have all tasks support conditions. Otherwise you are going to repeat the same condition over and over again.

But then again, I've never had a build situation complex enough to ever use the <if> task (and I'm the author of it). The first example for conditionals you see in the MSBuild docs is

<PropertyGroup Condition="'$(Config)'== 'DEBUG'">
    <Property Optimize                  = "false"                    />
    <Property OutputPath                = "bin\Debug\"               />
    <Property WarningLevel              = "1"                        />
</PropertyGroup>

<PropertyGroup condition="'$(Config)'=='RETAIL'">
    <Property Optimize                  = "true"                     />
    <Property OutputPath                = "bin\Release\"             />
    <Property WarningLevel              = "4"                        />
</PropertyGroup>
in Ant, I'd use <pre class="code"> <property file="${config}.properties"/> </pre> and two property files instead. YMMV.

path: /en/dotNet/msbuild | #

I should have opened the archives before I took them home. I don't have OpenOffice installed at home (and downloading it via my modem is no fun), so I couldn't read the docs that come as Word documents over the weekend.

In the meantime, Steve has had a first look at the docs as well. I agree with most of his points, but disagree on the target dependencies.

In Ant (and I think NAnt as well) targets depend on other targets, period. You declare the dependencies between targets and (N)Ant sorts out which targets to run in which order if you ask it to execute one.

In traditional make, you create files and those files depend on other files and you have rules that tell make how to build files from files. make will sort out which files to build when you tell it your "target" file. If your "target" cannot be expressed as a file, you need ".PHONY" targets, something that is the normal mode of operation in Ant.

This difference is one of the major stumbling blocks for people used to make when they come to Ant. All dependencies in Ant are "phony" and the file timestamp level dependencies are resolved by the tasks themselves. Ant doesn't avoid to run the target containing your compilation tasks by checking timestamps, it leaves this up to the <javac> task which looks at the timestamps.

Ant's model is more powerful1 as it allows tasks to perform smarter dependency checking that just looking at file timestamps. Like <zip> looking into the archive or <cc> parsing header files to calculate dependencies.

At the same time, it requires users to write a new task when all they need is a file-timestamp-checking on top of a target that performs a couple of operations. This is why we invented <apply> and <uptodate>. The former adds file dependency checking to <exec>, the latter sets a property that can be used in <target>'s if/unless attributes.

MSBuild supports both notions of dependencies. <Target> has a DependsOnTargets attribute that can be used in the way Ant's depends attribute works. In addition <Target> can specify its required inputs and the generated outputs. The inputs and outputs can be used by MSBuild to calculate the inter-target dependencies.

I'm not sure what happens when you use both dependency mechanisms together. It may lead to strange situations where the implicit dependencies and the ones stated explicitly in DependsOnTargets contradict each other.

Where Ant puts the burden of dependency checking onto the task writer, MSBuild does that in its core. Ant offers the functionality via utility classes, but the task writer still has to write the code herself.

MSBuild's model does not preclude smarter dependency checking in tasks (this is where I disagree with Steve), but it buries it under the more traditional make like dependency mechanism. I wonder whether for example the compilation tasks perform any file timestamp comparisons at all, the docs are not clear, but from my reading of the walk-through, I'd say they don't. In "Add dependency analysis to 301" they avoid recompilation in CSC by adding Inputs/Outputs to the Target containing the Task.

Supporting both types of dependencies inside MSBuild may be confusing to users. In the end I'd guess only one will survive and the other mechanism will become more or less unused. As it is probably easier to write a task without task-internal dependency checking, this may lead to "dumber" tasks than their (N)Ant counterparts.

If you wanted to write a Zip task that adds all files to an archive that are not already part of it (or are newer than the files inside of the archive) without making the task perform the tests, you'll end up with an incredibly complex dependency engine in the MSBuild core, though. Looking at the file name transformations that they already have to support now (prepend a directory, change the extension, ...), this is asking for trouble IMHO.

1here is why I think so.

path: /en/dotNet/msbuild | #

Microsoft's new XML based build tool that looks so much like Ant has become one of the hottest topics on the NAnt list, while it gets more or less ignored in Ant land. MSBuild is going to be bundled with the next version of Microsoft's Visual Studio and will be the default build mechanism for .NET projects then, so it certainly will become a big issue for NAnt.

NAnt's main benefit is and will be that it is Open Source and that it works well with Mono (at least I hope it will, I may need it ;-).

Actually, I'm more interested in what is different between Ant and MSBuild than how MSBuild is going to affect (N)Ant. What have they decided to do in a different way and why? Maybe they have some good ideas that we can improve upon.

John Lam posts a short list of observation he's made while playing with an early access version of MSBuild, he also attaches a sample build file.

I don't grasp the "inter target dependency engine" part, I'll wait until I can find some official docs. This sounds interesting, if I understand correctly what it means. The Item concept sounds like a step into the direction of Ken Arnold's "Ant needs pipes", something we should look into very seriously IMHO.

The other points seem minor, but I'll probably always prefer <csc> over <Task Name="csc"> (and I'd probably never get used to upper-case element and attribute names).

John promises to write an in-depth analysis of MSBuild soon, I'll be reading it.

Bob Arnson posted a pointer to some official information about MSBuild, search for TLS347. I've already picked up the presentation and the source zips but won't find time to actually look into it before the weekend.

Update

Here is what I found:

path: /en/dotNet/msbuild | #