Incremental build in Rider

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!

Rider incremental build

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:

Build tool window

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.

Enable incremental build to speed up build time

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.

Configure MSBuild toolset to be used

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!

Comments below can no longer be edited.

8 Responses to Incremental build in Rider

  1. Avatar

    vaskir says:

    May 24, 2017

    It seems the screenshots are from an older Rider version? EAP 22 settings dialog look like this

    • Avatar

      Maarten Balliauw says:

      May 25, 2017

      You are correct! Updated the screenshots to latest version.

  2. Avatar

    Some user says:

    May 26, 2017

    When it works it’s nice, but now incermental build is not picking up some changes – you never know your code is wrong and doesnt work, or it isn’t just built.
    It’s faster workflow to just rebuild everything.
    This is happening in 2017.1 EAP, worked in earlier versions.

    • Avatar

      Joe says:

      May 29, 2017

      I agree. This seems to be performing poorly of late.

      • Avatar

        Maarten Balliauw says:

        May 29, 2017

        Hi Joe,

        Would you happen to have a repro somehow? Would hep us to investigate.

        (and worst case you can always disable ReSharper build from the settings)

        Best regards,

  3. Avatar

    Markus Schaber says:

    June 8, 2017

    In our use case, it doesn’t work well.

    In our framework, we have two kinds of assemblies – plugins and others. For the plugins, all the dependencies (the other assemblies) are copied to the output directory via the appropriate setting at the project reference. Then we have a post-build step which installs the plugin with all dependencies in the target location.

    Now, when a non-plugin changes, but the public API stays the same, the plugin is not rebuilt, thus the post build-step with the installation is not executed.

Discover more