Building on a Multiprocessor Computer
For most projects, you can use the Windows Driver Kit (WDK) build environment on a multiprocessor machine without making any changes to your files. However, when the Build utility is run on a multiprocessor computer, different Build utility threads may be running on different processors. Therefore, you have to be careful that your products are built in the correct order.
Your project may contain compiler dependencies--for example, one part of your project may produce a global precompiled header that will be used by another part of your project. It may also contain linker dependencies--for example, one part of your project may be building a TARGETTYPE=LIBRARY product that contains several functions, and another part of your project may be building a TARGETTYPE=DYNLINK that will be exporting these functions.
How the Build Utility Operates with Multiple Processors
The SetEnv.bat file that is included with the WDK sets the BUILD_MULTIPROCESSOR environment variable to 1. With this setting, the Build utility uses the same number of threads as there are available processors when processing each build pass.
The /Mx switch on the Build utility overrides the BUILD_MULTIPROCESSOR variable and instructs the Build utility to use x threads when it processes each build pass. For more information about this switch, see Build Utility Command-Line Parameters.
When you run the Build utility on a multiprocessor machine, the Build utility ensures that all the tasks from one build pass complete before it starts the next build pass. For example, you do not need to use any synchronization macros to ensure that a library that is produced in Pass 1 is completed before being included in the creation of a driver .sys file during Pass 2.
Specifying dependencies within a build pass
If you build components that are located in different directories during the same build pass, you will need to modify your Sources files so that the build of these components are synchronized on a multiprocessor computer. For example, if you are building two static libraries where one library depends on the other, you need to identify that dependency to the Build utility.
The one case where you need to modify your Sources files to build on a multiprocessor computer is when you need to synchronize the building of components that are located in different directories during the same build pass. For example, if you are building two static libraries where one library depends on the other, you need to identify that dependency to the Build utility.
There are two sets of macros that can be used in your Sources files to control the build order of components:
The BUILD_xxx_PRODUCES and BUILD_xxx_CONSUMES macros.
The SYNCHRONIZE_xxx_BLOCK and SYNCHRONIZE_xxx_DRAIN macros.
You can use either set and you do not have to use both. Indeed, if a single Sources file contains BUILD_xxx_PRODUCES or BUILD_xxx_CONSUMES, any instances of SYNCHRONIZE_xxx_BLOCK or SYNCHRONIZE_xxx_DRAIN macros in that file will be ignored by the Build utility. You can combine both methods within a single project if they are never in the same Sources file, but this is not recommended.
Important The combination of BUILD_xxx_PRODUCES and BUILD_xxx_CONSUMES method is more powerful and usually lets the build complete faster than the SYNCHRONIZE_xxx_BLOCK and SYNCHRONIZE_xxx_DRAIN method.
The BUILD_xxx_PRODUCES and BUILD_xxx_CONSUMES Method
The BUILD_xxx_PRODUCES and BUILD_xxx_CONSUMES macros lets you specify dependencies in your project within each build pass.
The following table lists the BUILD_xxx_PRODUCES and BUILD_xxx_CONSUMES that synchronize processing during a specific build pass.
Build pass | BUILD_xxx_PRODUCES macro | BUILD_xxx_CONSUMES macro |
---|---|---|
Suppose that the objects in directory one have to be built before the objects in directory two. You can indicate this by putting the following macro in the Sources file of directory one:
BUILD_PRODUCES=SomeString
And then by putting the following macro in the Sources file of directory two:
BUILD_CONSUMES=SomeString
SomeString can be any string that does not contain spaces. The Build utility will look for matching strings. Any unique string can be used in exactly one BUILD_xxx_PRODUCES macro, and in any number of BUILD_xxx_CONSUMES macros in other files.
During each build pass, the Build utility builds the objects in the directory with a Sources file that contains the BUILD_xxx_PRODUCES macro set to a specified string value. After building the objects, the utility then builds the objects in any of the directories that have Sources files that contain the corresponding BUILD_xxx_CONSUMES macros set to the same string.
For example, during Pass 0, the Build utility builds the objects in the directory that contains the BUILD_PASS0_PRODUCES macro that is set to a string value of Pass0String before it builds any of the directories that contain the corresponding BUILD_PASS0_CONSUMES macros set to the same string value.
The following are guidelines for the correct use of the BUILD_xxx_CONSUMES and BUILD_xxx_PRODUCES macros:
There is no limit to the number of BUILD_xxx_PRODUCES or BUILD_xxx_CONSUMES macros that can be used in one Sources file; however, you must avoid circular use of these macros. There is no limit to the number of distinct strings that can be used in one project.
To keep track of these strings, it is recommended that a string contain the name of the directory that has its BUILD, _xxx_PRODUCES macro. If a string contains the $(VariableName) syntax it will be expanded before matching. If you use this technique, make sure that VariableName does not equal a macro that may have a different value in different Sources files.
Any directory that uses BUILD_xxx_PRODUCES should be listed first in its parent Dirs file, and any directory that uses BUILD_xxx_CONSUMES should be listed next in the Dirs file.
If the Build utility encounters a BUILD_xxx_CONSUMES macro before it encounters a matching BUILD_xxx_PRODUCES macro, it ignores the BUILD_xxx_CONSUMES macro. As a result, if a component is missing dependent components at link time, the linker generates an error.
Listing dependent components in the correct order in your Dirs files does not eliminate the need to explicitly specify the dependencies within a build pass. You must still identify dependencies in your Sources files by using BUILD_xxx_PRODUCES and BUILD_xxx_CONSUMES macros so that the Build utility can optimize the processing of dependent components on a multiprocessor machine.
The SYNCHRONIZE_xxx_BLOCK and SYNCHRONIZE_xxx_DRAIN Method
The SYNCHRONIZE_xxx_BLOCK and SYNCHRONIZE_xxx_DRAIN method provides a less granular way to control synchronization.
The following table lists the SYNCHRONIZE_xxx_BLOCK and SYNCHRONIZE_xxx_DRAIN that synchronize processing during a specific build pass.
Build pass | SYNCHRONIZE_xxx_BLOCK macro | SYNCHRONIZE_xxx_DRAIN macro |
---|---|---|
SYNCHRONIZE_xxx_BLOCK=1 instructs the Build utility to build a certain directory first during a specific build pass. When the Build utility finds this macro in a Sources file in a directory, it waits until the directory is built before building the directories that are specified after this directory in the parent Dirs file. You should use this macro in any directory that other directories depend on.
SYNCHRONIZE_xxx_DRAIN=1 instructs the Build utility to not build a directory, whose Sources file contains this macro, until all directories (specified before this directory in the parent Dirs file) are built. You should use this macro in any directory that depends on the products built in another directory
Any directory that uses a SYNCHRONIZE_xxx_BLOCK macro should be listed first in its parent Dirs file, and any directory that uses a SYNCHRONIZE_xxx_DRAIN macro should be listed next in the Dirs file.
Note It is strongly recommend that you do not use these macros. Use the BUILD_xxx_CONSUMES and BUILD_xxx_PRODUCES macros instead.
Send comments about this topic to Microsoft
Build date: 5/3/2011