- What is a design-time build?
- Targets that run during design-time builds
- Designing targets for use in design-time builds
- Diagnosing design-time builds
What is a design-time build?
Design-time builds are special builds that are launched by the project system to gather just enough information to populate the language service and other project services, such as the references node. Design-time builds are not directly user-initiated, but may be indirectly launched in response to a user action such as changing the project file or build options, or adding/removing source files and references, or switching configurations.
For performance reasons and unlike normal builds, which call the Build target, design-time builds call a limited set of targets. This can lead to custom builds that succeed during a normal build, but end up failing during a design-time build, typically due to custom targets with under-specified dependencies.
Targets that run during design-time builds
|Design-Time Target||Normal Target||Description|
|CompileDesignTime (new project system)/Compile||Compile||Passes command-line arguments, include
The design-time targets are typically simple wrappers around their normal target equivalents, with customized behavior for design-time builds.
Designing targets for use in design-time builds
Targets that dynamically change references, source files or compilation options must run during design-time builds to avoid unexpected behavior in Visual Studio. In contrast, if a target does not contribute these items, then it should actively avoid running in these builds to ensure design-time builds are as fast as possible. Whether a target is run in design-time builds is based on whether a target's
AfterTargets attributes specifies a direct or indirect dependency of any of the above targets. See Diagnosing design-time builds to see logs that help you figure out if your target is being run or not.
Running in a design-time build
If you've determined that your target needs to run in a design-time build, using the above table set
BeforeTargets to the normal target equivalent of what you are contributing to the build. For example, if a target changes
<Reference> items, then it should indicate that it runs before
<Target Name="AddAdditionalReferences" BeforeTargets="ResolveAssemblyReferences"> ... </Target>
AddAdditionalReferences target will run in both normal builds and design-time builds, leading to consistent results between them.
Determining whether a target is run in a design-time build
DesignTimeBuild (CPS-based projects) and
BuildingProject (legacy project system) properties to differentiate between when a target is run in a design-time build versus a normal build. This can be used to avoid expensive calculations or work that is only needed for a normal build.
<Target Name="AddAdditionalReferences" BeforeTargets="ResolveAssemblyReferences"> <PropertyGroup Condition="$(DesignTimeBuild) == true OR $(BuildingProject) != true"> <_AvoidExpensiveCalculation>true</_AvoidExpensiveCalculation> </PropertyGroup> ... </Target>
NOTE: The DesignTimeBuild property is typically empty ('') inside of a normal build, so avoid comparisons to
Specifying explicit dependencies
If your target has dependencies on properties, items or files produced during the build, it must have an accurate
DependsOnTargets attribute that indicates the set of targets that produce those assets. An under-specified
DependsOnTargets will lead to unexpected behavior, such as targets that fail on the first design-time build or fail during every design-time build.
Diagnosing design-time builds
Signs that a design-time build is failing or taking too long
While the results of design-time builds are not directly visible by default, the following symptoms are good indicators that one is failing for a given project:
- Source files in a project are marked as coming from the
Miscellaneous Filesproject when opened in the editor
- IntelliSense shows incomplete and/or incorrect results
- A normal build succeeds inside and outside of Visual Studio, yet the Error List continues to show build errors
The following are symptoms of a design-time build that is taking too long:
- Making modifications to project, such as renaming, adding or deleting files take a large amount of time
- Switching build configurations, for example, from Debug to Release, takes large amounts of time
Getting Visual Studio to output the results of a design-time build
You can force Visual Studio to show the results of a design-time build using the following instructions:
Visual Studio 2015 or below
- Delete the
.vsdirectory that sits alongside the solution that is experiencing the problem
- Start a Developer Command Prompt for VS2015
- At the prompt, run
- At the prompt, run 'devenv'
- Open the solution
- Under %TEMP%, look for [RANDOMGUID].designtime.log files, these will contain the results of the design-time build. If running Visual Studio 2015 Update 2 or higher, the name of the project and design-time target that is being called will also be included in the file name.
Visual Studio 2017 (version 15.3 or earlier)
In Visual Studio 2017 there are two C# and Visual Basic project systems. By default the majority of projects (.NET Framework, UWP, etc) continue to open in the same project system as previous versions of Visual Studio, and hence the instructions are the same as above.
The new .NET Core and .NET Standard project types, however, open in the new project system and you can use the following steps to see the results of design-time builds:
- Close all instances of Visual Studio
- Download the following script: DesignTimeBuildOutputPane.cmd
- From a elevated Visual Studio command-prompt, run the following:
- Open the solution in Visual Studio
The results of the design time build will appear in a new category called Build - Design-time in the Output window. The verbosity of the category respects the same settings under Tools -> Options -> Project and Solutions -> Build and Run as normal builds.
To turn off this pane:
- From a elevated Visual Studio command-prompt, run the following:
Visual Studio 2017 (version 15.4 or later)
- Install the Project System Tools extension
- In Visual Studio, choose the
View > Other Windows > Build Loggingmenu item.
- Click on the "play" button.
This will cause design time builds to show up in the build logging tool window. If you have the MSBuild Binary and Structured Log Viewer installed, you can double-click on a log to view it in the viewer, otherwise you can right-click and choose
Save As... to save the log in the new binary log format.
Diagnosing why a design-time build is failing or taking too long
After following the above instructions, open the resulting build log file or Output window (for the new project system).
Failing design-time build
For a failing build, look for errors at the end of the log:
Build FAILED. c:\Projects\MyProject\MyProject.csproj(17,5): error : An error occurred! 0 Warning(s) 1 Error(s)
These errors indicate that a target failed, typically this is due to targets that have not correctly specified their dependencies.
Slow design-time build
For a slow design-time, look for the target performance summary at end of the long which can indicate long running tasks and targets:
Target Performance Summary: 0 ms AfterClean 1 calls 0 ms Clean 1 calls 0 ms CleanReferencedProjects 1 calls 0 ms CleanPublishFolder 1 calls 0 ms BeforeRebuild 1 calls 0 ms BeforeClean 1 calls 0 ms BeforeBuild 1 calls 0 ms _SplitProjectReferencesByFileExistence 1 calls 1 ms CleanXsdCodeGen 1 calls 2 ms AssignProjectConfiguration 1 calls 7 ms CoreClean 1 calls 10 ms _CheckForInvalidConfigurationAndPlatform 1 calls Task Performance Summary: 0 ms RemoveDuplicates 1 calls 0 ms Error 1 calls 1 ms MakeDir 1 calls 1 ms Message 2 calls 1 ms ReadLinesFromFile 1 calls 1 ms WriteLinesToFile 1 calls 1 ms FindUnderPath 2 calls 1 ms AssignProjectConfiguration 1 calls 2 ms Delete 3 calls