Programming languages that target the .NET Framework use MSBuild project files to describe and control the application build process. When you use Visual Studio to create an MSBuild project file, the appropriate XML is added to the file automatically. However, you may find it helpful to understand how the XML is organized and how you can change it to control a build.
Note
This article is appropriate if you want to learn the basic fundamentals of how MSBuild works independently of any SDK. Building with an SDK, such as when you use dotnet build or you add the Sdk attribute to the root project element, is not covered in this article. See .NET Project SDKs.
The build logic imported by standard .csproj files supports many more options and a much more complex build process than this example.
For information about creating a project file for a C++ project, see MSBuild (C++).
This tutorial shows how to create a basic project file incrementally, by using only a text editor. The walkthrough follows these steps:
Extend the PATH environment variable.
Create a minimal application source file.
Create a minimal MSBuild project file.
Build the application by using the project file.
Add properties to control the build.
Control the build by changing property values.
Add targets to the build.
Control the build by specifying targets.
Build incrementally.
This tutorial shows how to build the project at the command prompt and examine the results. For more information about MSBuild and how to run MSBuild at the command prompt, see Use MSBuild.
To complete the tutorial, you must have Visual Studio installed because it includes MSBuild and the C# compiler, which are required for the walkthrough.
Extend the path
Before you can use MSBuild, you must extend the PATH environment variable to include all the required tools.
If you're running on Windows, you can use the Developer Command Prompt for Visual Studio. Search for it in the Windows search box in the Windows task bar. To set up the environment in an ordinary command prompt or in a scripting environment, run VSDevCmd.bat in the Common7/Tools subfolder of a Visual Studio installation.
Create a minimal application
This section shows how to create a minimal C# application source file by using a text editor.
At the command prompt, browse to the folder where you want to create the application, for example, \My Documents\ or \Desktop\.
Create a subfolder named \HelloWorld\ and change directory to go inside it.
In a text editor, create a new file HelloWorld.cs and then copy and paste the following code:
C#
using System;
classHelloWorld
{
staticvoidMain()
{
#if DebugConfig
Console.WriteLine("WE ARE IN THE DEBUG CONFIGURATION");
#endif
Console.WriteLine("Hello, world!");
}
}
Build the application by typing csc helloworld.cs at the command prompt.
Test the application by typing helloworld at the command prompt.
The Hello, world! message should be displayed.
Delete the executable.
Create a minimal MSBuild project file
Now that you have a minimal application source file, you can create a minimal project file to build the application. This project file contains the following elements:
The required root Project node.
An ItemGroup node to contain item elements.
An item element that refers to the application source file.
A Target node to contain tasks that are required to build the application.
A Task element to start the C# compiler to build the application.
To create a minimal MSBuild project file
In the text editor, create a new file HelloWorld.fromscratchproj and enter the following code:
Tasks in the Build target are executed sequentially. In this case, the C# compiler Csc task is the only task. It expects a list of source files to compile, and this is given by the value of the Compile item. The Compile item references just one source file, Helloworld.cs.
Note
In the item element, you can use the asterisk wildcard character (*) to reference all files that have the .cs file name extension, as follows:
XML
<CompileInclude="*.cs" />
Build the application
Now, to build the application, use the project file that you just created.
At the command prompt, type msbuild helloworld.fromscratchproj -t:Build.
This builds the Build target of the Helloworld project file by invoking the C# compiler to create the Helloworld application.
Test the application by typing helloworld.
The Hello, world! message should be displayed.
Note
You can see more details about the build by increasing the verbosity level. To set the verbosity level to "detailed", type this command at the command prompt:
This instructs the C# compiler to produce an assembly that is named by the AssemblyName property and to put it in the folder that is named by the OutputPath property.
Save your changes.
Your project file should now resemble the following code:
We recommend that you add the backslash (\) path delimiter at the end of the folder name when you specify it in the OutputPath element, instead of adding it in the OutputAssembly attribute of the Csc task. Therefore,
The Clean target invokes the Delete task to delete the application. The Rebuild target does not run until both the Clean target and the Build target have run. Although the Rebuild target has no tasks, it causes the Clean target to run before the Build target.
Add this DefaultTargets attribute to the opening Project element:
XML
<ProjectDefaultTargets="Build">
This sets the Build target as the default target.
Your project file should now resemble the following code:
You can exercise the new build targets to test these features of the project file:
Building the default build.
Setting the application name at the command prompt.
Deleting the application before another application is built.
Deleting the application without building another application.
To test the build targets
At the command prompt, type msbuild helloworld.fromscratchproj -p:AssemblyName=Greetings.
Because you did not use the -t switch to explicitly set the target, MSBuild runs the default Build target. The -p switch overrides the AssemblyName property and gives it the new value, Greetings. This causes a new application, Greetings.exe, to be created in the \Bin\ folder.
To verify that the \Bin\ folder contains both the MSBuildSample application and the new Greetings application, type dir Bin.
Test the Greetings application (for example, by typing Bin\Greetings on Windows).
The Hello, world! message should be displayed.
Delete the MSBuildSample application by typing msbuild helloworld.fromscratchproj -t:clean.
This runs the Clean task to remove the application that has the default AssemblyName property value, MSBuildSample.
Delete the Greetings application by typing msbuild helloworld.fromscratchproj -t:clean -p:AssemblyName=Greetings.
This runs the Clean task to remove the application that has the given AssemblyName property value, Greetings.
To verify that the \Bin\ folder is now empty, type dir Bin.
Type msbuild.
Although a project file is not specified, MSBuild builds the helloworld.fromscratchproj file because there is only one project file in the current folder. This causes the MSBuildSample application to be created in the \Bin\ folder.
To verify that the \Bin\ folder contains the MSBuildSample application, type dir Bin.
Build incrementally
You can tell MSBuild to build a target only if the source files or target files that the target depends on have changed. MSBuild uses the time stamp of a file to determine whether it has changed.
To build incrementally
In the project file, add these attributes to the opening Build target:
This specifies that the Build target depends on the input files that are specified in the Compile item group, and that the output target is the application file.
The resulting Build target should resemble the following code:
Test the Build target by typing msbuild -v:d at the command prompt.
Remember that helloworld.fromscratchproj is the default project file, and that Build is the default target.
The -v:d switch is an abbreviation of -verbosity:detailed that you used previously.
If you already built the output, these lines should be displayed:
Skipping target "Build" because all output files are up-to-date with respect to the input files.
MSBuild skips the Build target because none of the source files have changed since the application was last built.
C# example
The following example shows a project file that compiles a C# application and logs a message that contains the output file name.
Code
XML
<ProjectDefaultTargets = "Compile"><!-- Set the application name as a property --><PropertyGroup><appname>HelloWorldCS</appname></PropertyGroup><!-- Specify the inputs by type and file name --><ItemGroup><CSFileInclude = "*.cs"/></ItemGroup><TargetName="Compile"><!-- Run the C# compilation using input files of type CSFile --><CSCSources = "@(CSFile)"OutputAssembly = "$(appname).exe"><!-- Set the OutputAssembly attribute of the CSC task
to the name of the executable file that is created --><OutputTaskParameter = "OutputAssembly"ItemName = "EXEFile" /></CSC><!-- Log the file name of the output file --><MessageText="The output file is @(EXEFile)"/></Target></Project>
Visual Basic example
The following example shows a project file that compiles a Visual Basic application and logs a message that contains the output file name.
Code
XML
<ProjectDefaultTargets = "Compile"><!-- Set the application name as a property --><PropertyGroup><appname>HelloWorldVB</appname></PropertyGroup><!-- Specify the inputs by type and file name --><ItemGroup><VBFileInclude = "consolehwvb1.vb"/></ItemGroup><TargetName = "Compile"><!-- Run the Visual Basic compilation using input files of type VBFile --><VBCSources = "@(VBFile)"OutputAssembly= "$(appname).exe"><!-- Set the OutputAssembly attribute of the VBC task
to the name of the executable file that is created --><OutputTaskParameter = "OutputAssembly"ItemName = "EXEFile" /></VBC><!-- Log the file name of the output file --><MessageText="The output file is @(EXEFile)"/></Target></Project>
What's next?
Visual Studio can automatically do much of the work that is shown in this walkthrough. To learn how to use Visual Studio to create, edit, build, and test MSBuild project files, see Use MSBuild.