Integrating Build and Developer Studio
Ó 1996-1997 OSR Open Systems Resources, Inc.
Code samples for this article are also available online.
Soon after I started working on commercial products targeted for the Windows NT operating system, I realized that there was no way that I was going to put up with the hideous command line oriented build shells that come with the NT DDK. I like nice, gui-oriented, integrated development environments reminiscent of the Unix days with an X terminal with XEmacs running on it to glue together everything from my email to source code control.
Environment
There are a couple of small features that I insist on in order to do serious software development:
I demand syntax coloring. I want my RGB. There is no way I am going to stare at monochrome pages of source code. I would go blind. I’m not kidding.
I insist on automated browsing. I personally can’t remember more than about 3 or 4 things at any point in time, so navigating quickly from an object to its definition with a click of the mouse is just about my speed. I surround myself with computers to extend my mental capabilities, not strain them.
When I get a compilation error, it is non-negotiable that I must be able to click on the error message and have my nose rubbed in my own stupid code errors. I will never again count lines or demand that my editor insert hideous line numbers into the source display. The same goes for getting syntax for an API interface. I must be able to cut and paste from the description of the interface into the source code I am editing, without any major shuffling of display real estate.
My team must use software repositories and automated build facilities. I don’t know about you, but for me source code control works like this: when I attempt to alter a file, if the file is under source code control it gets checked out. This method, it turns out, is one of the best practices in software engineering for testing the validity of source code modifications. In other words, you and I should always have our checked-in source code under some sort of regularly scheduled build discipline.
I refuse to use more than one basic programming environment per operating system. You won’t catch me using one set of tools to create drivers and then a totally different set of tools to create the applications that use those drivers. I have enough trouble keeping one set of tools house trained.
Oh yes, one final thing: if the operating system vendor says that device drivers must be built using the vendor supplied build utilities, then well of course all of the features above must work in conjunction with the vendor supplied build utilities.
Limitations
Now it turns out that Microsoft Developer Studio (Visual C++ 4.x aka MSDS) together with Source Safe (or another source code control tool that is compatible with Developer Studio), does everything I want…er, almost everything. For some reason (which I cannot fathom and care not to comment on), there is no support in Developer Studio for building device drivers (Oh yes and the editor is a little lacking in the extensibility department, but so much else is right with Developer Studio that I am willing to ignore this).
Yes, I’ve seen the stuff put forth by MSDN about how you can hack driver support into Developer Studio. How charming. I really want to hack device drivers. I don’t know about your customers, but our customers actually get upset when our products don’t work. I’d much rather use processes that are not in the category of Use At Your Own Risk. Oh yes, and there are a few other small things, like support. Just suppose you happen to trip over a defect in NT while testing your device driver and wish to have Microsoft actually support you in resolving this claim. I think that if I were Microsoft, I wouldn’t even start to listen to your problem until your device driver was built using the supported build utilities.
Solution
So, here is what I did, and in retrospect, it wasn’t a big deal. Rather than some hard to get right and fragile custom build procedure, all I use is one shell script, ddkbuild.bat, and the external Makefile project type in Developer Studio for my driver development.
The shell script is rather simple (given that it uses the dreadful DOS shell, it must be simple): It takes a couple of command line arguments, runs the setenv.bat file from the DDK, and produces a build for you (free or checked, as you command). The script then does some postprocessing of the output from build, and creates browse files for you (if you are nice). Finally ddkbuild confronts you with all of your stupid coding errors. (FYI, all of this occurs inside the MSDS IDE). When ddkbuild completes, you just click on an error message and you are beamed right up to your error. There are two major limitations: You have to have your source tree in the DDK distribution tree, and your drivers are placed in %BASEDIR%\lib\ (you have no choice in this decision). Feel free to modify ddkbuild to overcome these limitations, or to extend it in any way you see fit.
Using ddkbuild.bat
In order to understand the ddkbuild process let’s walk through the creation of a simple dd. project.
Startup MSDS and select File/NEW/Project Workspace.
From the New Project Workspace dialogue select Makefile as the project type. Choose a name for your project (I’m using demo) and a location within the dd. tree. For my example, the location is C:\DDK\src\osr\demo. Click Create... and select Yes when MSDS asks if you want to specify command line settings. You should be at the Project Settings dialogue (shown the next picture.).
For the debug build, your task is to make your window look as follows:
(The Build command line should read ddkbuild checked %BASEDIR%\src\osr\demo, the Rebuild all line should read -cf, the Output file name is not needed but I used demo.sys in the example, and finally the Browse info file name is demo.bsc), and like figure z for the free build.
The only change between the Debug and Release versions is that the Build command line for the Release version replaces checked with free.
OK. So far pretty easy, right? Now there are one or two other steps you need to take. First, make sure that you have the DDK bin directory in your MSDS path. (Look at the Tools\Options\Directories dialogue – mine looks like figure xx).
You may also want to set the include directories here as well (shown in figure yy).
Now start adding files into your project. For my example lets just have two files: demo.c and SOURCES. The contents of the SOURCES file for this project look like this:
MAJORCOMP=ntos
MINORCOMP=demo
NT_UP=0
TARGETNAME=demo
TARGETPATH=$(BASEDIR)\lib
TARGETTYPE=DRIVER
INCLUDES=$(BASEDIR)\inc
MSC_WARNING_LEVEL=/W3 /WX /FR /FAcs
SOURCES=\
demo.c
We need some driver source code, of course. I just plunked the simple driver from the dd. samples (%BASEDIR%\src\simple\sys\ldunld.c) into demo.c, which ought to do for now.
We aren’t quite ready to build yet, though. You need to copy the Makefile template into the build directory. Now you should be able to just click on the build menu in MSDS and build should be invoked for you. If all works well, you ought to get some output in your build window in MSDS like that shown in figure zz.
-------------------Configuration: demo - Win32 Debug--------------------
build in directory C:\DDK\src\osr\demo with arguments (basedir C:\DDK)
run build -e -M for checked version in C:\DDK\src\osr\demo
BUILD: Using 2 child processes
BUILD: Compile and Link for i386
BUILD: Loading C:\DDK\build.dat...
BUILD: Computing Include file dependencies:
Scanning c:\msdev\mfc\include
Scanning c:\msdev\include
Scanning c:\DDK\inc
Scanning c:\DDK\src\osr\demo
Scanning demo.c
BUILD: Examining c:\DDK\src\osr\demo directory for files to compile.
c:\DDK\src\osr\demo
c:\DDK\src\osr\demo - 1 source files (194 lines)
BUILD: Saving C:\DDK\build.dat...
BUILD: Compiling c:\DDK\src\osr\demo directory
1>Compiling - demo.c for i386
BUILD: Linking c:\DDK\src\osr\demo directory
1>Linking Executable - c:\DDK\lib\i386\checked\demo.sys for i386
BUILD: Done
1 files compiled - 194 LPS
1 executables built
=============== build warnings ======================
build complete
building browse information files
ddkbuild complete
demo.sys - 0 error(s), 0 warning(s)
Now go ahead and play around with it. Put some errors in the source file and rebuild.
What, you want to browse too? First you need to add a line to your SOURCES file:
MSC_WARNING_LEVEL=/FR
This adds the /FR switch to the compiler invocation, so when you compile your driver, a .sbr file gets created. You also have to invoke BSCMAKE, so you need one more file, a file called sbrlst.txt in the top directory of your project. The existence of sbrlst.txt triggers ddkbuild to invoke bscmake. In its simplest form sbrlst.txt just contains:
/o demo.bsc *.sbr
Now when you build your driver, you get a browser tags file too, and when you click on a variable you can jump to its definition. Cool eh?