faqvsmsbuildintegration

Cancel
Save
Edit

VS/MSBuild Integration


Project File Format

* I'm a newbie. Can you walk me through a .CSPROJ or .VBPROJ file, line by line?
* What are the requirements for a hand-authored project file to get full intellisense and enable all IDE integration features?
* How is the value of determined for IDE scenarios?
* How do I modify a .*proj file in order to have it run my arbitrary build step?
* How can I disable certain compiler warnings?
* Every <Compile> item in my project takes up 3 lines of XML. Is there a way to clean this up?
* How do I get Visual Studio to recognize my environment variables?

VS Specific Concepts

* How does Clean work?
* How do linked files work?
* How do project-to-project references work?
* How do configurations work?
* How do I get items to not show up in solution explorer? Is there some kind of attribute I can tag the items with so they will be ignored by the IDE?

Supported Languages and Versions

* Does ""MSBuild"" support Visual Studio .NET 2003 projects?
* What's the story with ""MSBuild"" support for VC++ projects?

Logging

* How can I get the log when building from the IDE?
* Compilation is failing, but no errors are given in the IDE. Any advice?

Microsoft.*.targets (i.e., the build process)

* What are Visual Studio's resource naming rules?
* How do I override Visual Studio's resource naming rules, to force resources to be named whatever I want?
* How do I force to copy referenced assemblies to the output directory?
* How do I speed up my large build. Do you have any tips or tricks?

Schemas

* How do I extend the schemas to get intellisense for my own properties and items?

More information...


(The text below is from a topic that we put in the help system at the last minute -- it contains a lot more details about exactly how VS integrates with MSBuild.)

Overview


Visual Studio 2005 hosts MSBuild to load and build any managed projects. Because MSBuild is responsible for the project, almost any MSBuild format project can be successfully used in Visual Studio, even the project it was authored by a different tool and has a completely customized build process.

This topic describes specific aspects of Visual Studio's MSBuild hosting that should be considered when customizing projects and targets files that you wish to load and build in Visual Studio. These will help you make sure Visual Studio features like intellisense and debugging work for your custom project.

Project file extension


MSBuild.exe recognizes any project file extension matching the pattern .*proj. However Visual Studio only recognizes a subset of these project file extensions because it uses the extension to choose which language-specific project system to load the project with. Visual Studio does not have a language-neutral MSBuild based project system.

For example, projects that have the extension .csproj will be loaded by the C# project system, but a project with the extension .xxproj cannot be loaded by Visual Studio. A project file for source files in an arbitrary language must use the same extension as VB, C#, or J# project files to be loaded in Visual Studio.

Well-known target names


Choosing the "Build" command in Visual Studio will execute the default target in the project. Often, this target is also named "Build". Choosing the "Rebuild" or "Clean" command will attempt to execute a target of the same name in the project. Choosing "Publish" will execute a target named "PublishOnly" in the project.

Configurations and Platforms


Configurations are represented in MSBuild projects by properties grouped in a <PropertyGroup> element that has a condition on it. Visual Studio looks at these conditions in order to create a list of project configurations and platforms to display. To successfully extract this list the conditions must have a format like these examples:

Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "

Condition=" '$(Configuration)' == 'Release' "

Condition=" '$(Something)|$(Configuration)|$(SomethingElse)' == 'xxx|Debug|yyy' "

Visual Studio looks at the conditions on <PropertyGroup>, <ItemGroup>, and <Import> elements for this purpose, and on individual property and item elements.

Additional Build Actions


Visual Studio allows you to change the item type of a file in a project in the Build Action field of the properties tool window using a drop-down menu. "Compile", "EmbeddedResource", "Content", and "None" item types are always listed in this menu, along with any other item types that are on items already in your project. To ensure any custom item types are always available in this menu, you can add their names to an item list called "AvailableItemName". For example, adding the following to your targets file will add the custom type "JScript" to this menu for all projects that import it:

		            [<ItemGroup>]
		                        [<AvailableItemName] Include="JScript"/>
		            [</ItemGroup>]
	

Some item types are special to Visual Studio but not normally listed in this dropdown.

In-process compilers


Where possible Visual Studio will attempt to use the in-process versions of the Visual Basic or C# compilers for higher performance. For this to work correctly, the following conditions must be met:

-- there must be a task in any target called "Csc" (for C# projects) or "Vbc" (for Visual Basic projects)

-- the UseHostCompilerIfAvailable parameter must be set to true on the task

-- all parameters on the task are supported by the in-process compiler. This is the list of parameter values on the Csc task that are not supported by the C# in-process compiler:

		            -- [NoConfig=false] or <blank>
		            -- [ResponseFiles=<non] blank>
		            -- [AdditionalLibPaths=<non] blank>
		            -- [AddModules=<non] blank>
		            -- [CodePage=<non] zero>
		            -- [GenerateFullPaths=true]
		            -- [LinkResources=<non] blank>
	

If these conditions are not met, the compilation will work correctly, but will fall back to using the command-line compiler.

Design-time intellisense


To get intellisense before a build has generated any output assembly, the following conditions must be met:

-- there must be a target named "Compile"
-- either this target or one of its dependencies must call the compiler task
-- either this target or one of its dependencies must cause the compiler to get passed all necessary parameters for intellisense, particularly all references
-- the conditions listed above for using the in-process compiler must be met

Building Solutions


Within Visual Studio, the solution file and project build ordering is controlled by Visual Studio itself. When building a solution with msbuild.exe on the command line, MSBuild parses the solution file and orders the project builds. In both cases the projects are built individually in dependency order, and project to project references are not traversed. In contrast when individual projects are built with msbuild.exe, project to project references are traversed.

When building inside Visual Studio, the property $(BuildingInsideVisualStudio) is set to true. This can be used in your project or targets files to cause the build to behave differently.

Display of Properties and Items


Visual Studio understands the meaning of certain property names and values. For example, this property in a project:

<OutputType>WinExe</OutputType>

will cause the "Windows Application" output type to be displayed in the project properties pane. The property value can be edited in the project properties pane and saved in the project file. If such a property is given an invalid value by hand-editing, Visual Studio will show a warning when the project is loaded and use a default value instead.

Visual Studio understands defaults for some properties. These properties will not be persisted into the project file unless they have non-default values.

Properties with arbitrary names are not displayed in Visual Studio. To modify arbitrary properties in Visual Studio, you must open the project file in the XML editor and edit them by hand.

Items defined in the project with arbitrary item types are by default displayed in the Solution Explorer under their project node. To hide an item from display, set the Visible meta-data to false. For example, this item will participate in the build process but not be displayed in the solution explorer:

		            [<ItemGroup>]
		                        [<IntermediateFile] Include="cache.temp">
		                                    <Visible>false</Visible>
		                        [</IntermediateFile>]
		            [</ItemGroup>]
	

Items declared in files imported into the project are not displayed by default. Items created during the build process are never displayed in the Solution Explorer.

Conditions on Items and Properties


During build, all conditions are fully respected.

When determining property values to display, properties that Visual Studio considers configuration dependent are evaluated differently than properties it considers configuration independent. For properties it considers configuration dependent Visual Studio sets the Configuration and Platform properties appropriately and asks MSBuild to re-evaluate the project. For properties it considers configuration independent it is indeterminate how conditionals on them will be evaluated.

Conditional expressions on items are always ignored for the purposes of deciding whether the item should be displayed in the Solution Explorer.

Debugging


In order to find and launch the output assembly and attach the debugger to it Visual Studio needs at least the following properties to be correctly defined: "OutputPath", "AssemblyName", and "OutputType". The debugger will also fail to attach if the build process did not cause the compiler to generate a .pdb file.

Design-time target execution


Visual Studio attempts to execute targets with certain names when it loads a project. These targets include "Compile", "ResolveAssemblyReferences", "ResolveCOMReferences", "GetFrameworkPaths", and "CopyRunEnvironmentFiles". These are run so that the compiler can be initialized to provide intellisense, so that the debugger can be initialized, and so that references displayed in the Solution Explorer are resolved. If these targets are not present, the project will load and build correctly but the design-time experience in Visual Studio will not be fully functional.

Editing projects by hand


When it is necessary to edit an MSBuild project directly, or it is simply more convenient, right click on the project node in the Solution Explorer and choose "Unload Project". Then right click again on the project and choose "Edit Project". The project file will be opened in the XML editor and intellisense will be available. When you are done editing, save and close the project file, then right click on the project node again and choose "Reload Project".

Intellisense and validation


When using the XML editor, project file intellisense and validation is driven by the MSBuild schema files. These are installed by Visual Studio in the schema cache, which can be found beneath the <Visual Studio installation location>\Xml\Schemas folder.

Core MSBuild types are defined in Microsoft.Build.Core.xsd and common types used Visual Studio are defined in Microsoft.Build.CommonTypes.xsd. To customize the schemas so that you have intellisense and validation for your projects' item types, properties, and tasks, you can either edit Microsoft.Build.xsd, or create your own schema that includes the CommonTypes or Core schemas. If you create your own schema you will have to direct the XML editor to find it using the properties window for the XML file.

Editing loaded projects and targets files


Visual Studio caches the content of project files and files imported by project files. If you edit a loaded project file, Visual Studio will automatically prompt you to reload the project so that the changes take effect. However if you edit a file imported by a loaded project, there will be no reload prompt and you must unload and reload the project manually to make the changes take effect.

Output Groups


Several targets defined in Microsoft.Common.targets have names ending in "OutputGroups" or "OutputGroupDependencies". The names of these targets are well known to Visual Studio. Visual Studio calls these targets when it wishes to get particular lists of project outputs. For example, the "SatelliteDllsProjectOutputGroup" target's outputs are a list of all the satellite assemblies that building the project will produce. These output groups are used by features like publishing, deployment projects, and project to project references. Projects that do not define them will load and build in Visual Studio correctly, but some features may not work properly.

Reference Resolution


Reference Resolution is the name for the process of using the reference items stored in a project file to find the locations of actual assemblies. Visual Studio must trigger reference resolution in order to show detailed properties for each reference in the properties window. There are three kinds of references and here is how they are resolved:

Assembly References


The project system calls a target with the well-known name "ResolveAssemblyReferences". This target should produce items with the item type "ReferencePath". Each of these items should have an item spec containing the full path to the reference. The items should have all the meta-data from the input items passed through, in addition to the following new pieces of meta-data: "CopyLocal", indicating whether the assembly should be copied into the output folder, set to true or false; "OriginalItemSpec", containing the original item spec of the reference; and "ResolvedFrom", set to "{TargetFrameworkDirectory}" if it was resolved from the .NET Framework directory.

COM References


The project system calls a target with the well-known name "ResolveCOMReferences". This target should produce items with the item type "ComReferenceWrappers". Each of these items should have an item spec containing the full path to the interop assembly for the COM reference. The items should have all the meta-data from the input items passed through, in addition to the following new piece of meta-data: "CopyLocal", indicating whether the assembly should be copied into the output folder, set to true or false

Native References


The project system calls a target with the well-known name "ResolveNativeReferences". This target should produce items with the item type "NativeReferenceFile". The items should have all the meta-data from the input items passed through, in addition to the following new piece of meta-data: "OriginalItemSpec", containing the original item spec of the reference.

BeforeBuild and friends


While it isn't specific to VS integration, something else that is missing from the documentation that someone asked me about recently is this comment in the bottom of every VB and C# project:

		 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
	

		 <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
	

		 Other similar extension points exist, see Microsoft.Common.targets.
	

		 <Target Name="BeforeBuild">
	

		 </Target>
	

		 <Target Name="AfterBuild">
	

		 </Target>
	

		 -->
	

What is the full list of such "magic" names? Here's the full list, pulled from microsoft.common.targets:

		 [AfterBuild]
		 [AfterClean]
		 [AfterCompile]
		 [AfterPublish]
		 [AfterRebuild]
		 [AfterResGen]
		 [AfterResolveReferences]
		 [BeforeBuild]
		 [BeforeClean]
		 [BeforeCompile]
		 [BeforePublish]
		 [BeforeRebuild]
		 [BeforeResGen]
		 [BeforeResolveReferences]
	

To use any of these, just define a target with the appropriate magic name and put it below the <Import> tag in your project. Inside the target, use any MSBuild tasks (ours or custom ones) and they will run at the appropriate time.

All of these were created to make it unnecessary in the basic case to add something like this below the import:
		 [<PropertyGroup>]
		    [<ResGenDependsOn>$(ResgenDependsOn);MyTargetName</ResGenDependsOn>]
		 [</PropertyGroup>]
		 <Target Name="MyTargetName"> 
		 ... 
		 </Target>
	

We just did the work for you for some common cases. However, you'll still want to use the "dependsOn" way if you want to have maximum control over where the target goes. Another reason for "dependsOn" is if you want to add more than one target: for example, you have common targets that add a target before ResGen, and you want projects to be able to add a target there as well.