MSBuild for MAKEFILE converts

Don Box's Spoutlet

Syndication

Chris and I spent time in MSBuild-land this week to better automate some of our work.
 
In the past, I've been a big fan of NMAKE, which makes me a bit of an odd duck at Microsoft where most projects use build.exe to do their builds. 
 
I tried to get the zen of build.exe in my head when I started at the firm, but like many, I fell into the standard "copy a build configuration from an existing project" habit which really rubs me the wrong way. I'm one of those "I need to understand what I'm doing" people, and I was never able to attain the same level of understanding I had with NMAKE.
 
My day job now involves automating builds using MSBuild. I, like many people, made the mistake of diving into the extensibility model (ITask) first, rather than groking the build workflow first. After hitting my head against a few walls, I finally got my MSBuild understanding over the bar that I believe I have written my last MAKEFILE.
 
In fact, I just wrote what I hope to be my last makefile here as the tutorial I always wanted. Here it is:
 
INTERMEDIATEFILE=f2.txt
 
all : t1 t2
 
clean :
 del /f f3.txt f4.txt
 
t1 : f3.txt
t2 : f4.txt
 
f3.txt : f1.txt
    copy /y f1.txt $(INTERMEDIATEFILE)
    copy /y $(INTERMEDIATEFILE) f3.txt
    del /f $(INTERMEDIATEFILE)
 
f4.txt : f1.txt
    copy /y f1.txt f4.txt
 
And here's the corresponding MSBuild project file that accomplishes the same task:
 
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="all">
  <ItemGroup>
    <IntermediateFile Include="f2.txt" />
  </ItemGroup>
 
  <Target Name="all" DependsOnTargets="t1;t2" />
  <Target Name="clean" >
    <Delete Files="f3.txt;f4.txt" />
  </Target>
 
  <Target Name="t1" Inputs="f1.txt" Outputs="f3.txt" >
    <Copy SourceFiles="f1.txt" DestinationFiles="@(IntermediateFile)" />
    <Copy SourceFiles="@(IntermediateFile)" DestinationFiles="f3.txt" />
    <Delete Files="@(IntermediateFile)" />
  </Target>
 
  <Target Name="t2" Inputs="f1.txt" Outputs="f4.txt" >
    <Copy SourceFiles="f1.txt" DestinationFiles="f4.txt" />
  </Target>
</Project>
Yes, it's more verbose, but this one has the following advantages:
 
  1. I get intellisense in my favorite XML editor.
  2. I can load it up as a project in VS and have it do something reasonable. Not great, but reasonable.
  3. I can process and generate the project metadata as XML using my favorite XML programming system.
  4. I can host the workflow engine that interprets that metadata from any .NET program.
  5. MSBUILD.exe is part of the redist for the .NET Framework, NMAKE isn't.
 
As for point #2, if I were expecting VS users to load my project file (and I do), I'd have authored it like this:
 
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="all">
  <ItemGroup>
    <IntermediateFile Include="f2.txt" >
      <InProject>false</InProject>
    </IntermediateFile>
    <InputFile Include="f1.txt" />
  </ItemGroup>
  <Target Name="all" DependsOnTargets="t1;t2" />
  <Target Name="clean">
    <Delete Files="f3.txt;f4.txt" />
  </Target>
  <Target Name="rebuild" DependsOnTargets="clean;all" />
  <Target Name="t1" Inputs="@(InputFile)" Outputs="f3.txt">
    <Copy SourceFiles="@(InputFile)" DestinationFiles="@(IntermediateFile)" />
    <Copy SourceFiles="@(IntermediateFile)" DestinationFiles="f3.txt" />
    <Delete Files="@(IntermediateFile)" />
  </Target>
  <Target Name="t2" Inputs="@(InputFile)" Outputs="f4.txt">
    <Copy SourceFiles="@(InputFile)" DestinationFiles="f4.txt" />
  </Target>
</Project>
 
Note that I used the <InProject> element to suppress the intermediate file f2.txt from showing up in solution explorer.  I just wanted it as a variable, not as part of catalog of the input to my project.
 
Also, I added an item for my input file, which I do want to show up in solution explorer.  For hygiene reasons, I used the Item variable in the actual targets. 
 
Finally, I added a named target called "rebuild." VS has three common commands that invoke msbuild against different targets. Here's how it works:
 
  1. Selecting Clean Solution or Clean ProjectName in VS will build the target named Clean.
  2. Selecting Rebuild Solution or Rebuild ProjectName in VS will build the target named Rebuild.
  3. Selecting Build Solution or Build ProjectName in VS will build "default targets" which is either the first target in the project file or (when present) the semi-colon delimited list of targets in the Project/@DefaultTargets attribute.
 
 

Posted Jul 18 2005, 03:57 AM by don-box

Comments

Christopher Steen - Learning .NET wrote Link Listing - July 18, 2005
on 07-18-2005 9:49 PM
Behold the Power of TraceListeners
Data Source Controls (Part 4 - Caching)
Defining and Maintaining...
VinceX.NET's WebLog wrote MSBuild for MakeFile converts
on 07-19-2005 4:06 AM





Interesting
article found on Don
Box Spoutlet
&nbsp;
MSBuild for MAKEFILE converts

Depressed .NET user wrote re: MSBuild for MAKEFILE converts
on 04-19-2006 5:36 AM
Yes, the MSBuild file is more verbose than the Makefile. However, you also forgot to mention that it does much less than the Makefile.

Make calculates dependencies between targets (and has a correct conceptual model of targets too), only builds targets that are out of date, and calculates the value of variables lazily, all of which has to be programmed by hand in MSBuild.

Why didn't the MSBuild team just improve NMake up to and beyond the level of competing Make tools instead of producing a knock-off of Ant which is a truly awful build tool.
An MSBuild User wrote re: MSBuild for MAKEFILE converts
on 12-01-2006 9:40 PM
Where do you people come from? Can you read, or think?

MSBuild not only performs dependency analysis between targets within a project, it can also perform dependency analysis *between* different projects. If you write your project files correctly -- and it's easy to do so -- you get correct and accurate incremental builds, no matter where you build, within a large tree of components.

MSBuild *IS* a better NMAKE. You obviously haven't spent half an hour reading the docs or experimenting with MSBuild.

And yes, I've used Ant, and MSBuild does have advantages, even over Ant. Learn the tools before you just mindlessly bash them.
WaWA wrote re: MSBuild for MAKEFILE converts
on 04-13-2007 9:17 PM
So MSBuild dosn't make C++, MSBuild dosn't make MSI's projects, So what make it better than NANT ?? For cry out loud dose this make any sence!!

Add a Comment

(required)  
(optional)
(required)  
Remember Me?