In my opinion, the best features are just a checkbox that enables powerful scenarios. Rider has features like this, and one of them is called incremental build. Behold!
Incremental build reduces the time needed to build a solution by only building projects that need updating. This helps us stay “in the zone”: the quicker we can rebuild a solution, the quicker we get compilation feedback, the quicker we can run unit tests, the sooner we can move on to working and improving our code.
We’ve seen the checkbox, now let’s look behind the curtains and find out how incremental build works!
How does incremental build work?
Rider’s incremental build is the same as ReSharper Build. It manages the build process in the IDE, and decides if an individual project needs to be built, or not. The fastest way of making sure builds run faster, is not building at all. Very often, only one or two projects we’ve just made changes in needs to be rebuilt, instead of the entire 20-project solution.
Incremental build does not replace MSBuild (or XBuild) – it simply decides on which projects will have to build and which ones are up to date. Incremental build still calls into MSBuild to perform the actual work. This means we’ll get the same warnings and errors we know and love:
So how does it work? Why wouldn’t it be enough to just use MSBuild support for incremental builds? Good question! MSBuild compares the timestamps of inputs and outputs of a build target, and skips running the target if it’s still up to date. So far so good, except that MSBuild still has to be invoked on all projects to decide whether to build or do nothing.
Rider monitors timestamps and continuously tracks inputs and outputs to tasks, targets and projects, as well as changes happening on the file system. When we start a build in the IDE, it already knows which projects are still up to date and which have changes. Incremental build can then immediately decide whether to run MSBuild or skip a particular project.
Next to monitoring freshness, Rider’s incremental build also checks the public API surface of a project for changes. When a project is edited and rebuilt, MSBuild typically also rebuilds all projects that reference this project. This is a great thing if we are changing the name or the number of parameters passed to a public method or if we’re adding new types, but it has no value if we’re just changing some internal business logic.
Right after compiling a project, incremental build will scan the compiled output assembly. If its public API did not change, Rider knows it does not have to rebuild any of the referencing projects and can safely skip them. If a class, interface or method is not required to be
public, making it
internal will reduce the public API surface. This will even further reduce unnecessary builds.
So by using intelligent timestamping and monitoring as well as tracking the public API surface of our assemblies, Rider’s incremental build can reliably skip compilation for projects that do not need compilation, resulting in a much faster build process.
Configuring incremental build
As mentioned before, incremental build is “just a checkbox”. Rider comes with incremental build enabled by default. In the settings under Build, Execution, Deployment | Toolset and Build, we can choose to change this. Enabling it will make use of incremental build’s smart heuristics while disabling it will fall back to just using MSBuild (or XBuild) all the way.
Of course, incremental build also has to know which toolset to use. Under Build, Execution, Deployment | Toolset and build, we can configure which version of MSBuild or XBuild should be used by Rider. We can pick one of the toolsets that were found in our system, or provide the full path to a custom one.
Are there any limitations?
Rider incremental build supports most .NET project types and languages that are MSBuild-based (C#, VB.NET, F#, C++). Yes, that also means .NET Core projects are supported. There are a few technical limitations though:
- Non-MSBuild projects are not supported. For example, folder-based Web Site projects or WinJS projects are not supported. When any of these project types is found in a solution, Rider will fall back to the default build process.
- Custom build steps are not supported. Typically, custom build steps contain various commands like executing command line tools, copying files, … Incremental build can not track the custom build task logic nor their input and output.
When in the flow, nobody wants to be interrupted or have excuses for slacking due to slow compilation. Rider’s incremental build will greatly speed up the build process, making sure we can stay in the flow.
Download the latest Rider EAP build and try out incremental build! We’d love to hear your thoughts and feedback!