Previous Next

Building on a Multiprocessor Computer

When the Build utility is run on a multiprocessor computer, different Build utility threads may be running on different processors. Therefore you need 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 containing several functions, and another part of your project may be building a TARGETTYPE=DYNLINK that will be exporting these functions.

Note  Often, what seems to be a synchronization problem actually results from misuse of TARGETLIBS and LINKLIBS. If you are building a DLL (TARGETTYPE=DYNLINK), and one directory is building a function, and a second directory is building a binary that will export that function, you need to use the LINKLIBS macro to specify the library built from the first directory within the sources file of the second directory. In all other cases you should use TARGETLIBS.

On a multiprocessor computer, you need to control the order of your build so that the Build utility does not attempt to build a product without first having built any products on which it depends.

There are two different pairs of macros that can be used in your sources files to control the build order. One pair is BUILD_PRODUCES and BUILD_CONSUMES. The other pair is SYNCHRONIZE_BLOCK and SYNCHRONIZE_DRAIN.

You can use either pair; you do not have to use both. Indeed, if a single sources file contains BUILD_PRODUCES or BUILD_CONSUMES, any instances of SYNCHRONIZE_BLOCK or SYNCHRONIZE_DRAIN 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.

The BUILD_PRODUCES and BUILD_CONSUMES method is more powerful and usually lets the build complete faster than the SYNCHRONIZE_* method.

The BUILD_PRODUCES and BUILD_CONSUMES Method

BUILD_PRODUCES and BUILD_CONSUMES lets you indicate dependencies in your project. Suppose that the objects in directory one need to be built before the objects in directory two. You can indicate this by placing the following macro in the sources file of directory one:

BUILD_PRODUCES=SomeString

and then by placing 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_PRODUCES macro, and in any number of BUILD_CONSUMES macros in other files. For each string, the Build utility will build the objects in the directory containing the BUILD_PRODUCES macro before building any of the directories containing the corresponding BUILD_CONSUMES macros.

There is no limit to the number of BUILD_PRODUCES or BUILD_CONSUMES macros that can be used in one sources file, although of course 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 with its BUILD_PRODUCES macro. If a string contains the $(VariableName) syntax it will be expanded before matching. If you use this technique, be very careful of letting VariableName equal a macro that may have a different value in different sources files.

Any directory that uses BUILD_PRODUCES should be listed first in its parent dirs file., and any directory that uses BUILD_CONSUMES should be listed last in the dirs file.

The SYNCHRONIZE_BLOCK and SYNCHRONIZE_DRAIN Method

SYNCHRONIZE_BLOCK and SYNCHRONIZE_DRAIN provide a less granular way to control synchronization.

Any directory that uses SYNCHRONIZE_BLOCK should be listed first in its parent dirs file., and any directory that uses SYNCHRONIZE_DRAIN should be listed last in the dirs file.

You should use these directives very sparingly, because they completely stall a multiprocessor build when they are encountered.