Getting Visibility into Design-Time Builds

In my last blog post, I talked about design-time builds and why you should care about them. But one of the biggest problems with design-time builds is that they are invisible. They run in the background and you don’t get any feedback that anything is going on (except, maybe, that Visual Studio seems to be a bit slower while they run). And if they fail, there’s no way to determine that that happened and no way to determine what went wrong.

To address some of these issues, the project system team has now published a new Visual Studio extension that can help: Project System Tools. This extension is a place where the project system team can add tools that make working with the project system better. The first tool that we’ve added to the extension is the Build Logging tool window. When you pull down the View menu item, under “Other Windows” there will now be a “Build Logging” choice. If you choose that you’ll see a tool window come up:

When you hit the “play” button on the toolbar, the build logging window will start recording build logs for all builds that happen in Visual Studio, including design-time builds! In the window, you’ll be able to see:

  • The project that was built
  • The type of project (csproj, vbproj, etc.)
  • The “dimensions” of the build (x86, AnyCPU, Debug, Release, etc.)
  • The top-level targets that were built
  • Whether the build was a design-time build
  • Start time and elapsed time
  • Whether build succeeded or failed (or is still running, for that matter)

The build logs are saved in the new MSBuild binary log format. If you double-click on a build log entry, we’ll try and open the binlog file using whatever viewer is registered. (I suggest installing Kirill Osenkov’s MSBuild Log Viewer) You can also right-click on the log and save it to a location of your choice, which can be handy for passing around build logs.

One thing to note is that because the Build Logging window depends on new APIs that were added to Visual Studio in the 15.4 release, you will only be able to install the extension on the most up-to-date version of Visual Studio 15 (or one of the Preview builds).

Try it out and let us know what you think! The project system tools are open source, so you can contribute to them if you go to our repo: https://github.com/dotnet/project-system-tools. We also have some more ideas of things to add, so stay tuned!

You can also follow me on Twitter here.

The Scourge of Design-Time Builds

Part of my job on the Visual Studio project system lately has been looking at the speed at which Visual Studio opens solutions containing managed language projects (such as C# and VB). As with many things, over time this common operation has gotten slower, and we would like to put some spring back in it’s step since everyone (including us!) have to open solutions all day every day.

As we’ve started to look at the various things that go on when you open a solution, one of the most obvious things we had to look at is something called design-time builds. Design-time builds are probably one of the least known and least understood things that go on in Visual Studio, and yet they often can have a real impact on how fast the Visual Studio UI responds (and not just on solution load!). I thought I’d take a minute to explain what design-time builds are and why you should care about them.

The origins of design-time builds comes from the fact that the Visual Studio build system (aka MSBuild) is not a fully declarative system. That is, you can’t just look at a .csproj file or .vbproj file and immediately understand everything you might want to know about how that project is going to build. In particular, you might not know the following:

  • Given an assembly reference in the project file, what assembly on disk is that reference going to actually refer to at compile time?
  • Given a XAML file, what is the code that is going to be generated by the XAML compiler at compile time going to look like?
  • Given a glob file pattern (*.cs), what files are actually going to be included at compile time?

And these questions aren’t just academic — if you’d like to get a nice Intellisense experience (or all the other editor enhancements that you get from the compiler), then the compiler has to be able to answer those questions before you ever get to compiling your project. If it can’t get those answers, then it can’t see all the code and assemblies that make up your project, and therefore it can’t give you help in the editor.

So, what to do? Well, obviously, if you need to know what’s going to happen in a build, why not just run it? And so you get design-time builds. Unbeknownst to most users, Visual Studio builds your projects a lot more than you think. Potentially every time you make a change to a project that will affect how the project is built, Visual Studio will fire off a design-time build in the background. Now, there are a few differences in how design-time builds work from regular builds. In particular:

  • The design-time build doesn’t actually run the C# or VB compiler because it doesn’t need to produce the actual output (i.e. dll or exe). It just needs to know how the build would be run. So instead of, say, calling csc.exe, it will just tell MSBuild to let it know what it would have asked csc.exe to compile without actually compiling it.
  • The design-time build runs a slightly different set of MSBuild targets from a regular compile. This allows skipping things that aren’t needed in a design-time build, plus it allows the project system to run some additional targets (if needed) to provide extra information that the project system might need for, say, the Solution Explorer.

Design-time builds have two obvious issues. First, if they’re slow, it’s going to slow down Visual Studio but you won’t be able to tell where the problem is coming from. For example, a common place where slow design-time builds show up is switching between configurations. If you switch a large solution, say, from Debug to Release in Visual Studio, you might notice quite a long pause in which you can’t do anything in the UI. This is usually due to the configuration change kicking off a whole bunch of design-time builds to react to the fact that things in the project now might look different under the new configuration.

The other issue is if a design-time build fails. Since the compiler and the project system rely on design-time builds to accurately understand the contents of your solution, if design-time builds fail, things might start going wrong in the Visual Studio UI. The Solution Explorer might not show all of your files, or it might show them in the wrong place. Intellisense might not show you everything available, or it might show you nothing at all. You might get weird errors in the Error List. Often these kinds of problems can be traced back to a failing design-time build. The problem, as with performance issues, is that there’s no visible indication that that’s what the problem is.

So… Design-time builds are a necessary evil that can really mess things up if they go wrong. What can we do about it? Stay tuned…

You can also follow me on Twitter here.

Understanding your dependencies better in Visual Studio 15

Since coming back to the Visual Studio Languages team recently, I’ve been working on features for Visual Studio 15 that aren’t really ready for public testing yet. But we’ve now put up a teaser blog post, ‘A Vision For Visual Studio “15”: Take on Dependencies. Stay Productive.‘, that covers some of the things I’ve been working on.

Specifically, we’re looking at ways that Visual Studio can provide better navigability for dependencies that you take on library that have source available in places like GitHub or TFS. When using, say, JSON.NET, it would be nice to be able to do F12 and go the definition of something without having to clone the repo and figuring out how to compile it correctly. And it would be nice to be able to see usages of JSON.NET APIs across open source dependencies to be able to see how other people are using the APIs.

The idea behind it is to leverage Roslyn to extract semantic information about open source libraries (starting, of course, with Roslyn itself) and then make that information available to Visual Studio language services just as if those projects were in your solution. We’re still in the earlier phases of this work, but we should hopefully have something soon you can actually play with…

You should also follow me on Twitter here.

You Can Go Home Again (or, Returning to Programming Languages)

About a year and a half after doing something I swore I’d never, ever do, I have to admit… it didn’t stick. While working in Windows during the Windows 10 initial cycle was fascinating and fun, it turns out that I just miss working in programming languages too much to become a long-term member of the Windows team. I had a great time working with some great people (and a few of the things I worked on are just about going to go public…), but in the end, I’ve been lured back to the PL world.

Interestingly, I’ve decided to return to the team I left seven-odd years ago just as they were beginning to start this crazy re-write of the VB and C# compilers into managed code. Now that Roslyn has shipped, I felt it was finally safe to return… So I’ve accepted a position back on the Visual Languages team. I don’t plan on doing anything specific with Visual Basic — that language is in very good hands at the moment — but will be working on some ideas about how we might leverage Roslyn to do some interesting stuff. More information to come as it becomes available!

You should also follow me on Twitter here.

Edge JsRT: Miscellany

To close out the series on Edge JsRT, there are two minor APIs that were added that didn’t fit any of the other categories.

Filling in a hole I accidentally left when I originally did the APIs, JsNumberToInt allow extracting an integer value from a JS Number value.

And to aid in debugging and other diagnostics, JsCreateNamedFunction allows creating a function that has a name associated with it that will show up in callstacks, toString, etc.

You should also follow me on Twitter here.

Edge JsRT: Universal Windows Platform

The last major chunk of new APIs in Edge JsRT relate to the Universal Windows Platform, or UWP. Hopefully, you’re familiar with the UWP already, but if not, the UWP is the “modern” way of building Windows applications that go into the Windows Store. (Thus, UWP apps are also called “Store apps”.) At it’s most basic, the UWP is a set of curated APIs that UWP applications can use to talk to the system. UWP APIs are built in a special way (similar to the way .NET APIs are built) that allow them to be written once and then be usable in C++/CX, JavaScript, and C#/VB.

The way that UWP APIs are exposed in each language is called projection. To make projection work, each language has a special piece of code that knows how to take a UWP API and make it appear correctly to programs written in that language. To turn on that special code in Chakra requires some calls that were not available to JsRT hosts in the past, but which have now been exposed in Edge JsRT. The main one is called JsProjectWinRTNamespace. (WinRT is yet another legacy name for the UWP.)

JsProjectWinRTNamespace will take a root UWP namespace (such as “Windows”) and project it into the current context, making that namespace available in the global JS namespace. Great, right! Well, there’s one catch: unless your host is a UWP application (i.e. a Store app), you can only project the Windows namespace. That’s because projecting anything outside of the Windows namespace requires loading some UWP component that supports that namespace. And UWP components can only be loaded by UWP applications. This is a somewhat entirely arbitrary restriction, but since the UWP platform is built that way, oh well. It does mean that non-UWP hosts can still get access to some useful UWP system APIs.

The other API is a little more esoteric, but still important. JsSetProjectionEnqueueCallback is needed to support asynchronous UWP APIs. If you’ve been following along at home, you’ll remember that my previous post talked about setting up a callback that allows asynchronous JavaScript APIs to let you know to run some code when an ES6 async API is finished. Well, this is basically the same thing, but for the UWP platform as opposed to ES6. So go back to read that post if you want to understand a bit more what this is for. The shape is slightly different (confusingly) but the purpose is basically the same.

You should also follow me on Twitter here.