My History of Visual Studio (Part 1)
[All the other Parts: History of Visual Studio]
I wrote in the teaser that there is no one “History of Visual Studio”, there are as many histories as there were people involved. If I may repurpose a famous quote, “There are eight million stories in the Naked City...” This is one of them.
Visual Studio’s history probably begins in 1975 with Bill and Paul’s decision to create Altair BASIC. Maybe you could start before that but I think that’s as far back as you could go and still say it’s about Visual Studio at all – it’s at that time that Microsoft decided it was going to have software development products and not, say, toaster automation.
Old timers like me used MS-BASIC on many different classic microcomputers, for me it was mostly the Commodore PET (I started on the PET 2001 model, whose name is especially ironic considering how unrepresentative it is of a 2001 era computer but I digress). You could have used MS BASIC on an Apple, or a TRS-80. Many of us cut our teeth on those computers, and the idea of rich immediate feedback, a sort of personal programming experience was branded on us.
Those of us that really wanted to know what made a computer tick (literally) would spend countless hours tearing apart the software that made them run; I’m fond of saying that Bill Gates taught me 6502 assembly language by proxy and so was training me for my job at Microsoft years later.
The 80s were a time of genetic diversity in computers, and so in programming tools as well. Lots of people were making programming languages and I’m going to avoid dropping names to stay out of trouble with trademark holders but I think you can remember many different first class systems for the computers of the time. I can think of at least 5 off the top of my head.
If you were creating tools for the PC, which was starting to be the dominant machine by the middle of the 80s, your life was especially difficult. The x86 instruction set wasn’t terribly fun; the machine architecture with its 64k memory segments was enough to give you a migraine. These challenges, and the need to milk every bit of performance out of processors, resulted in very bizarre PC-specific language constructs.
It’s 1988 and I landed at Microsoft fresh out of college, I had my own PASCAL compiler under my belt (built with 4 friends in school), and an assembler and linker to boot. But I was not ready for:
char _near * far pascal GetString(char far * far * lplpch);
For starters, what the heck was a Pascal keyword doing in my C programming language? The only thing Visual about this thing was that the nears and fars were making me wish for bifocals (recently granted, and I was better off without them).
I need to rewind a bit.
The compiler that I was using to do my job in 1988 was Microsoft C 5.1 – a great little language and maybe one of our more successful releases. Microsoft had enjoyed considerable success in the languages space leading up to that time but in recent years, and for some time to come, a certain company, whose name starts with a B, was eating our lunch. Great tools, great prices, it was very motivational in Buildings 3 & 4 on the Redmond campus.
So the C product was already on its 5th major release. The basic compiler “BC6” had just shipped and Quick Basic “QB4” was going out the door.
You may have noticed I’m not mentioning C++ yet. We’re still a goodly distance from that part of the story.
So where am I? Ah yes, 1988. The project I’d been hired to work on was cancelled after a few months (I expect I’m in good company on that score), that project by the way was a cute variant on the C language designed for incremental compilation – it was called, cough, C#. Strangely, through the lens of 2009, it looks remarkably like what you would get if you tried to make C.Net.
The mainstream project at that time was C6.0, it featured a bunch of cool things, new compiler optimizations, better debugging, and more. Its primary target was an operating system called OS/2 – you may have heard of it – but it also had to run well on DOS. A tall order that.
I was working on the programming environment, in particular on the source browser, largely because I had worked on the source browser for the C# system and people liked it and many of its ideas had found their way into the C6 product already. I suppose nobody will be surprised that one of the first things I had to do was improve the performance of the thing.
Anyway the programming environment, arguably the first IDE we ever shipped, was called “PWB” or programmer’s workbench. It was all character mode graphics but it used that funky Character Windows thing that was prevalent in the flagship applications Microsoft was shipping at the time. CW, or just COW as we lovingly called it, was a delightful environment that provided all kinds of automatic code swapping (but not data) to allow you to have more than 640k of total code while still running on a regular PC. Its swapping system bears a lot of resemblance to what was in the real Windows of that era (2.4.x I think it was).
Now the thing about having only 640k of memory and trying to have an IDE is that you can’t actually expect the thing to be loaded and running while you’re doing something like a build, or debugging, or basically anything other than editing really because you simply don’t have the memory. So this beauty used some very slick tricks – like for instance to do a build it would first figure out what build steps were needed, write them to a file, then exit, leaving only a small stub to execute those steps, run the steps, and then as the last step restore itself to exactly where it had been when it exited having created the illusion that it was resident the whole time, which it was not.
Debugging used even more sleight of hand.
I think the Codeview debugger may be one of the first, and possibly the most important DOS Extended applications ever written (because of influence). You see the debugger is in a difficult position because it needs to have symbols and other supporting data active at the same time as your program is running, and it doesn’t want to disturb that program very much if it can avoid it. This is quite a challenge given that memory is as tight as it is – but there was a bit of an escape clause. Even in say 1989 you could use features on your 386 processor (if you had one) to get access to memory above the 640k mark. These kinds of shenanigans were commonly called “using a DOS extender” and I think the Codeview debugger probably had one of the first ever written, and I think a bunch of that code later inspired (who knows) the extension code in another product you may be familiar with – that would be Windows 3.0. But that is really another story.
All right so optionally dos extended character mode debugger with character mode editor and build system that makes the product exit to do anything. Get all the bugs out of it and presto you have the first MS IDE.
Lots of languages built on PWB, it was designed to support a variety of them. I know the Browser formats supported Basic, Pascal, FORTRAN, COBOL, and C style symbols out of the box. Most of those actually saw the light of day at one time or another.
That was spring of 1990 and that was C6.0. That IDE was the basis for the compiled languages for some time.
However, things were not standing still.
C++ was taking the world by storm, and having a high quality optimizing C compiler was old news, but lucky for us we had not been idle during this time. While some of us had been busy getting C6.0 ready others had been busily working on a C++ front end for our compilation system. I think mostly everyone was sure we could finish up that C++ compiler in no time at all (I say mostly because there were people who knew better).
Wow, were we wrong. I mean, seriously, majorly, what-were-we-THINKING wrong.
It turns out C++ is a hard language to compile; heck it’s a hard language to even understand. I remember this one particular conversation about how tricky pointers-to-members are with eye-popping results when it was pointed out that one of those things could point to a member defined in a virtual base… C++ is like that, a lot of things seem easy until you combine them with other things and then they get hard.
Meanwhile we were struggling to get the needed features into the debugger stack, it turns out that creating a C++ expression evaluator is no easy feat either. Expression evaluators are lovely things – they are frequently called upon to evaluate expressions that would be illegal in any actual compilation context (e.g. find me the value of a static variable that is currently out of scope, or the value of a global defined in another module). Expression evaluators have to do all these things while still retaining the feel of the language and remaining responsive.
Did I mention all this could be slow?
I was working on a new development environment, targeting the new 3.0 release of Windows – another project that never saw the light of day – but we were having fits trying to get windows.h to compile in anything like a decent amount of time.
That’s when the precompiled headers miracle happened.
I call it that because the .pch literally revolutionized the way we built things with our tools. Other system had used similar systems in the past but ours had some very clever notions. The most important of which was that since it was snapshot based it guaranteed that the net effect of the headers up to the PCH point was absolutely identical in every compiland. That meant that, for instance, you could exactly share the debugging and browsing information as well as all the compiler internal state. The fact that when you #include something you may or may not get the same net effect in one file as in another is the bane of your existence as a tools person and this was immediate relief! And it was fast!!!
I’m not name-dropping but suffice to say I know the person who did this work very well and I was one of those weekend miracle deals that you read about, it couldn’t be done, can’t be done, oh wait there it is.
Meanwhile, yet another team was working on a little something called Quick C for Windows which turned out to be hugely important. A lot of ground breaking work went into that product, it was the first IDE for windows with real debugging, but I’d have to say it was incomplete and I’ll talk more about why that is hard in just a second.
Meanwhile that other company was not standing still and they were delivering great C++ compilers. It was 1992 before we had anything at all. In those months we delivered C7 on top of PWB again (PWB 2.0) and blink-and-you-missed it, we delivered Quick C for Windows (QCW).
My project was cancelled. Again. It’s a good thing had my fingers in a lot of pots :)
By the way, the C7 product was, by mass, I believe, the heaviest thing we ever shipped. I don’t think we ever tried to deliver that many books ever again.
So we shipped a bookshelf and now things were getting interesting.
We couldn’t ship PWB again, we needed a graphical development environment, our basis for this was going to be QCW and work was already underway to generalize it but oh-my-goodness there was a lot of work there. Also, we were missing some critical C++ language features; the competition was not standing still. We had a very limited class library that shipped with C7, MFC 1.0. We needed an answer there, too. And did I mention that we needed a speed boost?
Any of these bits of work would be daunting, but let me talk about just a few of them. First, debugging.
Debugging 16 bit windows (it would be Win3.1 by the time we were done) is nothing short of a miracle. Win16 is cooperatively scheduled, it has no “threads” per se, there is just one thread of execution. Now think about that, what that means is that you can’t ever actually stop a process, if you do the entire world stops. So if you’re trying to write a GUI debugger actually stopping the debuggee is sort of counterproductive. So, instead, you have to make it LOOK like you stopped the debuggee but actually you didn’t, you let it keep running, only it isn’t running any of the user’s code it is running some fairly (hopefully) innocuous debugger code that keeps it dispatching messages, lets the debugger run and doesn’t actually proceed with the user's whatever-it-was-they-were-doing.
A tiny part of this miracle is that when the debuggee “stops” you have to, on the fly, subclass each and every one of its windows and replace its window proc with something that draws white if asked, queues up important messages to be delivered later, and mostly does a lot of default processing that is hopefully not too awful. That’s quite a trick of course when any running process could be trying to send messages to the thing for say DDE or OLE or something. It’s the miracle of what we call “soft mode debugging” and that’s what we delivered.
Meanwhile, the tools… Well there was this thing called Windows NT going on, maybe you’ve heard of it, we didn’t want to produce all different kinds of binaries for hosting in different environments so we needed to change our dos extension technology to be something that allowed us to run Windows NT character mode binaries on DOS. That’s exciting. And it had to be regular vanilla DOS or DOS as running inside of Windows. Double the excitement. But sure, we did that too (with quite a bit of help from a 3rd party that again I’m not naming because I don’t want to go there).
And the tools were too slow. Yet another effort went into putting codeview information into .pdb files to alleviate the painful de-duplication of debug info that was the cvpack step; those steps were then fused directly into the linker so that we didn’t write out the uncompressed stuff only to read it back in and compress it, so we could write it out again. Add that to some practical compiler changes and we were, for the first time in a very long time, the fastest C++ compiler out there (at least according to our own internal labs, YMMV).
Meanwhile MFC was coming along very nicely thank you very much. And there was a designer and a couple of critical wizards and wow this thing was starting to feel like VB: draw, click, wire done.
I really should say something about VB.
The code name for Visual Basic 1.0 was Thunder. I thought it was arrogant when I first heard it. I thought their “Feel the Thunder” attitude was just some cocky boy swagger. I was wrong.
There was a reason every product wanted to be like Visual Basic, they changed their names to Visual <whatever> and tried to get that feel for their programmers. It was because it was just that good. Not everyone had that hot-while-you-type interpreter action going on in their environment but boy was everyone trying to recreate the key elements in their space. We certainly were. By the time we were done Visual Basic had profoundly affected the design experience and the framework – it wasn’t VB but it was Visual – it was Visual C++ (that’s C8 and MFC2 if you’re keeping score.)
We did a very fun follow-on release where we got the 16 bit tools working under Windows NT in 16 bit mode (kudos to their compat people, we were not an easy application to port) and we added more OLE and ODBC support. People were really liking this thing and for the first time since I had been at Microsoft I felt like we had the edge against our competitors in the C/C++ tools space. We were still missing language features but what we had was pretty darn cool.
While that was going on, a few of our number were doing something else that was pretty darn cool. They were porting all this stuff to 32 bits and getting it to run natively on Windows NT. That would be around the Windows NT 3.5 time-frame. That and getting a Japanese version out and generally fixing all of our bad “that doesn’t work internationally” practices. Very important, totally underappreciated work that was.
So Visual C++ “1.1” the NT version was available at about the same time as 1.5, as was the J version.
I guess I would be remiss if I just left it at that. Internally some people thought "1.1" wasn’t a real product it was “just a port.” These are people who clearly know nothing about development tools. The 1.1 system included a totally new 32 bit compiler back end. We all know just how portable back-ends are, especially against totally diverse machine architectures. Oh and it also included a totally new debugger back end with a totally different theory of operation – because of course Windows NT *does* have threads that you can stop. Oh and of course the memory model for the whole program was different – far and near were gone. But ya, other than those few minor things, it was just a port.
That was 1993 and we called the product “Barracuda” – I had not much to do with it personally but those guys deserve a salute in the History.
Things are about to get really exciting though; The most important release of the C++ toolset in my memory is VC++ 1.0 “Caviar” – without it I think our tools would have died. But almost as important, is the next release which I’ll write about in the next installment. VC++ 2.0 “Dolphin” which truly integrated things for the first time.
[I would really be tickled if other people would write their own "My History of VS", either in the comments or on their blog or anywhere they like]
[See The Documentary on Channel 9!