Summary: Why does MSBuild have a "task" model to abstract tools?

Makefiles call tools directly -- invoking CL.exe, Xcopy, and so on. The MSBuild way is to abstract units of execution like tools with "tasks". There are all kinds of reasons why this is a useful abstraction. I hope we can persuade you tasks are cooler than launching tools directly:

		          -- tasks can abstract of in-process execution for speed (CSC today is run in-process when you build within Visual Studio and out of process from msbuild.exe with the same targets file). Maybe one day a task for CL (the C++ compiler) can be improved to run in-process, and if that happens, not a single targets file or project will have to be modified, they'll just use the same task.
	

		          -- tasks abstract switches into human readable properties with intellisense (think of CL that has a hundred switches (/P, /EP, /E, or /EP /P ?) and how much more useful properties like [PreprocessToAFile,] [SuppressPreprocessLineNumbers] are
	

		          -- tasks avoid the hassles of having to append negative switches to try to disable a switch added to the command line earlier in a makefile (just flip the property going into the task instead)
	

		          -- tasks can add built-in reliable transitive dependency analysis that understands the tool's domain (for example, we internally have a CL task prototype that reliably tracks all the CL inputs and outputs so it can build the minimum set of sources the targets pass in -- without the targets file needing to know how it's done)
	

		          -- tasks can abstract any necessary response files (for very long command lines) and any looping for tools that only process one file at a time (like midl) and any cmd line quoting and escaping you need
	

		          -- some tools can use cache files to speed up their work, and these are abstracted from the targets file by having a task. For eample, our [ResolveAssemblyReference] task does this
	

		          -- tasks can emit output properties and items that can feed into the next task, such as the subset of files that were actually compiled or copied
	

		          -- tasks can be used to abstract and re-use algorithms, like for the complex logic that resolves assembly references
	

		          -- tasks can do rich logging: time spent in tools, who in you're tree is compiling without passing /GS, etc, all in one place
	

		          -- all this can be implemented by one person and shared amongst many targets file authors
	

		          -- probably more things we haven't thought of yet...
	

Of course, you can always launch your tool directly if a task isn't available -- use the Exec task. In future, we're working on ways to make it easier to generate the code for a task to wrap the tool of your choice, or even create tasks without compiling any code...
Microsoft Communities