Visual Studio 2010 Migration Post Mortem

I have more or less completed the task of migrating my internal projects to Visual Studio 2010. Native C++ programmers are pretty low on the totem pole of programming coolness these days, but Microsoft did throw us a few bones. At this point I have to say I’m ambivalent overall with VS 2010, but I really like some of the architectural changes and I’m excited about the future.

The Good

The new intellisense database is a huge improvement over the old .ncb file. I’ve had a few hiccups, but in general nothing serious. It still locks up the IDE occasionally, but not nearly as often or as long as previous versions. In previous versions I had to delete corrupted .ncb files all the time; those days appear to be gone in VS 2010.

Despite some shortcomings and the extra work required to make it usable, I love the new (to C++ projects anyway) MSBuild system and the new native multi-targeting feature that came with it. The MSBuild system is completely customizable, flexible, consistent, and standardized (unfortunately all the documentation assumes you’re already familiar with it, so it’s very daunting at first). MSBuild and native multi-targeting were the main reason I decided to move to VS 2010.

The switch away from the single inherited property sheet to the unlimited stack of property sheets is a very nice change, albeit a migration headache. In previous versions, these had to be maintained in a text editor; now they can be managed completely within the IDE using the familiar property page interface. This ranks as my second favorite improvement behind native multi-targeting.

VS 2010 still gets confused when you use the same source files in multiple projects, but less so than previous versions. In previous versions, source code was always parsed in the context of the first listed project of the solution that uses the file. In VS 2010, it is displayed in the context of the project you opened the file from. IMO it should switch with the active project, but at least you can now close a file and reopen it from the other project to view it in the context of the new project. This affects the display of Intellisense errors and graying of code hidden by preprocessor macros.

The Bad

There is no way to permanently turn off the display of Intellisense errors in the error list. You have to wait until one is displayed, then right click in the header area to turn them off. I guess in simple projects it might be useful to leave them on, but in all my projects they are numerous and useless.

The build system gets confused by multiple projects in a solution with different sets of configurations that don’t match the solution configurations one-to-one. Previous versions did too to some extent, but you could always fix these problems in earlier versions by setting build dependencies correctly in the solution file. In VS 2010, I have some projects that simply will not build correctly in some scenarios no matter how they are set. There are several different manifestations of this problem: batch builds that build projects in the wrong order, rebuild all resulting in a project getting cleaned a second time after it has already been rebuilt (hence not being available when a referencing project needs it), and batch builds that don’t build referenced projects which are selected to build but which are not selected in the active solution configuration.

Utility and MakeFile projects cannot have output files set, which means e.g. deployment projects that consume their output will end up empty handed. In addition, they can delete files indiscriminately when cleaning. I found a partial workaround to these problems by changing the project type to Application, and giving each project a unique intermediate directory — but that requires a bit of extra work.

Migrating complex projects is far from automatic. A lot has changed, and while VS 2010 does a decent job of migrating things from earlier versions, I had to do moderate to massive manual work after the migration to every single one of my migrated projects. For example, the migration resulted in odd and incomplete project configurations named “Template” being left in the converted project files that had to be manually removed in a text editor. Build rules required some manual work in some cases. I also had to convert all my Utility and MakeFile projects to Application projects, which required some manual rewiring.

Visual Studio has gotten larger and slower. It takes longer to start than VS 2008, it’s slower to start a debuggee, and some common actions like going to a symbol definition occasionally and unpredictably result in interminable minutes-long delays during which the UI is completely unresponsive.

Visual Studio caches some open files. In some cases, this means that files cannot be deleted until Visual Studio is closed. I’ve also seen cases where the file was not held open, but changes were ignored until Visual Studio was closed and restarted. That one resulted in some hair pulling until I figured out that I have to close and restart Visual Studio if I modify certain MSBuild related files (most notably, *.props files).

The Ugly

Lockups. I’ve had several cases where VS 2010 locked up so tight even task manager couldn’t get a word in edgewise, and I ultimately had to hard reset the computer. Previous versions lock up and crash as well, but I can almost always clear the cobwebs by killing the process. In VS 2010, there are several background worker processes involved as well, and things can get a bit uglier when those background processes get in on the action.

I have never been able to single step a 32-bit debuggee on my 64 bit Windows 7 machine. I was hoping Visual Studio 2010 would fix that, but alas, it’s still broken.

Finally, there is one bug that drives me absolutely nuts. It has dogged Visual Studio since forever, and I’m sorry to say that Visual Studio 2010 still has it. The bug is that certain actions cause every merge module and deployment project to be expanded in Solution Explorer. I meticulously build a solution explorer sand castle by setting the state of every node in my complex and sometimes deeply nested projects. Then suddenly and without warning, something as simple as going to a symbol declaration causes Visual Studio to crawl from one end of the solution to the other, exploding every carefully collapsed deployment project node. It is such a helpless feeling, like watching the waves slowly and tauntingly wash away your sand castle, all the while knowing that you have no choice but to wait patiently then rebuild it again when the storm passes. Why, oh why, didn’t Microsoft finally fix this?

Visual Studio 2010 Native Multi-Targeting

I was hoping that Microsoft would address the need to target earlier versions of Visual Studio within the Visual Studio 2010 IDE, but since they decided to punt, I tackled the problem myself. I’ve released my solution as an open source project named Daffodil for Visual Studio.

With Daffodil installed on your system along with earlier versions of Visual Studio, you can use the new native multi-targeting feature in Visual Studio 2010 to target those earlier versions. This makes it possible to use Visual Studio 2010 for building ObjectARX projects, for example. Daffodil performs essentially the same function that my VC Build Hook utility did in Visual Studio 2008 and 2005.

GlowCode Success Story

I use GlowCode for profiling ObjectARX applications. As far as I know, this is the only profiler that works with AutoCAD. What makes GlowCode special is that it can instrument code on the fly, including a monster like AutoCAD. It has a clunky interface that takes some patience to figure out, but it’s a lifesaver when you need it.

Recently a CADLock customer sent us a drawing file that was apparently not very complicated, yet it took over 20 minutes to create a deep vault. To determine the cause, I used GlowCode to profile the vault creation process. I could see almost immediately that most of the time was being spent in AcDbObjectId::operator ==, which was being called from AcDbObjectIdArray::find.

This turned out to be a classic case of using the wrong type of container. Searching an AcDbObjectIdArray isn’t bad when the array is small, but this drawing contained a special case where the array was very large, and this special case exposed the flaw. I changed the array to a std::set and tested again. The new time was 30 seconds to create the vault — a slight reduction of approximately 95%.

[Full Disclosure: Electric Software has for many years provided me with a complimentary license of GlowCode in exchange for my testing and feedback.]

Visual Studio 2010 Ships

Visual Studio 2010 shipped today accompanied by .NET Framework 4.0. I blogged before about the switch to using the MSBuild build system, and how that theoretically could be helpful in targeting multiple AutoCAD versions from the same solution. The shipping VS 2010 does not support non-Unicode response files, so out-of-the-box it cannot target VC 7.0 (for AutoCAD 2006 and earlier). When time permits, I’m planning to see if I can find a workaround; in the meantime, I’ll continue to use VS 2008 for ObjectARX.

AutoCAD for Mac

There have been rumblings and rumors for a while now about a native Mac OS X port of AutoCAD. The ObjectARX 2011 SDK header files contain clear evidence of a native Mac port in the works. The evidence comes in the form of code comments and changes made to the files so that they work with the GCC compiler and the Mac OS X libraries.

For example, acedads.h conditionally declares a global function to return the main window handle as follows:

#if defined(_WINDEF_) || defined(_ADESK_MAC_)
/* AutoCAD graphics window handle */
HWND adsw_acadMainWnd();
#ifndef adsw_hwndAcad
#define adsw_hwndAcad adsw_acadMainWnd()
#endif

And in acedinpt.h there’s a telling comment:

#ifndef _ADESK_MAC_
#ifndef ACAD_PORT
#ifdef ACAD_API
#define ACAD_PORT _declspec(dllexport)
#else
#define ACAD_PORT
#endif
#endif
#else
// On OS X, we will export all symbols by default and will use GCC
// attributes to exclude symbols we don’t want to export.
// In this case, we do want to export the AcEdInputPoint symbol
#define ACAD_PORT
#endif // _ADESK_MAC_

It’s clear from the type, quantity, and quality of changes that Autodesk has successfully built at least a limited AutoCAD executable for OS X (both 32 and 64 bit). It’s also clear that the Mac build still has limitations, and some of these limitations might require significant changes (i.e. changes of the sort that would break binary compatibility for ObjectARX applications), therefore one could reasonably conclude that no full-blown Mac port is imminent.