WDF drivers are built by using the WDK Build utility (Build.exe), which is the command-line tool that Microsoft uses to build Windows itself. The Build utility is the only tool that Microsoft supports for building drivers, but it can also be used to build various other types of projects including user-mode applications. This section provides a basic introduction to how to use the Build utility to build driver binaries and related files such as INFs.
The Build utility is run from a command window. You set environment variables for this window to specify the following three key build parameters:
Which version of Windows the driver will be installed on.
UMDF drivers can be installed on Windows XP, Windows Vista, and later versions of Windows.
KMDF drivers can be installed on Windows 2000 and later versions of Windows.
Which CPU architecture the driver will be installed on.
UMDF can be installed on the x86 and x64 architectures.
KMDF drivers can be installed on all three supported architectures: x86, x64, and Intel Itanium.
Whether to build a checked or free version of the driver.
Checked builds provide extensive debugging support but tend to be relatively slow. Free builds lack the debugging support but are fully optimized.
You can manually configure the build environment in a generic command window, but this process can be complicated. To simplify the process, the WDK includes a set of build environment command windows with appropriate environment settings, one for each supported combination of Windows version, CPU architecture, and build type.
For details on the environment settings, review the contents of the Setenv.bat file, located at %wdk%\bin. This is the batch file that configures environments for the build environment window.
On the taskbar, click Start, and then click All Programs.
Click Windows Driver Kits, click the latest WDK version, and then click Build Environments.
Click the appropriate CPU architecture, and then open a checked or free build environment window for the appropriate Windows version.
The build environment window for a specified version of Windows works for that version and all later versions.
Note Although UMDF drivers can be installed on both Windows Vista and Windows XP, the drivers must be built with the Windows Vista build environment.
The Build utility depends on a number of supporting files that specify the details of how the build is to be performed, plus a project's code and header files. The supporting files are all text files and must be edited with a text editor-no tools are available to automatically create these files. However, for most projects, you can copy the supporting files from an appropriate sample and then modify them to suit your project.
All projects use at least the following two supporting files:
This file contains build instructions. It should be named Makefile and consist of only the following statement, which includes the standard WDK make file-Makefile.def:
Do not write your own make file. Just copy one from any of the WDF samples.
This file contains project-specific information that is used to build the driver, such as the list of source files. The example in Listing 19-1 shows the contents of a basic KMDF Sources file for a driver named WdfSimple, with a single source file, WdfSimple.c.
Listing 19-1: A minimal KMDF Sources file
TARGETNAME=WdfSimple TARGETTYPE=DRIVER KMDF_VERSION=1 SOURCES=WdfSimple.c
A more typical Sources file includes several additional directives. For example, many projects have custom targets, which must have corresponding directives in Sources. Examples of more complex Sources files, along with an explanation of the various directives, are given later in this chapter.
Driver projects typically include one or more of the following optional supporting files:
This file contains a list of subfolders to be built. It is used by projects that have source files in multiple subfolders or to build multiple projects with a single build command.
INX file (.inx)
An INX file is an architecture-independent INF file. When the appropriate instructions are specified, the Build utility uses the data in an INX file to produce an appropriate INF file for the project. Chapter 20, "How to Install WDF Drivers," provides information on INX files.
The make file supports building the standard target: the driver binary. However, many projects also build one or more custom targets. Typical examples are projects that use an INX file to automatically generate architecture-specific INFs or drivers that support WMI. In that case, the directives for building the custom targets are placed in Makefile.inc. Makefile itself should never be modified.
Resource files (.rc)
These files contain various resources. For example, the VERSION resource contains information such as the version number and manufacturer.
Managed object format (MOF) resource files (.mof)
Drivers that support WMI must have a MOF resource file.
Note Projects that include MOF or INX files must have a Makefile.inc file that contains the directives and data that the Build utility uses to build the associated output files. Some examples of such Makefile.inc files are given later in the chapter.
Tip See the online help for the command-line Stampinf.exe tool for information about INX files. The tool is located in the %wdk%\bin folder. To display the help, run stampinf /? in a command window.
The Build utility assumes by default that the make file, Makefile.inc, Sources, and Dirs files are named Makefile, Makefile.inc, Sources, and Dirs, respectively, so those are the names that most projects use. However, you can use any names that are convenient for most project files and folders, with one important restriction: the file names cannot contain spaces or non-ANSI characters.
Tip See "Build Utility Reference" in the WDK for details about contents and format of these files-online at http://go.microsoft.com/fwlink/?LinkId=79349.
The Build utility places some limitations on how you organize your projects. The utility can only build files that are located the same folder as the Sources file, that folder's parent folder, or a platform-specific subfolder of the Sources folder. If you need source files in other locations, you should use a separate build procedure to compile them into .lib files and then link to the .lib files.
Tip See "Build Utility Limitations and Rules" in the WDK for details about the Build utility-online at http://go.microsoft.com/fwlink/?LinkId=80059.
The steps for building a project are straightforward.
Open the appropriate build environment window.
Use cd to move to the project folder.
Run the Build utility to compile and link the driver, using the following command syntax:
where [-a[b[c]…]] represents the build arguments, most of which consist of a single case-sensitive character, as described in the following section.
The WDK has a complete list of flags for the Build utility, but the following are some of the commonly used flags:
Displays a list of all command-line flags.
Deletes all object files.
Generates log, error, and warning files.
Uses colored text to display warnings, errors, and summaries.
Prevents dependency checking or scanning of source files.
Typically, build commands have relatively few arguments. In addition, the Build utility assumes by default that the project has a make file that is named Makefile, a Sources file that contains the list of source files, and so on. Therefore, if you use the standard names, you do not need to explicitly specify any of these files. Build commands are thus usually simple, as in the following commonly used command:
The build command itself is relatively simple, because all the details are in the supporting files. These files are discussed in the next two sections.
The Build utility can produce a number of different output files. The output files normally go in a subfolder of the project folder. The default output folder name depends on the build environment. For example, the default output folder for a Windows XP x86 free build is named ProjectFolder\objfre_wxp_x86\i386.
All builds produce the following three types of output files:
KMDF drivers are packaged as .sys files, and UMDF drivers are packaged as .dll files. The standard file names are TargetName.sys and TargetName.dll, respectively.
The Build utility produces an object file for each source file. This file is named SourceFileName.obj.
The driver's symbol file is named TargetName.pdb. This file is essential for debugging or generating trace messages.
The Build utility can also be used to produce other output files, such as additional DLLs or static libraries, as necessary. Also, if you have an appropriate MakeFile.inc and INX file, the Build utility produces an INF file-TargetName.inf-and places it in the output folder.
In some cases, such as projects that use interface definition (IDL) files, the Build utility dynamically creates header files and places them in the output folder. To enable .c or .cpp files to include the header, add $(OBJ_PATH) to the list of folders in the INCLUDES macro in the project's Sources file.
The following are some guidelines for building UMDF drivers:
The Build utility error message "cannot instantiate abstract class" usually means that you have neglected to override one or more of the methods on an interface. Interfaces are declared as pure abstract base classes, so you must override every method on the interface.
You can usually determine which method is missing by directly running Nmake. Running the Nmake all command shows more build output, including full error messages from the compiler. These messages allow you to determine which methods are missing. If your project uses a Dirs file to build from sources in multiple subfolders, you must run Nmake all in a "leaf" folder-in other words, a folder that has only a Sources file.
If you declare an interface method but neglect to implement it, the linker issues an error telling you that the method cannot be found.