Contents

Click on a topic formatted in green to view more information about that topic.

•	Getting Started

•	Windows® NT® Directory Structure

•	Using the Build Utility

•	Building Multiple Targets from One Subdirectory

•	Multi-processor Build Issues

•	Specifying Libraries

•	Precompiled Headers

•	Environment Variables

•	Macro Definitions

•	Rules

•	Debugging

•	Building Windows NT Software

•	Building Chicago Software

•	Building Win32 Subsystem Software

•	Frequently Asked Questions

•	Glossary


 Getting Started

The Build Utility, build.exe, was created by Steve Wood it to build Windows NT. The Build Utility provides a structured way of building things. This is the default build process for Windows NT. Groups who use it enable the Windows NT group to be able to build with their group and to make changes to the group’s source files when needed. Other groups, such as the VC team, use the Build Utility for precisely this reason. Even though the VC team did not need the same multi-platform support for their build process as the build process for Windows NT needed, the Build Utility enabled them to override all the default settings for build.exe and still take advantage of Windows NT.

See Also
Features
Why Use the Build Utility
Where is the Build Utility Located
Quick Start


Steve Wood

Steve Wood was one of the initial ten people working on Windows NT. They knew that they were going to build something really, really big. Steve came from OS/2 where everyone used individual procedures for building products. In OS/2, there were the UI people, the base kernel people, and the net people, who all had their own way of doing things. The build was tremendously difficult to coordinate. If you went to one subdirectory, you built a certain way, but if you went to another subdirectory, you built a different way. There were people in different geographic locations, all of them making changes and none of them compatible with each other or working together. So Steve came from that environment and realized there was a need for something better. That’s how the Build Utility came into being.

The question Steve asked was how could he abstract out all of this complicated gobbeldy-gook and put it in a master file? Steve noticed that nmake itself does not have some of the functions needed to build Windows NT: the ability to occasionally exclude directories or only build certain directories. He also wanted to have a way to have a global look at the whole tree for Windows NT. If a file changed anywhere in the tree, the developers could easily answer the question: “What do we have to rebuild as a result of that change?”

One of the things the Build Utility does is create a master database of all the inter-dependencies in the tree. This means you can go to any subdirectory, make a change to a file, and check it in. Then you can go to the top of the build tree for Windows NT, run build.exe, and anything in the tree that needs to be rebuilt, will be rebuilt. You don’t have to worry if you did the right thing. There would have been no way to build Windows NT without this type of structure and methodology.

The Build Utility eliminates the requirement of testing every single release against every single platform. This requirement is not needed for Windows NT because Windows NT performs the same way on all platforms: Intel, Alpha, MIPS, and PowerPC.


Features

The Build Utility:

•	Automatically establishes file dependencies.

•	Provides tools to build products for multiple hardware platforms without specifying any target-specific information.

•	Shields you from the details of the various compilers and machine architectures.

•	Is multiprocessor aware for speedier compilation.

•	Provides feedback during compilation, including:

*  How much longer before the build will finish
*  How many lines are compiling
*  How fast it’s compiling them
*  How many files you have to link
*  How many targets you are creating

•	Provides detailed information about the build process.


Why Use the Build Utility?

The great benefit to using this Build Utility, rather than creating your own make or nmake files, is because:

•	The Build Utility isolates all target-dependent information in a centralized location (including header and library include paths, compiler names and switches, and linker switches).

•	You can build products for multiple hardware platforms without specifying any target-specific information.

•	The Build Utility ensures that everyone builds consistently.

This is important when you have multiple files to build, many .exe files that you are generating, and multiple developers working on a project, You never have to be specific places. Once you are set up in one subdirectory in Windows NT, you can build all your subdirectories using build.exe. For this reason, the Build Utility has been used successfully by the following groups: Exchange, VC, Media Foundation, and MSN.


Where Is the Build Utility Located?

Every drop of Windows NT includes build.exe in the Internal Development Workstation (IDW) subdirectory. It also ships in the DDK as a tool for people who are writing device drivers. You can copy build.exe from the most recent build drop of Windows NT. The X86 version runs on Windows® 95® as well as Windows NT.


Quick Start

The sources.tpl file is contained in this topic. It is a template that specifies the target component that you want to build and the list of sources files needed to build it. It also specifies optional compiler switches and libraries that are unique for the component being built. Follow the instructions in this topic to copy and edit this template so you can use it to run the Build Utility.

Steve Wood (stevewo) wrote sources.tpl in April of 1990, and it was later modified. There is a commented description of this file is in \nt\bak\bin\sources.tpl. For more detailed information, see Getting Started.

Instructions

Here is what you need to do to get started using the Build Utility:

1.	Choose Edit, Copy from the menu bar to copy this topic to the Clipboard.

2.	Paste this topic into a file using a text editor.

3.	Replace the xxxxx in the MAJORCOMP and MINORCOMP macros below with your component's major and minor component name for example:

MAJORCOMP=ntos, MINORCOMP=ke

Note: Do not type spaces surrounding the equal sign.

4.	Replace the xxxxx in the TARGETNAME macro with your target name, for example:

TARGETNAME=myprogram

5.	Edit the TARGETPATH and TARGETTYPE macros to specify the location and type of the target.

6.	Edit the INCLUDES macro if you have a private include directory to search.

7.	Carefully edit the SOURCES macro so that it defines all the source files for the component that you are building.

8.	Remove these instructions and all comments.

9.	Save this file, naming it sources.tpl, and quit your text editor.

10.	Run the Build Utility from the command line by typing “build” and pressing Enter.
From now on, you can run either build or nmake to build the component.

#

# The MAJORCOMP and MINORCOMP variables are defined

# so that $(MAJORCOMP)$(MINORCOMP)filename can be used in

# cross compiling to provide unique filenames in a flat namespace.

#

MAJORCOMP=xxxxx

MINORCOMP=xxxxx

#

# The developer defines the TARGETNAME variable. It is the name of

# the target (component) that is being built by this makefile.

# It should not include any path or filename extension.

#

TARGETNAME=xxxxx

#

# The developer defines the TARGETPATH and TARGETTYPE variables.

# The first variable specifies where the target will be built. The second specifies

# the type of target (either PROGRAM, DYNLINK, LIBRARY, UMAPPL_NOLIB or

# BOOTPGM). Use UMAPPL_NOLIB when you are only building user-mode

# programs and do not need to build a library.

#

TARGETPATH=obj

# Select one of the following, and delete the others:

TARGETTYPE=PROGRAM

TARGETTYPE=DYNLINK

TARGETTYPE=LIBRARY

TARGETTYPE=UMAPPL_NOLIB

TARGETTYPE=BOOTPGM

#

# The TARGETLIBS macro specifies additional libraries to link against your target

# image. Each library path specification should contain an asterisk (*)

# where the machine-specific subdirectory name should go.

#

TARGETLIBS=

#

# The INCLUDES variable specifies any include paths that are specific to

# this source directory. Separate multiple paths with single

# semicolons. Relative path specifications are okay.

#

INCLUDES=..\inc

#

# The developer defines the SOURCES macro. It contains a list of all the

# source files for this component. Specify each source file on a separate

# line using the line-continuation character. This minimizes merge

# conflicts if two developers are adding source files to the same component.

#

SOURCES=source1.c  \

        source2.c  \

        source3.c  \

        source4.c

i386_SOURCES=i386\source1.asm

ALPHA_SOURCES=alpha\source1.s

MIPS_SOURCES=mips\source1.s

PPC_SOURCES=ppc\source1.s

#

# Next, specify options for the compiler using C_DEFINES.

#

C_DEFINES=

#

# Next, specify one or more user-mode test programs and their type.

# Use UMTEST for optional test programs. Use UMAPPL for

# programs that are always built when the directory is built. See also

# UMTYPE,  UMBASE,  and UMLIBS.

#

UMTYPE=nt

UMTEST=bunny*baz

UMAPPL=bunny*baz

UMBASE=0x1000000

UMLIBS=obj\*\bunny.lib

#

# Defining either (or both) the variables NTTARGETFILE0 and/or NTTARGETFILES

# causes makefile.def to include .\makefile.inc immediately after it

# specifies the top level targets (all, clean and loc) and their dependencies.

# The makefile.def file expands NTTARGETFILE0 as the first dependent for the

# "all" target and NTTARGETFILES as the last dependent for the "all" target.

# This is useful for specifying additional targets and dependencies that do not fit the

# general case covered by makefile.def.

#

#   NTTARGETFILE0=

#   NTTARGETFILES=

#   For more information about the macros in this file, see Macro Definitions.


Building Multiple Targets from One Subdirectory

In a typical build model, every subdirectory builds one target. The Build Utility gives you the advantage of having a single subdirectory where you can build multiple executable output files. The Build Utility supports a library-linked-to-main model, which enables you to have one subdirectory that builds multiple targets that are very similar. This eliminates the need to move recursively through 10 different subdirectories to build 10 different .exe files when they are all pretty much the same except for one source file that’s different between them.

In a single subdirectory you can have a number of files that share some common subset of code. Each of them will have a single source file that will have the unique code for that product. If your build product consists of several source files, you can specify all but the main source file as components of a library. The Build Utility links this library with the file containing main.

This model is especially useful in situations like in the tree for Windows NT tree where you have a subdirectory or in which you are building UNIX tools that all have a common file I/O code, memory code, and registry code. Then they also have a little wrapper around it that implements the name, which is the thing specific to that tool. What the Build Utility enables you to do is set up a target type of library in that subdirectory and use the use remote applications macro (UMAPPL) to specify the target names.

Consider, for example the simple UNIX commands tar, cat and grep:

UMAPPL=tar*cat*grep

Put all your common source files in the SOURCES macro. The Build Utility compiles all of those into a library, then compiles each one of the individual source files for tar.c, cat.c, and grep.c and links each of those against the common library that you built to produce tar.exe, cat.exe, and grep.exe.

See Also
UMAPPL
SOURCES


sources File

You describe build products in a file named “sources” that resides in each source code subdirectory. The sources file contains a series of macro definitions that are recognized by the Build Utility. A sample of this file is contained in Quick Start.


binplace.exe

Binplace.exe is the utility that the Build Utility uses to create the installable share point for the product. When you build an image, the Binplace Utility determines where that image will reside.

The Build Utility only calls binplace.exe if _NT<platform>TREE is defined before building.  When enabled, the build process will run binplace.exe after building every image. If there are extra files you want distributed, use the MISCFILES macro to specify them in your sources file.

BINPLACE_PLACEFILE is something you define when you do not want to have a public directory. The Build Utility expects to find this file in public, but if you do not want it there, you can override it with your own name.

The platform determines whether or not the Build Utility should run binplace. Binplace will be run if  _NT<platform>TREE is defined, for example:

_NTMIPSTREE=root_of_the_ mips_release_tree
_NTALPHATREE= root_of_the_alpha_release_tree
_NT386TREE= root_of_the_x86_release_tree
_NTPPCTREE= root_of_the_ppc_release_tree

See Also
BINPLACE_FLAGS
NTDBGFILES
BINPLACE_PLACEFILE


build.dat

When you use the Build Utility, it looks for a sources file and a dirs file. It processes the dependencies and builds a file called build.dat, which it puts in the NT subdirectory by default. Build.dat is basically a dump from build.exe of what the dependency graph looks like.


dirs File

You can instruct the Build Utility to recursively build an entire source tree by using the dirs file. The dirs file resides in a directory that contains subdirectories (that is, at the root of a source code tree or subtree). Each subdirectory can be a source directory or another source tree. You should place a dirs file at the root of each source code subtree. Then go to the leaf node in each source code subdirectory and specify your build products in a sources file. To view a sample of a sources file, see Quick Start.

You should define the following macros in your dirs file:

DIRS	This macro lists the directories that the Build Utility should always go into. Specify a list of subdirectories to be built unconditionally. Separate the entries in this list with spaces or tabs
OPTIONAL_DIRS	This macro lists the directories that the Build Utility does not have to go into, and by default will not go into. Specify a list of subdirectories to be built only if they are explicitly specified on the original build command line.
Example:

DIRS=dir1 dir2 dir3
OPTIONAL_DIRS=dir4 dir5

Build <currentdir>\dir1 <currentdir>\dir2 <currentdir>\dir3 in that order, all the time. <currentdir>\dir4 and <currentdir>\dir5 will only be built if you specify them to build on the command line or in the BUILD_OPTIONS environment variable.

The Build Utility supports a 'not' switch (~) for removing a directory from the default build. Using the above example,

build ~dir1 ~dir3 dir4

would build only dir2 and dir4.  If you follow a distinct pattern when naming your directories, it's trivial to use this to build multiple versions of a product. List the current version in the DIRS macro, the new or previous versions in the OPTIONAL_DIRS macro.  On your build machine, you can then build whichever version you want.


makefile.def

The Build Utility makes use of a generic makefile called makefile.def, which contains all the macro definitions that the sources file uses. (For an example of a sources file, see Quick Start.) The Build Utility sets the appropriate header and library include paths, compiler names and switches, and linker switches that are defined in makefile.def, and invokes nmake.exe.

The current version of makefile.def resides on \\orville\razzel\src\public\oak\bin.

Note: You must use nmake version 1.30 or greater because earlier versions do not understand the message command and the Build Utility depends on a number of features that are only in version 1.30 or greater.


makefile.plt

The platform-specific information for the makefiles is contained in makefile.plt. You can include makefile.plt in your own makefiles to select the build target and set platform-specific variables. For an example of this, see makefile.def. The latest  is stored on \\orville\razzel\src\public\oak\bin.

There are three very useful macros in this file:

TARGET_DIRECTORY
FREEBUILD
TARGET_CPP


makefile.tpl

This is the template makefile.  Nothing has to be in the makefile except:

!include $(NTMAKEENV)\makefile.def

The complete text of makefile.tpl is as follows:

#

# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source

# file to this component. This file merely indirects to the real makefile

# that is shared by all the components of Windows NT and OS/2

#

!INCLUDE $(NTMAKEENV)\makefile.def


verrc.tpl

Use this template file to add a version resource to an image. The final name would be something like <myimage.rc>. The following is the complete text of verrc.tpl:

/*

** Template for version resources. Place this in your .rc file,

** editing the values for VER_FILETYPE, VER_FILESUBTYPE,

** VER_FILEDESCRIPTION_STR and VER_INTERNALNAME_STR as needed.

** See winver.h for possible values.

**

** Ntverp.h defines several global values that do not need to be

** changed except for official releases such as betas, SDK updates, etc.

**

** Common.ver has the actual version resource structure that all these

** #defines eventually initialize.

*/

/* #include <windows.h> needed if this will be the .rc file */

#include <ntverp.h>

/*-----------------------------------------------*/

/* the following lines are specific to this file */

/*-----------------------------------------------*/

/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR

 * and VER_INTERNALNAME_STR must be defined before including COMMON.VER

 * The strings do not need a '\0', because common.ver has them.

 */

#define	VER_FILETYPE	VFT_DLL

/* possible values:	VFT_UNKNOWN

VFT_APP

VFT_DLL

VFT_DRV

VFT_FONT

VFT_VXD

VFT_STATIC_LIB

*/

#define	VER_FILESUBTYPE	VFT2_UNKNOWN

/* possible values	VFT2_UNKNOWN

VFT2_DRV_PRINTER

VFT2_DRV_KEYBOARD

VFT2_DRV_LANGUAGE

VFT2_DRV_DISPLAY

VFT2_DRV_MOUSE

VFT2_DRV_NETWORK

VFT2_DRV_SYSTEM

VFT2_DRV_INSTALLABLE

VFT2_DRV_SOUND

VFT2_DRV_COMM

*/

#define VER_FILEDESCRIPTION_STR     "Version Checking and File Installation Libraries"

#define VER_INTERNALNAME_STR        "VERSION.DLL"

#define VER_ORIGINALFILENAME_STR    "VERSION.DLL"

#include "common.ver"


makefile.inc

For each platform, there is a special makefile.inc:

•	mipsmk.inc

•	alphamk.inc

•	ppcmk.inc

•	i386mk.inc

The current version of these files reside on \\orville\razzel\src\public\oak\bin. In these files, there are optimization rules or assembler instructions that are specific for that target. There may also be extra link flags, resource compiler flags, or C preprocessor rules that are needed to make it all work. The makefile.inc files are not something you would usually edit because there are macros to override all the settings in makefile.inc in your sources file. If you want to change optimization, use MSC_OPTIMIZATION.  If you want to change linker flags, use LINKER_FLAGS.


ntverp.h

This is the master version file for Windows NT, from which all of version resources are built. It's located in \\orville\razzle\src\public\sdk\inc (more conventionally known as in the public project in the \sdk\inc subdirectory). Every image has a version resource on it. When they release a build from the Windows NT  Build Lab, they increase that master version number. Anything they link or build after that will automatically get a new version resource attached to it with the correct build number.

You can either use ntverp or the MASTER_VERSION_FILE macro to specify a different master version file. You do not have to have \\public\sdk\inc\ntverp.h. The VC team uses a different master version file because they have a different version scheme than Windows NT does.

If you look on the very last line of makefile.def, you will see the one place where MASTER_VERSION_FILE is used as a dependency for the resources.


_objects.mac

The Build Utility puts a file in the obj subdirectory called _objects.mac which contains the object dependencies for each platform. If you type that file out, all you see is something like:

i386objects=i386\x.obj i386\y.obj

mipsobjects=mips\x.obj mips\y.obj

ppcobjects=ppc\x.obj ppc\y.obj

This is something that the Build Utility creates. It is not something you need to edit. Every time the sources file gets updated, this file is regenerated.


Directory Structure

Windows® NT® has a fixed directory tree. The root of the build process is usually \NT (you can change this if you set the BASEDIR environment variable). Underneath are two subdirectories.  Public, and Private.  Public contains all the headers, libraries, build rules, etc shared by the source projects.  Private contains all the source code.  Each subcomponent in Windows NT has its own directory under private.  The major components are:

ntos	The kernel, core OS, and most drivers
windows	The shell
ole	The OLE source
rpc	RPC-related tools and libraries
sdktools	The source to all the tools

Here is an example of the Windows NT directory structure:

nt

+---private

¦   +---csr

¦   ¦   +---inc

¦   ¦   +---server

¦   ¦       +---alpha

¦   ¦       +---daytona

¦   ¦       +---i386

¦   ¦       +---km

¦   ¦       +---mips

¦   ¦       +---ppc

¦   +---dcomidl

¦   +---developr

¦   +---dfs

|...

|

+---public

    +---oak

    ¦   +---bin

    ¦   ¦   +---alpha

    ¦   ¦   +---i386

    ¦   ¦   +---mips

    ¦   ¦   +---ppc

    ¦   +---inc

    +---sdk

    ¦   +---bin

    ¦   +---inc

    ¦   ¦   +---chicago

    ¦   ¦   +---crt

    ¦   ¦   ¦   +---mrc

    ¦   ¦   ¦   +---sys

    ¦   ¦   +---gl

    ¦   ¦   +---mfc40

    ¦   ¦   ¦   +---l.chs

    ¦   ¦   ¦   +---l.deu

    ¦   ¦   ¦   +---l.esp

    ¦   ¦   ¦   +---l.fra

    ¦   ¦   ¦   +---l.ita

    ¦   ¦   ¦   +---l.jpn

    ¦   ¦   ¦   +---l.kor

    ¦   ¦   ¦   +---res

    ¦   ¦   +---posix

    ¦   ¦       +---sys

    ¦   +---lib

    ¦       +---alpha

    ¦       +---i386

    ¦       +---mips

    ¦       +---ppc

    +---tools

You can follow the directory structure that Windows NT uses for your own build process or you can specify the following macros in your sources file. These macros enable you to specify alternate object directories:

BINPLACE_PLACEFILE
COFFBASE_TXT_FILE
COMPILER_WARNINGS
SDK_INC_PATH
SDK_LIB_PATH
CRT_INC_PATH
CRT_LIB_PATH
MASTER_VERSION_FILE
OAK_INC_PATH


Using the Build Utility

The Build Utility enables you to build multiple pieces of your product in a logical way and exactly the same. In a typical development environment, you have everybody doing their own sequence of steps to build their .exe files. The Build Utility eliminates all those differences.

The files used by build.exe are:

•	sources - lists the rules and macros. needed to build a specific component subdirectory.

•	dirs - contains macros called DIRS and OPTIONAL_DIRS that specify the directories to open recursively and the order in which they should be opened.

Build.exe looks into the dirs file for the macros DIRS and OPTIONAL_DIRS.  It then recurses to each directory listed where it might find another dirs file (indicating more directories to recurse into) or a sources file (indicating something needs to be built). If the latter, it looks for the macros SOURCES, INCLUDES, TARGETNAME, and TARGETPATH.  These are parsed to determine the dependencies, the list of files to build, and the end result.  Normally, this information is then kept in a file called build.dat that the build utility will create for future reference.  Depending on the options you pass to build, it does the appropriate action and then calls a make program (For more information, see BUILD_MAKE_PROGRAM) to build the component.  There are files (makefil0 and makefile.inc) that build will recognize in special circumstances (for instance, only on a clean build or only when NTTARGETFILES is specified in the sources file).  When the entire directory tree is built, build terminates. For an introduction to the Build Utility, see Getting Started.

Invoke build.exe with the “-?” option to display the following syntax and command line options:

-b	Displays full error message text without truncating anything.
-c	Deletes all object files.
-C	Deletes all .lib files only.
-e	Generates the build.log, build.err, and build.wrn files.
-E	Always keep the log files.
-f	Forces rescan of all source and include files.
-i	Ignores extraneous compiler warning messages.
-j filename	Use filename as the name for log files. The j switch changes the first field, so it produces filename.log, filename.wrn, and filename.err. Some people have it set up on their machine where they share their source drive and then they connect with their x86 or Alpha or MIPS and in each of those they set the j switch so they can build all those machines at the same time across the net and produce the log, warning and error files for each platform’s build.
-k	Keep out-of-date targets (do not delete them).
-l	Link only, no compiles.
-L	Compile only, no link phase.
-M	Multiprocessor
-m	Background mode; run build in the idle priority class.
-o	Display out-of-date files.
-O	Generate obj\_objects.mac file for current directory.
-p	Pause before compile and link phases.
-P	Print elapsed time after every directory.
-q	Query only; do not run nmake.
-r dirpath	Restarts clean build at specified path.
-s	Display status line at top of display.
-S	Display status line with include file line counts.
-t	Display the first level of the dependency tree
-T	Display the complete dependency tree.
-$	Display the complete dependency tree hierarchically.
-v	Enable include file version checking.
-w	Show warnings on screen.
-z	No dependency checking or scanning of source files; one pass compile and link.
-Z	No dependency checking or scanning of source files; two passes.
-why	List reasons for building targets.
-all	Same as specifying -386 , -mips, -alpha and -ppc
-alpha	Build targets for Alpha.
-mips	Build targets for MIPS.
-386	Build targets for i386.
-ppc	Build targets for PowerPC.
-x filename	Exclude include file from dependency checks.
-nmake arg	Argument to pass to nmake.


Multi-processor Build Issues

There are two important multi-processor directives: SYNCHRONIZE_DRAIN and SYNCHRONIZE_BLOCK. Their syntax and meaning are as follows:

SYNCHRONIZE_DRAIN=1	Do not build this subdirectory until all the prior subdirectories are done.
SYNCHRONIZE_BLOCK=1	Do not continue building until this subdirectory is done.
Use SYNCHRONIZE_DRAIN when you have a subdirectory that needs the results from a prior subdirectory on the same pass. For example, when building a DLL, you may have several subdirectories with TARGETTYPE=LIBRARY where each builds some component. You have another subdirectory with TARGETTYPE=DYNLINK, and the Build Utility will build a DLL that exports functions from the component libraries. In such a case, set LINKLIBS to the component libraries, make sure the DLL subdirectory is the last in the parent DIRS file, and add SYNCHRONIZE_DRAIN=1 to the sources file for the DLL.

Use SYNCHRONIZE_BLOCK when you have a subdirectory that other subdirectories require the results from in order to build. The usual example is a global precompiled header. List the precompiled directory first in the DIRS list, add SYNCHRONIZE_BLOCK=1 to that sources file, and the subsequent directories that use the PCH will not be built until the PCH is created.

Note: Use these directives very sparingly because they completely stall an MP build when they're encountered. In most cases, the problem is not with the MP nature of the build, but rather the macros used in the sources file. A common mistake is using LINKLIBS to specify import libraries when building a DLL. You almost never want to do this. LINKLIBS must exist during pass 1 because they're used to build the import library for the DLL. TARGETLIBS do not need to exist until pass 2 because they are only used to link the image. Use LINKLIBS for component libraries only. Use TARGETLIBS for import libraries.


Specifying Libraries

Unlike some other environments that use the LIB environment variable, the Build Utility always requires the full path to eliminate any ambiguity.

For instance, some build processes rely on the linker to "figure out" the correct libraries by using paths stored in the LIB environment variable and a list of default libraries stored in the objects.  However, there's an inherent (and undesirable) side-effect in this approach because you never really know what library you're using, and controlling this on a per-library basis is difficult. For consistency, the Built Utility requires you specify the full path to the library(s) and it will disable any default library lookup the linker might perform.  Additionally, when specifying the libraries, you should try to abstract any absolute dependencies in the path. The build process provides an asterisk to take the place of the platform.  You can use BASEDIR macro to take the place for the root of the source tree. You can use the SDK_LIB_PATH  if you don't want to rely on the Windows NT directory structure.

Additionally, you should use an asterisk to indicate the target platform in the path. For instance, assume you're building a typical Win32 Windows exe. Normally, this would require you to link against kernel32.lib, user32.lib, gdi32.lib, and maybe a component library you built called mylib.lib.  Here's what the TARGETLIBS macro would look like:

    TARGETLIBS = \

        $(BASEDIR)\public\sdk\lib\*\kernel32.lib \

        $(BASEDIR)\public\sdk\lib\*\user32.lib \

        $(BASEDIR)\public\sdk\lib\*\gdi32.lib \

        ..\mylib\obj\*\mylib.lib

When building on X86, this would mean the same as:

    TARGETLIBS = \

        $(BASEDIR)\public\sdk\lib\i386\kernel32.lib \

        $(BASEDIR)\public\sdk\lib\i386\user32.lib \

        $(BASEDIR)\public\sdk\lib\i386\gdi32.lib \

        ..\mylib\obj\i386\mylib.lib

See Also
LINKLIBS
TARGETLIBS
TARGETPATH
UMLIBS


Precompiled Headers

The easiest way to use precompiled headers is to state in your sources file:

  PRECOMPILED_INCLUDE=some_header_file_that_every_source_file_includes

If you are building C++ code you state:

  PRECOMPILED_CXX=1

Then you are done!

Precompiled headers are put into the obj\platform subdirectory by default or $(O). Therefore, they should not collide with simultaneous compilations.

See Also
PRECOMPILED_CXX
PRECOMPILED_INCLUDE
PRECOMPILED_OBJ
PRECOMPILED_TARGET


Environment Variables

You can set the following variables in your environment:

BUILD_OPTIONS
BUILD_DEFAULTS
BUILD_MAKE_PROGRAM
BUILD_DEFAULT_TARGETS
BUILD_ALT_DIR


BUILD_ALT_DIR

Use this to specify an alternate object directory name. It must be ten characters or less and contain no spaces. The value is added to the end of the .obj name and (if no -j switch is used for build.exe) the logfile name, for example:

c:\> set BUILD_ALT_DIR=Debug
c:\> build -MIPS -e

Would generate objects in the objDebug\mips subdirectory and logfiles named "buildDebug.log/buildDebug.wrn/buildDebug.err".  If you do not set this, the default is nothing.  Use this macro when you want to build the same source in different windows using different language, optimizations, or debugging information.

This Build Alternate Directory macro was added to the Build Utility so the VC group could use the same build process as the Windows NT group. They wanted to be able to build debug and retail versions from the same subdirectory at the same time on the same machine. This macro enabled them to specify the output directory. Instead of always being OBJmachine_name, it would be OBJ plus whatever they tacked onto this BUILD_ALT_DIR macro. That enabled them to specify a "D" for where the debug files went. They had another screen group that did retail builds.

You could extend this logic and make it one screen group that does USA and one that does Korean, or one that does optimize and one that does not, The only limitations on BUILD_ALT_DIR are that it be less than 10 characters and it cannot have embedded spaces or dots.

If you do not want to build using the same directory structure as the Windows NT group, specify the following macros and you do not need it any more.

BINPLACE_PLACEFILE
COFFBASE_TXT_FILE
COMPILER_WARNINGS
SDK_INC_PATH
SDK_LIB_PATH
CRT_INC_PATH
CRT_LIB_PATH
MASTER_VERSION_FILE
OAK_INC_PATH


BUILD_DEFAULT_TARGETS

Use this to specify the default target platform for which you are building. Assuming cross compilers existed, you could set it to -MIPS on an X86 and build MIPS binaries. Usually, you can just set it to the platform you're hosted on, for example:

c:\> build -mips

   means the same as:

   c:\> set BUILD_DEFAULT_TARGETS=-mips

   c:\> build


BUILD_DEFAULT

Used this to specify options to build, for example:

   c:\> build -eswM -nmake -i

   means the same as:

   c:\> set BUILD_DEFAULT=-eswM -nmake -i

   c:\> build


BUILD_MAKE_PROGRAM

Use this to specify the make program to execute. The default is nmake.exe, but if you want to use some other make program, just set this variable. You can specify the full path name to the make program, if desired.


BUILD_OPTIONS

Use this to specify the OPTIONAL_DIRS to process, for example:

// DIRS file:

        DIRS=dir1 dir2 dir3

        OPTIONAL_DIRS=OptDir1 OptDir2 OptDir3

    c:\> build OptDir1 OptDir2 OptDir3

   means the same as:

   c:\> set BUILD_OPTIONS=OptDir1 OptDir2 OptDir3

   c:\> build


Macro Definitions

You set the variables for most of the following macros in a sources file; a few are set in your environment (for a list of these, see Environment Variables): Except for DIRS and OPTIONAL_DIRS, which are used by build.exe, these macros are all used by nmake. All that build.exe does is open all the files, figure out the dependencies, and then calls nmake. The other macros used in the build process are all used by nmake. Here are all the macro names, how they are used and why you would want to put them in your sources file.

INCLUDES

SOURCES

TARGETEXT

TARGETNAME

TARGETPATH

TARGETTYPE

UMAPPL

UMAPPLEXT

UMLIBS

Optional macros that you may want to define in your sources file include:

BASEDIR

BINPLACE_FLAGS

BINPLACE_PLACEFILE

C_DEFINES

COFFBASE

COFFBASE_TXT_FILE

COMPILER_WARNINGS

CRT_INC_PATH

CRT_LIB_PATH

DEBUG_CRTS

DLLBASE

DLLDEF

DLLENTRY

DLLLIBOBJECTS

DLLORDER

DRIVERBASE

EXEPROFILEINPUT

FREEBUILD

GPSIZE

HALBASE

IDL_RULES

IDL_TYPE

LANGUAGE

LINKER_FLAGS

LINKER_NOREF

LINKLIBS

MAJORCOMP

MAKEDLL

MASTER_VERSION_FILE

MFC_FLAGS

MFC_INC_PATH

MFC_INCLUDES

MFC_LIB_PATH

MFC_LIBS

MFC_VER

MIDL_OPTIMIZATION

MIDL_UUIDDIR

MINORCOMP

MISCFILES

MSC_OPTIMIZATION

MSC_WARNING_LEVEL

NOLINK

NOMFCPDB

NO_NTDLL

NOT_LEAN_AND_MEAN

NT_INST

NT_UP

NTDBGFILES

NTDEBUG

NTDEBUGTYPE

NTKEEPRESOURCETMPFILES

NTNOFUZZYLOOKUP

NTNOPCH

NTPFROFILEINPUT

NTTARGETFILE0

NTTARGETFILE1

NTTARGETFILES

O

OAK_INC_PATH

PASS0_CLIENTDIR

PASS0_HEADERDIR

PASS0_SERVERDIR

PASS0_SOURCEDIR

PNP_POWER

PRECOMPILED_CXX

PRECOMPILED_INCLUDE

PRECOMPILED_OBJ

PRECOMPILED_TARGET

RC_COMPILER

SDK_INC_PATH

SDK_LIB_PATH

SOURCES_USED

SUBSYSTEM_VERSION

TARGET_CPP

TARGET_DIRECTORY

TARGETLIBS

TARGETPATHLIB

UMBASE

UMENTRY

UMENTRYABS

UMTEST

UMTYPE

USE_CRTDLL

USE_INCREMENTAL_LINKING

USE_LIBCNTPR

USE_MFCUNICODE

USE_MFC

USE_MFC30

USE_MSVCRT

USE_NATIVE_EH

USE_NOLIBS

USE_NTDLL

USE_PDB

USE_STATIC_MFC

USECXX_FLAG

USER_C_FLAGS

USE_LIBCMT

USER_INCLUDES


BASEDIR

Use the BASEDIR macro when referring to the base of the source tree.  By default, the source tree starts at $(_NTDRIVE)\nt, but it's not required. By using BASEDIR to refer to the base, you abstract out this dependency.

Example

   Instead of this:

    TARGETLIBS=d:\nt\public\sdk\lib\*\kernel32.lib

   Use this:

     TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib


BINPLACE_FLAGS

Use this macro to specify arguments that you want to pass to binplace.exe.  Type binplace-? to display a list of these switches.


BINPLACE_PLACEFILE

Use this macro to specify the placefile used by binplace.  If nothing is listed,

   $(BASEDIR)\public\sdk\lib\placefil.txt is used by default.

For more information, see binplace.exe.

Set this macro if you don't use the Windows NT directory structure.


C_DEFINES

Use this macro to specify switches you want passed to the compiler. Typically, they are compiler #defines.

You might specify:

C_DEFINES = /DDEBUG_BUILD

to define DEBUG_BUILD to the compiler.  There's no limit to what this #define can be except that C_DEFINES gets passed to the compiler and it also gets passed to the resource compiler.  Therefore, you cannot put compiler optimization or other    machine- or tool-specific switches in the C_DEFINES macro.  Instead, use one of the following macros for this:

MSC_OPTIMIZATION
MSC_WARNING_LEVEL
USER_C_FLAGS


COFFBASE

Use this macro to specify the name to look up in COFFBASE_TXT_FILE.  If you do not specify a name, it defaults to the value of TARGETNAME (if building a DYNLINK) or usermode (if you are building a UMAPPL, PROGLIB, or PROGRAM).  If you want to specify an absolute base address for your image and not use a global file for all, see DLLBASE or UMBASE.


COFFBASE_TXT_FILE

The name of the file passed to the linker with the base addresses for the images you build. By default, this is $( BASEDIR)\public\sdk\lib\coffbase.txt. The file should have three columns.  The first is the name of the image.  The second is the starting address for the image.  The last is the maximum size of the image.  There should also be an entry with the name "usermode" that will be the default value.  Here's an example:

usermode	0x60000000	0x20000000

MyDll1	0x70000000	0x00010000

MyDll2	0x70010000	0x00010000

Set this macro if you don't use the Windows NT directory structure.

The Build Utility assumes that coffbase.txt will be in \\public\sdk\lib and will be called coffbase.txt. You can override this filename and call it anything you want by using COFFBASE_TXT_FILE.


COMPILER_WARNINGS

The name of the warning file passed to the compiler with the /FI switch.  By default, this is $( BASEDIR)\public\sdk\inc\warning.h.  The file contains a list of compiler pragmas used to disable, enable, or promote warnings for the entire build.

Set this macro if you don't use the Windows NT directory structure.


CRT_INC_PATH

Specifies the path to the C Runtime headers.  The default is $(BASEDIR)\public\sdk\inc\crt.

Set this macro if you don't use the Windows NT directory structure.


CRT_LIB_PATH

Use this macro to specify the path to the C Runtime libraries .  The default is $(BASEDIR)\public\sdk\lib\*

Set this macro if you don't use the Windows NT directory structure.


DEBUG_CRTS

Whether you build checked or free system, the Build Utility always links against the retail runtime libraries and the retail MFC. If you want to link against the debug MFC and the debug runtime libraries, specify the following in your sources file or set it in your environment variables before you build:

DEBUG_CRTS=1

For example, the VC team sets DEBUT_CRT=1 in a batch file that sets up for a debug build of the VC product because the VC team builds differently than the Windows NT team, and do not use the debug runtime libraries.


DLLBASE

You only need to use this macro when your TARGETTYPE macro is set to DYNLINK. Use it to set the base address for the DLL image you are creating. If you do not specify an address, the Build Utility will assume that the target name in coffbase.txt is the name of your image. You can override this default target name by specifying a target name with the DLLBASE macro. You can set DLLBASE to be the hard-coded base address, a hex address, or you can leave it blank. If you leave it blank, the Build Utility will always look up the target name specified in coffbase.txt.

Example:  If you are building kernel32.dll, the Build Utility will look up kernel32 in coffbase.txt to find that base address.


DLLDEF

Use this macro to specify the name of the .def file that the Build Utility will pass to the librarian when building the export and import files. If you do not set this, the Build Utility will assume it is the same name as the image you are building. The most common usage is:

DLLDEF=mydll.def

Additionally, there is a standard inference rule that will run the C preprocessor over the .def or .src file in the current directory to create build-specific .def files in the object subdirectory. The same compiler defines you key off of in your source code can be used in the root .def or .src file to create the export list. To enable it, use something like:

DLLDEF=$O\mydll.def

Here's an example of what mydll.src might look like:

    ; mydll.src

    LIBRARY mydll

    EXPORTS

    #if defined(_M_IX86)

        X86Routine

    #elseif defined(_M_MRX000)

        MipsRoutine

    #elseif defined(_M_ALPHA)

        AlphaRoutine

    #elseif defined(_M_PPC)

        PPCRoutine

    #else

    #error Unknown platform

    #endif

    // Grab some other exports from another file

    #include "master.src"


DLLENTRY

Use this macro to specify the DLL entry point. By default, no entry point is assumed. For example, when you bring over programs that were built in the VC build environment or use the C Run-time, you will probably set:

DLLENTRY=_DllMainCRTStartup

Look up the documentation on DLL entry point in the Win32 SDK to find the values to use.


DLLLIBOBJECTS

Use this macro to specify extra objects to add to an import library.

Usually, when the TARGETTYPE is DYNLINK, the end result is a DLL and an import library. If you want to have different LIB objects for each platform, you can override this to create different platform-specific DLL LIB objects. DLLLIBOBJECTS enables you to specify additional objects to add to the import library. For example, you might have an OLE custom control (with GUIDs used to identify this control) that also exports a non-OLE C interface via an import library. Rather than build two separate libraries (for example, mydll.lib and myuuid.lib), you can list the GUID data object(s) in DLLLIBOBJECTS. The result is a single library that all your users will link against.


DLLORDER

When you are building a DLL, you can specify an order file that will be passed to the linker. The order file lists the functions and the order in which they should be linked together. By default, the Build Utility passes the name of the DLL as the name of the order file. For example, if you are building kernel32.dll, the Build Utility expects kernel32.prf as the order file.

You can use the DLLORDER macro to specify another name. The Build Utility will use whatever name you give it. It can be in a different subdirectory, have a different name, or a different an extension. You can set DLLORDER to whatever you want it to be, and you can give it a fully qualified path name.


DRIVERBASE

Similar to DLLBASE and UMBASE, use this macro to specify the base address for a driver. It's generally not necessary to set this because it will be relocated at run time anyway.


EXEPROFILEINPUT

This macro has been changed and is now exactly the same as NTPROFILEINPUT.


FREEBUILD

Use this macro to specify whether your build is checked (debug) or free (retail). You can say, “If $FREEBUILD, do things for a retail build.” Maybe you want to set a different set of flags or put it in a different place or compile a different way from a checked (or debug) build.


GPSIZE

Specify a value for this macro in your sources file to control the GPSIZE switch to the linker. The GPSIZE is an optimization used on RISC platforms (on MIPS and PowerPC only). The value used for Windows NT is 32.


HALBASE

Similar to DLLBASE and UMBASE,  use this macro to specify the base address for a HAL. It's generally not necessary to set this because it will be relocated at run time anyway.


IDL_RULES

This macro is only used for Cairo and OLE builds.


IDL_TYPE

When you specify an IDL file in your sources rule, you have to specify whether this is an OLE IDL or an RPC IDL because their syntax differs. Based on the syntax, the Build Utility passes different commands to MIDL. The default for IDL_TYPE is OLE. Both of the following commands specify OLE:

IDL-TYPE=" "
IDL_TYPE=ole

Otherwise, specify RPC:

IDL_TYPE=rpc


INCLUDES

Use this macro in your sources file to indicate to the Build Utility where to find the headers that you are including in your build. Specify a list of the paths to be searched for include files during compilation. Separate the entries in this list with a semicolon. Path names can be absolute or relative, for example:

INCLUDES=bunny;inc

INCLUDES=.\

INCLUDES=.\inc

The INCLUDES macro is read by the Build Utility. It looks at the INCLUDES variable that you specify in your sources file to figure out where to find the header files that you are including in your source code so it can build the dependency tree.

You will usually use the INCLUDES macro in your sources file to indicate to the Build Utility where to find the headers that you are including in your build. But there are times when some header files may not exist. Maybe they are built as part of the build process. Specify those header files in USER_INCLUDES.


LANGUAGE

Use this macro to specify the language when you set up dependencies so that you can include country-specific parts in your build. If you are building a product for the USA, you may want to include a USA icon, but if you are building for Korea, you would want to use a Korean one.

For example, the Exchange team used this macro because their directory tree was set up so that \LANG\LANGUAGE\USA\mainscreen.bmp was used for their main splash screen. So they could just override LANGUAGE to build their product for Korea, Japan or any other country. They set LANGUAGE to something that was unique for them: KOR for Korean, JPN for Japan and GER for German. But there is no limitation on what this can be so long as it makes sense in your build environment.

The default is LANGUAGE=USA.


LINKER_FLAGS

Use the LINKER_FLAGS macro to override any default linker switch that you want to pass to the linker. Type link-? to view a list of all the linker switches. This macro just gives you a way to pass in flags that you cannot pass in another way.


LINKER_NOREF

Use this macro to turn off switches to the linker. The Build Utility turns some switches on, by default. One of them is the OPTICAL_AND_REF switch, which says, "Throw out everything that's not referenced in this module." This is the right thing to do if you want small modules, but if you've got some debug routines in there that you want to call from the debugger, it's kind of annoying to have them all thrown away on you. To avoid this, set LINKER_NOREF in your environment, rebuild your product, load it up in the debugger, and then run these functions that are only used in the debug scenario.


LINKLIBS

Use the LINKLIBS macro to specify libraries that you need to link against. LINKLIBS enables you to specify a macro called PERFLIBS, which are extra libraries you use for a performance case.

Example:  The Windows NT Performance Lab people do that when they build the system to generate the BBT ordering files. They set PERFLIBS equal to some extra libraries that they want linked in to get some instrumentation stuff.

The only difference between TARGETLIBS and LINKLIBS is the ordering on the command line. LINKLIBS usually gets passed first; TARGETLIBS gets passed second. If you order them in your TARGETLIBS macro correctly, that shouldn't be a problem EXCEPT when you are building a DLL. When you are building a DLL, you may have some objects that you've built, but you also have some other libraries that you want to export some features from. Maybe you go to subdirectory one and compile a number of objects into a library. In subdirectory two, you compile some more into a library. In subdirectory three, you actually build the DLL, but it exports functions that are defined in library one or library two. So put those libraries in your LINKLIBS macro.

Caution! The LINKLIBS macro requires that the library has to be around in pass one of the build, because the Build Utility builds the import libraries during pass one. You must structure your build in such a manner that the libraries will be guaranteed to exist during pass one. You should never specify an import library in your LINKLIBS macro, mainly because you can get into some real nasty cases where you export something that you've imported from somebody else instead of what you actually had, perhaps with typos or whatever. You may not realize this until suddenly your program starts acting really weird. Stick with the rule that you use TARGETLIBS everywhere. There is TARGETLIBS and There is LINKLIBS; if you use TARGETLIBS for everything, life is good. (To avoid problems when doing multi-processor builds, see Multi-processor Build Issues.)

Use LINKLIBS only for the case that meets the following conditions:

•	You are building a dynamic link.

•	You are exporting something that's defined in some other component library that you also build.

•	In your dirs file in the subdirectory above, you have ordered it so that the component libraries are around before you build the dynamic link.

There is a similar macro called UMLIBS that you can use if you are building UMAPPLs.

See Also
TARGETLIBS


MAJORCOMP

Use this major component macro to specify the first part of a filename you are building for use by the MIPS compiler. Use the MINORCOMP macro to specify the minor component filename.

For example, when you build the kernel for Windows NT, you specify:

MAJORCOMP=ntos
MINORCOMP=drivers

You can use this if you have global sources file or a global rules file. You can state:

If MAJORCOMP=something

Then do something you might do for all your NTOS things, but:

If MAJORCOMP=somethingelse

Then do something you might do for all your drivers.

Note: This macro is required for MIPS and ALPHA builds.


MAKEDLL

The build process is a two-pass build. In the first pass, the Build Utility compiles all the source files, and creates import libraries and component libraries. In the second pass, it links everything against those libraries. The default, which directs the Build Utility to make the second pass, is as follows:

MAKEDLL=1

You typically would not set this for yourself. You might do a test in your makefile to say:

IF MAKEDLL=1
  do things that you want to do on the second pass of the build

A more frequent use of this macro is to run nmake from the command line to run the compile and link without having to run build.exe:

nmake MAKEDLL=1

The Build Utility will then do the compile and the link all in one step without having to run build.exe. This works because all that build.exe does is  figure out dependencies and call nmake. This works when:

•	You know the dependencies.

•	The source file has changed and you do not care about the header file dependency generation.

•	You are in a leaf node subdirectory.


MASTER_VERSION_FILE

Every image has a version resource on it. When they release a built from the Windows NT  Build Lab, they increase the master version number. Anything they link or build after that will automatically get a new version resource attached to it with the correct build number.

You can go into the File Manager or Windows Explorer or you can run filever.exe to view properties and see which version resource setup uses when it copies that image onto a new system. The system checks whether or not the version resource is newer than the one already on the system. If it is, it is copied onto the system, otherwise it is not.

There is a master version file for Windows NT, from which all version resources are built. The Master Version File for Windows NT is called ntverp and it's located in \\public\sdk\inc. You can either use ntverp or use the MASTER_VERSION_FILE macro to specify a different master version file. You do not have to have \\public\sdk\inc\ntverp.h. The VC team uses a different master version file because they have a different version scheme than the Windows NT group does.

If you look on the very last line of makefile.def, you will see the one place where MASTER_VERSION_FILE is used as a dependency for the resources. The TARGET_DIRECTORY macro is always dependent on the master version file to determine what the name of the resource is for your image.


MFC_FLAGS

If you have extra command line options you want to pass to the compiler, you can put them in MFC_FLAGS. They will only affect programs that use MFC. That would be useful if you had a global project. You could set MFC_FLAGS equal to some macro name or compiler #define that you want to add. There are other ways to handle that, however, for example by using the C_DEFINES macro.


MFC_INC_PATH

Use this macro to specify the path to the MFC headers. The default is:

$(BASEDIR)\public\sdk\inc\mfc$(MFC_VER)

Set this macro if you don't use the Windows NT directory structure.


MFC_INCLUDES

If you have your own MFC include files, use this macro to specify where you put your MFC headers on your system. This is another macro you might use if you choose not to follow the same directory structure.  asWindows NT uses.

For example, the MSN group has their own MFC libraries. They do not use the ones from Windows NT. They do not use the public directory. So, they specify their MFC_INCLUDES to be wherever they put their MFC headers on their systems.


MFC_LIB_PATH

Use this macro to specify the path to the MFC libraries. The default is $(BASEDIR)\public\sdk\lib\*

Set this macro if you don't use the Windows NT directory structure.


MFC_LIBS

Use this macro to provide explicit MFC library names and override the default names that the Build Utility uses. This is another macro you might use if you choose not to follow the same directory structure.  as Windows NT. For example, the MSN group has their own MFC libraries. They do not use the ones from Windows NT. They do not use the public directory.


MFC_VER

Use this macro to specify the version of MFC to build with.  By default, it is set to 40. Valid values must be 40 or greater. To use MFC 3.x, define USE_MFC30.


MIDL_OPTIMIZATION

Use this macro to override the default optimization that is passed to the MIDL compiler. The default is OI2.


MIDL_UUIDDIR

Use this macro to specify where the GUID file goes when you generate an OLE IDL file (UUIDs and GUIDs are the same thing). By default everything built in pass zero goes to wherever you set the TARGETPATH subdirectory. Use this macro to override that.

To create the GUIDs in the current subdirectory, set MIDL_UUIDDIR to be dot:

MIDL_UUIDDIR=.

It does not matter where you put the GUIDs so long as whatever you set here, you set your #includes to get them from here. Otherwise the subsequent tools used by the Build Utility will not be able to find the GUIDs.


MINORCOMP

Use this macro to specify the second part of the filename constructed for use by the MIPS compiler. This is required only for MIPS and ALPHA builds.


MISCFILES

Use the MISCFILES macro to list items that you want to put into the appropriate installation point when the Build Utility runs binplace.exe.


MSC_OPTIMIZATION

Use this macro to override the default optimization the Build Utility uses on the compiler. By default, everything is optimized. If you want to turn off optimization to step through your code, you can set MSC_OPTIMIZATION to whatever is appropriate for your compiler. Most people in the Windows NT group use /Odi, which is unoptimize everything, for the code they want to hand debug. All of these flags also have platform-specific variants. If you know your code works great on all platforms except PowerPC, you can set the MSC_WARNING_LEVEL to /W3/WX and then you can say PPC_WARNING_LEVEL=/W1. The same is true for optimization, you can specify PPC optimization or MIPS optimization or Alpha optimization or i386 optimization to override for each specific platform. If you do not specify any of those, MSC optimization will be the default. If you do not specify MSC_OPTIMIZATION, the default is:

Oxs - Fully optimize, size overrules speed.

While performance testing Windows NT, it was determined that the overhead from handling page faults and cache misses usually outweighs any optimization the compiler might make that results in larger code. Therefore /Oxs is used by default. It directs the compiler, "when presented with an optimization choice that is either bigger/faster or smaller/slower, choose the smaller case". This is also the reason why /G5 isn't used when compiling for X86. /G5 directs  the compiler to break complex instructions into several more primitive instructions that the Pentium can run faster. Again, larger code typically means more page faults and the net result is slower performance.

If, after testing for yourself, you find that this is not the case for your code, you can always override the generic MSC_OPTIMIZATION macro with platform-specific macros. They are:

MSC_OPTIMIZATION (all platforms)
ALPHA_OPTIMIZATION (Alpha)
386_OPTIMIZATION (Intel)
MIPS_OPTIMIZATION (Mips)
PPC_OPTIMIZATION (Power PC)

See Also
MSC_WARNING_LEVEL


MSC_WARNING_LEVEL

Use this macro to set the warning level to use on the compiler. The default is W3. After you have your code building without errors, you probably want to change MSC_WARNING_LEVEL to /W3/WX, which always makes any warnings an error.

MSC_WARNING_LEVEL is generic to all platforms. Platform-specific variants include:

i386_WARNING_LEVEL

MIPS_WARNING_LEVEL

ALPHA_WARNING_LEVEL

PPC_WARNING_LEVEL

See Also
MSC_OPTIMIZATION


NOLINK

The NOLINK and MAKEDLL macros are primarily used in the master makefile (makefile.def) to indicate which rules to enable or disable when the Build Utility goes through two tools. NOLINK=1 indicates a link isn't supposed to occur (most likely because this is pass one and build cannot guarantee the libraries needed are built yet). MAKEDLL=1 indicates a link should occur and is  used in pass two after all the libraries are built. If you run a one-pass build (by specifying -z on the command line to build), only MAKEDLL=1 is specified.

You can test for this macro in your makefile. You can say, if NOLINK=1, then you know you are in pass one; if MAKEDLL=1, then you know you are in pass two because in the first pass you do not want to link and in the second pass you just want to make the DLL.

See Also
MAKEDLL


NOMFCPDB

By default whenever you are building an MFC program, the Build Utility generates the symbolic debugging information in a PDB file (a program database). MFC has so much stuff, the Build Utility puts it in the PDB. If you define NOMFCPDB, it won't.


NOT_LEAN_AND_MEAN

The windows.h file checks to see if WIN32_LEAN_AND_MEAN is defined. If it isn't, it includes every header file; if it is, it only includes the Windows headers. All of Windows NT builds that way.

So if you include windows.h, you get just Windows. If you want OLE and RPC and all the net stuff, you include those headers as you need them.

The SDK ships with this undefined. If you've got code that you brought over from the SDK or if you've built it in the VC build environment, you probably included windows.h and got all these things for free without realizing that it just made your build so much slower. When you are bringing code over from that environment, define the following in your sources file:

NOT_LEAN_AND_MEAN=1

Then it will all continue to work the same way it worked in your old build environment.

The right thing to do, of course, would be to go through and get rid of unneeded headers, but sometimes that's more work than is necessary.


NO_NTDLL

Use this macro to indicate that NTDLL.LIB should not be automatically added to the library list.


NT_INST

This macro is used internally by the Windows NT build group to specify instrumentation. Some components for Windows NT use it to enable some special instrumentation when building. Whatever you set this value to will be passed to the compiler as is. For example:

NT_INST=1

Results in:

/DNT_INST=1

passed to the compiler. The default is /DNT_INST=0.


NT_UP

Use this macro to indicate whether your driver will run on a uniprocessor machine or multiprocessor machine. The default is uniprocessor, as follows:

NT_UP=1

To specify multiprocessor, set”

NT_UP=0


NTDBGFILES

Use this macro to control whether symbols should be stripped from final image files when the Binplace Utility is run by the Build Utility.

Binplace.exe is the utility that the Build Utility uses to create the final installation format for an image. When you build a CD, the Binplace Utility directs which images go in the root of the CD, which images go in different subdirectories, which .inf files need to be in certain subdirectories with other files, and which symbols need to be split off.

As part of this process, the Build Utility enables you to split off the symbols that are used for debugging. This is because in the Windows NT build environment, everything built has symbols. But the final product is not shipped with symbols. Instead, the Build Utility directs binplace.exe to strip the symbols from all the images and put them in a symbols subdirectory. Then the Windows NT group ships the binary subdirectory. The symbols subdirectory goes out separately on the CD, the SDK, or the DDK.

What determines whether or not the Build Utility should split off symbols is based on whether NTDBGFILES is set.

You usually do this in your environment, not in your sources file.

You should do this on your build machine rather than on all of your developers' machines because they probably want the symbols there. It’s easier to track. The debugger does not have to do all this hand waving to find the debug symbolic files that match the images themselves.


NTDEBUG

Use this macro to specify what type of symbolic information you want when building (and therefore which debugger you'll be using).  It is rarely used in the sources file, instead it should be set in the environment before building the project.

To indicate a checked (or debug) build, specify:

NTDEBUG=ntsd

To indicate a free (or retail) build, specify:

NTDEBUG= ntsdnodbg

The only difference between the two of them is that specifying ntsd causes the Build Utility to define DBG=1 and ntsdnodbg causes it to define DBG=0, so the Build Utility can direct the code to do or not do something based on the value of DBG. Some groups, such as the VC group, define _DEBUG  for their debug version and NDEBUG  for their non-debug version.


NTDEBUGTYPE

The Blue text on the NTDEBUGTYPE page - Yes, ntsd does specify coff information... and it does make sense... :-)  The paragraph at the bottom can be removed.  Instead, for NTDEBUGTYPE=windbg, we should add: "specifies Codeview information in the final image.  If you want to generate a program database (.PDB file) for the CV info, you'll need to set USE_PDB=1 also.

Use this macro to specify the method of linking, which symbols are used.

NTDEBUGTYPE=ntsd The ntsd information is only useful for debugging with NTSD, which is our character-mode debugger that ships with the system and Kernel Debugger (KD). The other debuggers understand CodeView, so most people want to stick with windbg for everything because every debugger understands it.

NTDEBUGTYPE=windbg (specifies CodeView information in the final image.  If you want to generate a program database (.pdb file) for the CV information, you'll need to set USE_PDB=1 also.)

NTDEBUGTYPE=coff

NTDEBUGTYPE=both (Specifies both CodeView and ntsd information.)

Any of these settings used for NTDEBUGTYPE will compile with C7, which means put the CodeView information in every object. There is a C9 compiler from the VC group and a C10, C11, which enables you to put all the type information in a program database (PDB). If you want to do that, you have to say USE_PDB=1 in your sources file or in your environment. This is not recommended, however.


NTKEEPRESOURCETMPFILES

In the Windows NT build, the RC Compiler generates a binary file, but it cannot be linked into a final image because it hasn't been converted to the right format. When you do a Windows NT build, the Build Utility converts it as soon as the RC Compiler creates it. In most other build processes, they convert it when they link it in. This means that, in our case if you build it once, it can be linked as many times as you want and it will never need to be reconverted. In their environment, every time you link it, you reconvert it. But in their environment, after you run it through our C, you can still bring it up in other tools that understand the RC output. In the Windows NT environment, it's been converted and it's not in the RC output any more. So, if it’s important to you that it stay in the RC output and not be converted, you have to set:

NTKEEPRESOURCETMPFILES=1

All that says is "Do not do the conversion after you build it. Hold off on converting it until you go to link it." Every time you link it, it will convert it. This makes your links a little slower, but it means you can use other tools, such as the Visual C Resource Editor, to modify it before you link it.


NTNOFUZZYLOOKUP

This macro was added to help bring other projects into the build environment for Windows NT.

By default, in the method used by Windows NT, you have a .def file. You may have a DLL that you want to build. That DLL is going to export functions a, b, and c. But on x86, it may be _bunny@8; on MIPS, it may be bunny; on Alpha, it may be _bunny. So they all have unique names, but you do not want to have a different .def file for each platform because then it becomes a maintenance nightmare. What you instead want to do is state in your .def file, "Export function a. Exporting function b." Then call the linker to say, "Here is the .def file and here are all the .obj files. Go figure out what the right name is supposed to be." That's called fuzzy matching.

Some people have set up their build environments so that they specify the fully declared name in the .def file. So instead of saying “Export function a” or “Export function b,” they say export_functionb@8. If they do that, they already have the declared name in there. They've just made it so that every time they do a new platform, they've got to go through and edit their .def files and add in the new funky names. If you are bringing a project over that does that, you can prevent the extra step of passing in all the objects and directing the linker to figure out the right names by stating the following in your sources file:

NTNOFUZZYLOOKUP=1

Once you specify a declared name and you ship a product with the declared name in it, you've got to use that from now on. It makes it very hard, but sometimes it's too late. You cannot fix it. That's when you specify NTNOFUZZYLOOKUP.


NTNOPCH

Use this macro to turn off precompiled headers for a single source file.

If you have precompiled headers on a subdirectory, the Build Utility expects you to build that subdirectory and then make subsequent changes as you go along. Whenever you change one of the source files, you need to rebuild that file. The Build Utility will detect that you used precompiled headers there, and will compile that single source file without them. That enables you to build everything, then change a definition in a header file (for example, a #define something to something else). Then you change the source file to use that new definition. You really do not want to regenerate the precompiled header and rebuild everything else. You just want to rebuild that one source file. But you do not want to use the old precompiled header because that information is not valid any more. So in that case, the Build Utility does a non-precompiled header build. For that one source file, it turns off precompiled headers. That makes it reread all the headers, and all the type information is then correct. That's only going to happen when you do a build with a -Z or -z switch when you are directing it to not scan dependencies and therefore do not regenerate the precompiled header.


NTPROFILEINPUT

The linker lets you specify a profile, which is a list of all the functions or symbols in your image and the order you want them emitted in the final image. You can optimize page usage by listing the functions in the order they should be emitted in the final image. You can automate this list generation with the Working Set Tuner (wst.exe).

To use the profile, specify the following in your sources file::

NTPROFILEINPUT=1

If you set that, the Build Utility expects to find the name of the thing you are building with a .prf filename extension in the current subdirectory. If you are building kernel 32, it expects to find kernel32.prf in the current subdirectory. The Build Utility will use that to order the final image that it builds.


NTTARGETFILE0

You can define NTTARGETFILE0 and/or NTTARGETFILES to cause makefile.def to include .\ makefile.inc immediately after it specifies the top level targets (all, clean and loc) and their dependencies. The makefile.def file expands NTTARGETFILE0 as the first dependent for the "all" target and NTTARGETFILES as the last dependent for the "all" target. Use this to specify additional targets and dependencies that do not fit the general case covered by makefile.def.

NTTARGETFILE0=

The fact that NTTARGETFILE0 exists, even if it is defined to nothing, means that the Build Utility should open makefile.inc in the same subdirectory as the sources file. If you set NTTARGETFILE0, what you are saying is, “Not only should you include makefile.inc, but you should also build the thing that the macro defines.” So if:

NTTARGETFILE0=myfile.a

Then, as part of pass zero, the Build Utility will build myfile.a.

If you do not set NTTARGETFILE0, the Build Utility will go down to the specified subdirectory on pass zero, include makefile.inc, and do any default rules that it contains.


NTTARGTFILE1
NTTARGETFILE1

NTTARGETFILE1 is exactly like NTTARGETFILE0,  except that it happens later in the build process. NTTARGETFILE0 happens on pass zero; NTTARGETFILE1 happens on pass two. Both of these macros cause the Build Utility to change directories to a specified subdirectory and run nmake on pass zero or pass two where it might not ordinarily do that.


NT_TARGETFILES
NTTARGETFILES

If you have unique rules in your subdirectory, you can set up this  macro to key the build process to say that along with your sources file in the subdirectory, you also have a makefile.inc, which can include extra dependencies, extra command line rules, anything you want to build.


O

Use this macro to specify the final objects subdirectory. Define this macro in your sources file or in makefile.inc to be certain something goes into the object subdirectory. The benefit of using $(O) is that any files that you have built and placed in the objects subdirectory will be deleted on the next clean build. This guarantees that no collisions will occur between two builds running on the same machine at the same time. They will never override each other's files if you follow the convention that everything you build goes in $(O).


OAK_INC_PATH

Use this macro to specify the path to the OEM Adapter Kit headers. The default is:

$( BASEDIR)\public\oak\inc

Set this macro if you don't use the Windows NT directory structure.


PASS0_CLIENTDIR

PASS0_CLIENTDIR, PASS0_HEADERDIR, and PASS0_SERVERDIR are used when you have a SOURCES macro in your sources file. That macro can contain the following types of files:

•	C

•	C++

•	RC

•	MC

•	IDL

Use the PASS0_CLIENTDIR, PASS0_HEADERDIR, and PASS0_SERVERDIR macros to specify where to put the output from MC and MIDL.

When you have IDLs in your SOURCES macro and run MIDL, you generate a server part, a client part, a header, and a default source. You specify where you want to put that output in PASS0_SERVERDIR and PASS0_CLIENTDIR.

When you run MC, you create a header and a source file. You put that in PASS0_HEADERDIR and PASS0_SOURCEDIR to specify where you want to put that output.

When you are building a MIDL stub, it's RPC, so you have what runs on the client side and what runs on the server side. There are stub programs that communicate in RPC to each other. You can override those by default.


PASS0_HEADERDIR

Use this macro to specify where the headers generated by MC and MIDL go. By default everything built in pass zero goes to wherever you set the TARGETPATH subdirectory. Use this macro to override that.

To create the headers in the current subdirectory, set PASS0_HEADERDIR to be dot:

PASS0_HEADERDIR=.

It does not matter where you put the headers so long as whatever you set here, you set your #includes to get them from here. Otherwise the subsequent tools used by the Build Utility will not be able to find the headers.

See Also
PASSO_CLIENTDIR


PASS0_SERVERDIR

Use this macro to specify where the server part generated by MIDL goes. By default everything built in pass zero goes to wherever you set the TARGETPATH subdirectory. Use this macro to override that.

To create the server part in the current subdirectory, set PASS0_SERVERDIR to be dot:

PASS0_SERVERDIR=.

It does not matter where you put the server part so long as whatever you set here, you set your #includes to get them from here. Otherwise the subsequent tools used by the Build Utility will not be able to find the server part.

See Also
TARGETPATH
PASSO_CLIENTDIR


PASS0_SOURCEDIR

Use this macro to specify where the source code generated by MIDL and maketype.lib file goes. By default everything built in pass zero goes to wherever you set the TARGETPATH subdirectory. Use this macro to override that.

To create the source code generated by MIDL and maketype.lib in the current subdirectory, set PASS0_SOURCEDIR to be dot:

PASS0_SOURCEDIR=.

It does not matter where you put the source code generated by MIDL and maketype.lib, so long as whatever you set here, you also set your #includes to get them from here. Otherwise the subsequent tools used by the Build Utility will not be able to find the source code generated by MIDL and maketype.lib file.

See Also
TARGETPATH
PASSO_CLIENTDIR


PNP_POWER

This macro is used internally by the Windows NT build group to specify plug-and-play power definition. This enables you to build a driver that understands plug and play. If it's not set, the Build Utility does not define a value; if it is, the Build Utility defines

PNP_POWER=1


PRECOMPILED_CXX

Use this macro to indicate whether the precompiled header you are building will be used with C files or with C++ files. The default is to use precompiled headers with C. Therefore, to use the precompiled header with C, do not set PRECOMPILED_CXX at all.

To use the precompiled header with C++ files, specify

PRECOMPILED_CXX=1

See Also
Precompiled Headers


PRECOMPILED_INCLUDE

Use this macro to specify the name of the precompiled header. For example, if you have precompiled headers that are a.c, b.c, and c.c as your source files, and all of them include precomp.h, specify:

PRECOMPILED_INCLUDE=precomp.h

If you omit this, you will not be able to have precompiled headers. PRECOMPILED_INCLUDE is what triggers the build process to understand that you do have precompiled headers.

See Also
Precompiled Headers


PRECOMPILED_OBJ

By default, the Build Utility takes the precompiled header with the precompiled #include setting that you specify, for example precomp.h. Out of that, it creates precomp.obj for the precompiled object and precomp.pch for the precompiled target. You can override those names by setting the PRECOMPILED_OBJ and PRECOMPILED_TARGET macros.

See Also
Precompiled Headers


PRECOMPILED_TARGET

By default, the Build Utility takes the precompiled header with the precompiled #include setting that you specify, for example precomp.h. Out of that, it creates precomp.obj for the precompiled object and precomp.pch for the precompiled target. You can override those names by setting the PRECOMPILED_OBJ  and PRECOMPILED_TARGET  macros.

See Also
Precompiled Headers


RC_COMPILER

The Exchange team uses this macro when they are compiling different builds for different countries. They set the RC code page equal to the code page for Korea, and set the Japanese one to the code page for Japan. That informs the RC Compiler about what to expect from the input side so it can translate the correct code page. If you do set the code page, it will be passed as the -C switch to the Resource Compiler. You can override other switches to the Resource Compiler with RC_OPTIONS.


SDK_INC_PATH

Use this macro to specify the path to the SDK headers. The default is:

$(BASEDIR)\public\sdk\inc

Set this macro if you don't use the Windows NT directory structure.


SDK_LIB_PATH

Use this macro to specify the path to the SDK libraries. The default is:

$(BASEDIR)\public\sdk\lib\*

Set this macro if you don't use the Windows NT directory structure.


SOURCES

The SOURCES macro is the most important macro for the Build Utility. You must have this macro in your sources file. The SOURCES macro specifies which files are going to be compiled. The Build Utility will look at these files and generate a dependency list. If any of those dependencies change, the Build Utility will rebuild this source file.

Use this macro to list your source filenames (except for the file containing main. Include the filename extension and separate the entries in this list with spaces or tabs.


SOURCES_USED

Use this macro to indicate that another sources file or makefile exists elsewhere in the tree when that file has things in it that your build is dependent upon. When you specify:

SOURCES_USED=filename_someplace_else

nmake will regenerate the objects file when your sources file in this directory changes and also when another sources file or makefile that you specified in SOURCES_USED changes.

For example, the first thing you do in your sources file is include some other file. Then, right underneath that, specify:

SOURCES_USED=that_filename

This establishes a link between that file and the sources file. When that other file changes, nmake will regenerate objects.mac.


SUBSYSTEM_VERSION

If your product has to run on Windows NT 3.1 or 3.5 or 3.51, set your subsystem version to that version number. For example, in the current setup program of Windows NT:

SUBSYSTEM_VERSION=3.1

This is the most common usage. If you do not set SUBSYSTEM_VERSION, the default will be whatever the current build of Windows NT is.

You can also set individual subsystem versions. If you want to set the Windows version to 4.0, specify:

SUBSYSTEM_WINVER=4.0

Likewise, you can set:

SUBSYSTEM_CONVER
SUBSYSTEM_OS2VER
SUBSYSTEM_POSIX
SUBSYSTEM_NATVER


TARGET_CPP

Use this macro to specify name of the compiler. Instead of having to specify that on x86 it’s CL386 and on MIPS, it’s CLMIPS, and on PowerPC, it’s CLPPC, you can simply specify:

TARGET_CPP=name_of_compiler


TARGET_DIRECTORY

Use this macro as follows to specify the target directory when you want some dependency file to always end up in the obj subdirectory:

TARGET_DIRECTORY=some_sourcefile:some_dependency_file

This enables you to do platform-specific builds from the same source tree at the same time and they won’t override each other. You do not have to hard code the name of the platform.

For example, if you have a special build rule for some feature in your code or if you want to build a particular object from a particular C file, specify:

obj\$(TARGET_DIRECTORY)\filename.obj; filename.c

By using the TARGET_DIRECTORY macro, you guarantee that it’s going to end up in the correct platform subdirectory, such as \obj\i386subdirectory\obj\.

There are some default targets. One of them is .cod. If you go to a subdirectory where you've got source files and specify:

nmake SOURCE_FILE_NAME=.cod

it will create an assembler listing for you that you can view to see where the compiler erred.

There is another default target called .pp file, a preprocessed listing. Preprocessing adds line numbers. You can look view to see where the Build Utility got your headers, and which #defines and what kinds of structures it added.

The other thing with a .pp file is that you can send it out to the compiler group if something goes wrong. It's all self-contained. They do not have to have any header files or anything like that in their environment You can just give it to them. They are usually quite large, in the neighborhood of a meg or more, with several hundred thousand lines. You can send that to the compiler group.

You can, again, go to a subdirectory where you have a source file and say:

nmake SOURCE_FILE_NAME=.pp

and it will preprocess it.

The .cod and .pp files are very useful for tracking bugs in the build process.


TARGETEXT

Use this macro to specify the extension name (such as .cpl) when you want the DLLs to have something other than .dll as the filename extension.

If you specify something unexpected, you will see a message "Unexpected Target Ext." If you want an extension added to the Build Utility, contact Bryan Tuttle (bryant).


TARGETLIBS

Use TARGETLIBS to specify other libraries that you want to link against when building your image. It should be your primary method for specifying libraries or objects you want to link against to build your image.

You can also use the LINKLIBS macro to specify libraries that you need to link against. The only difference is the ordering on the command line. LINKLIBS usually gets passed first; TARGETLIBS gets passed second. If you order them in your TARGETLIBS macro correctly, that shouldn't be a problem EXCEPT when you are building a DLL. When you are building a DLL, you may have some objects that you've built, but you also have some other libraries that you want to export some features from. Maybe you go to subdirectory one and compile a number of objects into a library. In subdirectory two, you compile some more into a library. In subdirectory three, you actually build the DLL, but it exports functions that are defined in library one or library two. So put those libraries in your LINKLIBS macro.

Caution! The LINKLIBS macro requires that the library has to be around in pass one of the build, because the Build Utility builds the import libraries during pass one. You must structure your build in such a manner that the libraries will be guaranteed to exist during pass one. You should never specify an import library in your LINKLIBS macro, mainly because you can get into some real nasty cases where you export something that you've imported from somebody else instead of what you actually had, perhaps with typos or whatever. You may not realize this until suddenly your program starts acting really weird. Stick with the rule that you use TARGETLIBS everywhere. There is TARGETLIBS and There is LINKLIBS; if you use TARGETLIBS for everything, life is good. (To avoid problems when doing multi-processor builds, see Multi-processor Build Issues.)

Use LINKLIBS only for the case that meets the following conditions:

•	You are building a dynamic link.

•	You are exporting something that's defined in some other component library that you also build.

•	In your dirs file in the subdirectory above, you have ordered it so that the component libraries are around before you build the dynamic link.

There is a similar macro called UMLIBS that you can use if you are building UMAPPLs.


TARGETNAME

Use this macro to specify the name of the library being built, excluding the filename extension. You must have this macro in your sources file.


TARGETPATH

Use this macro to specify the target directory name that is the destination of all build products ( such as .exe, .dll, and .lib files). Notice that object files always end up in the obj subdirectory. You must have this macro in your sources file. For example:

TARGETPATH=obj

See Also
Specifying Libraries


TARGETPATHLIB

Use the TARGETPATHLIB macro to specify where to put the import library when you are building a DLL.

When you are building a DLL, you create the DLL itself and you create an import library that other images can use that need to use your DLL. For example, a Windows NT developer built kernel32.dll and also kernel32.lib that users of kernel32.dll would link against. In the past, you would handle all that by specifying:

TARGETPATH=publicsdk.lib

and it would put both the DLL and the import library in the public tree. By specifying TARGETPATHLIB, you can say, “Put the library in the public tree.” Then you can set TARGETPATH=obj and we use the DLL in the obj subdirectory in the source tree and put the import library in the public tree where people might want to share it.

The VC team uses this because on their release point they have the root of the VC tree and then they have a bin subdirectory and a lib subdirectory. They put all their DLLs in the bin subdirectory and all their libraries in the lib subdirectory. So they would specify:

TARGETPATH=bin
TARGETPATHLIBS=vc\lib


TARGETTYPE

Use this macro to specify the type of product being built. This is typically LIBRARY or DYNLINK (for DLLs), but can take other values. This is a required field in the sources file. TARGETTYPE gives the Build Utility  some clues about some of the input files that it should be expecting. You must have this macro in your sources file. The valid values for TARGETYPE include:

PROGLIB is an executable that exports something. It's a program library.

PROGRAM - This is just a plain, program file that does not export anything. It just imports stuff in the default .exe on the command line.

DYNLINK - A DLL, a control panel applet, anything that can be dynamically loaded or that people can import from that has to have when its linked, it uses the DLL switch to the linker to indicate it's not a standalone .exe. It's actually something that's dynamically linked. When you build a dynamic link, you may also need to set the TARGETEXT macro.

LIBRARY - A component library. This is a library of objects, not an import library (an import library is built as a side effect of building a dynamic link. Anytime you build a dynamic link, you get a .lib file and a .dll file. When you build a library, you just get a .lib file.)

DRIVER - A system kernel driver.

EXPORT_DRIVER - An export driver is like a driver except it exports things. It provides services to other drivers. There are two of those in Windows NT.

HAL - Hardware Abstraction Layer.  This is the kernel HAL for Windows NT.

BOOTPGM - A kernel driver.

MINIPORT - A kernel driver.

GDI_DRIVER - A kernel driver that is similar to a DLL, which is loaded in user and kernel space. This was added for Windows NT 4.0.


UMAPPL

This macro enables you to build multiple targets from a single subdirectory where every target is a source file and some other .lib files that you link against.

To use this macro, specify a list of source filenames containing a main function. Specify these filenames without filename extensions and separate them with an asterisk. For example:

UMAPPL=a*b*c*d

The Build Utility will compile and link each file in this list after the main target in the sources file is built. The only restriction is that there can only be one source file and you must specify what it links with using the UMLIBS macro.

The Build Utility links against whatever things you list in the UMLIBS macro. Those things could be a .res file if you have a common resource, a library that you just built in a subdirectory, a library or object from another subdirectory. There is no limit to what can be listed in UMLIBS.

The difference between UMTEST and UMAPPL is that if you use UMTEST, you need to specify the executable names that need to be built through the command line to build.exe. If you use UMAPPL, you need not specify anything on the command line, and build.exe will automatically build all the program files.

See Also
UMLIBS
UMTEST


UMAPPLEXT

Use this macro to specify the extension name (for example .COM or .SCR) that will be appended when you want image files to have multiple filename extensions when you are building from a single source file. Use UMAPPLEXT when you want the extension to be something other than .exe. If you want the filename extension to be .exe, use UMAPPL. If you have questions about using UMAPPLEXT, see makefile.def or contact Bryan Tuttle or Wes Witt.


UMBASE

You only need to use this macro when you are building a dynamic link library (a DLL). Use it to set the base address for the DLL image you are creating. If you do not specify an address, the Build Utility will assume that the target name in coffbase.txt is the name of your image. You can override this default target name by specifying a target name with the DLLBASE macro. You can set DLLBASE to be the hard-coded base address, a hex address, or you can leave it blank. If you leave it blank, the Build Utility will always look up the target name specified in coffbase.txt.

Example:  If you are building kernel32.dll, the Build Utility will look up kernel32 in coffbase.txt to find that base address.


UMENTRY

Use this macro to override the default entry point (mainCRTStartup) and specify the entry point depending on the UM Type. You can set this name to be anything you choose. If the UM Type is Windows or Console, the default entry point is main and you can override it with winmain, wmain, or wwinmain.

You can only use this macro if your UMTYPE is Windows or Console.


UMENTRYABS

Use this macro to specify an absolute entry point. For example, you might specify:

UMENTRY=main

but the real entry point is mainCRTStartup. If you do not want mainCRTStartup to be the entry point, specify UMENTRYABS to make main the absolute entry point. This prevents the Build Utility from going through the translation table that says if it’s main, make it mainCRTStartup.


UMLIBS

Use this macro to specify a list of library path names to be linked to the files specified in UMTEST or in UMAPPL.  Include the library generated by the sources file. Separate the entries in this list with spaces or tabs.


UMTEST

Use this macro to list source filenames containing a main function. Type these filenames without filename extensions and separate them with an asterisk.

UMTEST=a*b*c*d

The Build Utility compiles and links each file in this list.

See Also
UMAPPL


UMTYPE

Use this macro to specify the type of product being built:

Set UMTYPE to This:	To Specify This:
windows	A Win32 Program
nt	A Native Kernel-mode System Windows NT Program
ntss	A Windows NT Subsystem
os2	An OS/2 Program
posix	A POSIX Program
console	A Win32 Console Program


USE_CRTDLL

Depending on how you want to link your image, you can link runtime libraries from the DLL for Windows NT or use:

•	The runtime libraries in a DLL

•	The multi-threaded runtime libraries

•	The single-threaded runtime libraries

•	The kernel runtime libraries

•	No runtime libraries at all

Use this macro, or one of the following macros, to define the type of runtime library you are using. Which one of these macros you use will depend on the type of runtime libraries you want to have on your system.

This Marco:	Specifies This Runtime Library:
USE_CRTDLL	Multi-threaded runtime in a DLL
USE_MSVCRT	Multi-threaded runtime in a DLL
USE_LIBCMT	Multi-threaded static
USE_LIBCNTPR	Kernel
USE_NTDLL	The DLL for Windows NT
USE_NOLIBS	None
The default is LIBC, statically linked in single-threaded runtime libraries. If you do not define any of these macros, you get LIBC.


USE_INCREMENTAL_LINKING

Use this macro to direct the Build Utility to use incremental linking.

USE_INCREMENTAL_LINKING=1

If you are running on slower hardware, you may find that using incremental linking can speed up the build.

See Also
USE_PDB.


USE_LIBCNTPR

See USE_CRTDLL.


USE_MFC

Use this macro in your sources file to indicate you are using MFC. The syntax is:

USE_MFC=1

This will establish the correct build environment for a program that needs to use MFC. The Build Utility supports either MFC3 or MFC4.


USE_MFC30

Use this macro to direct the Build Utility to use MFC version 3.0 headers and libraries when building. You must list this with USE_MFC or USE_MFCUNICODE  to be effective.


USE_MFCUNICODE

Use this macro in your sources file to indicate you are using Unicode MFC. The syntax is:

USE_MFCUNICODE=1

This will establish the correct build environment for a program that needs to use Unicode MFC. The Build Utility supports either MFC3 or MFC4.


USE_MSVCRT

See USE_CRTDLL.


USE_NATIVE_EH

If you are using Try Catch and Throw, the standard C++ exception handling (C++EH), you must specify the following in your sources file:

USE_NATIVE_EH=1

This directs the Build Utility to turn on some needed switches to the compiler.


USE_NOLIBS

See USE_CRTDLL.


USE_NTDLL

See USE_CRTDLL.


USE_PDB

If you want a VC4 PDB for your debug symbolic files, specify:

USE_PDB=1


USE_STATIC_MFC

The Build Utility always uses MFC in a DLL, but there are a number of cases where that's not available. In those cases, specify USE_STATIC_MFC in your sources file. Then the Build Utility will link MFC into your program statically instead of dynamically loading it from a DLL. Your program will get bigger, but you can do more things.

If you need to redefine or change the MFC code, specify USE_STATIC_MFC because that enables you to make the changes you need, and whatever you do not change will be linked in for you. If you build a DLL, you must use what’s in the DLL. You cannot override classes. You cannot add new members. You cannot change arguments.

It’s highly unlikely that you will ever need to use this macro. This macro was used in one case where the rich edit support was not correct for Windows NT.


USECXX_FLAG

This macro enables you to go to a subdirectory that has all C files and compile them with the C++ compiler rather than the C compiler. One reason for doing that might be switching to C++. Rather than change all your filenames to be a.cpp, b.cpp, which is a lot of work for no real gain, you can just specify:

USECXX_FLAG=/Tp

That switch directs the compiler to compile this subdirectory using the C++ compiler instead of the C compiler.


USER_C_FLAGS

Use this macro to specify flags that only go to the C/C++ compiler. Unlike C_DEFINES,  USER_C_FLAGS doesn't go to the RC compiler.


USER_INCLUDES

You will usually use the INCLUDES macro in your sources file to indicate to the Build Utility where to find the headers that you are including in your build. But there are times when some header files may not exist. Maybe they are built as part of the build process. Specify those header files in USER_INCLUDES to notify the Build Utility, “Here’s another place to go, but do not worry if you cannot find these header files because there may not be anything there.”

The reason you put things in USER_INCLUDES is because you do not want the Build Utility to do dependency checking on them. They either will be there or they won’t, but it’s not up to the Build Utility to figure out if they’re not found.


USE_LIBCMT

See USE_CRTDLL.


Building NT Software
Building Windows NT Software

The Build Utility assumes you are building the current version of Windows NT (current meaning what Windows NT is currently working on, not what has already shipped). If you are building something that needs to run on a future version of Windows NT, there are other settings available.

If you have a single set of source files that build for Chicago, Windows NT, or future versions of Windows NT, there are some macros that you can specify in your source code to do that. They are:

WIN_32_WINNT for Windows NT

WIN32_WINDOWS for Chicago or Win95


Building Chicago Software

The Build Utility assumes you are building the current version of Windows NT (current meaning what Windows NT is currently working on, not what has already shipped). If you want to build a Chicago binary, specify the following in your sources file:

CHICAGO_PRODUCT=1

This defines some variables to indicate to the Build Utility that you are building a Chicago product. It defines Chicago to be equal to 200. It does not use any of the system DLLs for Windows NT. It always uses just kernel 32 DLLs. If you specify this in your sources file, when you are all done building, you should have an .exe that will run fine on Win95 and on Windows NT at the same time.

This macro was used by the OLE team.


Building Win32 Subsystem Software

In the sources file describing a Win32 build product, set UMTPYE to windows:

UMTYPE=windows

This selects the appropriate libraries and entry point for the build product(s).

For an example of a sources file that builds a Win32 program, see \\rastaman\ntwin\src\shell\accessory\calc\sources.


Rules

•	There are a number of limitations and rules associated with the Build Utility.

•	Only one DLL or library may be built in a given source directory. The equivalent of an import library will be generated automatically when you build a DLL.

•	Any number of .exe files can be generated, as long as each one consists of a single source file (containing main) that is to be linked to the library or DLL being generated.

•	If your DLL needs to link with other libraries, these libraries must be specified in the TARGETLIBS statement within your sources file. These libraries must be specified with the same * notation as described for UMLIBS.

•	Build.exe does not understand NMAKE macros or conditional syntax. So the value of a BUILD keyword in a sources file must be textual; it cannot contain references to NMAKE macros.

•	Only files in the current subdirectory, one directory above, and in the platform subdirectory can be listed in the SOURCES macro.


Debugging

In the build environment for Windows NT, you can always debug what you build. No matter how you build using the Build Utility, you get debug symbolic files. This is different from other build processes. In the VC build environment, when you are building debug you get debug symbolic files; when you are building retail, you get nothing You control the type and amount of symbolic information with the NTDEBUG,  NTDEBUGTYPE,  and MSC_OPTIMIZATION variables.  For example, NTDEBUG=ntsd, NTDEBUGTYPE=both, MSC_OPTIMIZATION=/Odi will allow you to single step through your code with windbg and the VC ide or you can asm debug with ntsd or the kernel debuggers.


Frequently Asked Questions

Question #1:  I have a new multi-processor machine.  How do I take advantage of it with build?

Question #2: I've read the help file.  I've tried the quick start.  I still have more questions.  Is there anyone I can ask for help?

Question #3:  What about Win16 or OS/2? I have legacy code I need to maintain and the build process I use works. Can I integrate it into the build utility?

Question #4:  What's the best way to convert a project to use the Build Utility?

Question #5:  How do I generate debugging information?

Question #6:  What's the difference between free and checked builds?

Question #7:  What happened to all the makefiles?

Question #8:  Where is my .def file?

Question #9:   Do I have to edit the dirs files to customize which components I build?

Question #10:   I get a return code of 4b from binplace - why?

Question #11:   I am getting a load of undefined symbols which I know are exported from a DLL  (often the shell DLL msvcshl$(D)). Why?

Question #12:   Where do the build errors go? I need to know what failed.

Question #13:  How do I get browse information?

Question #14:  I have a number of small tools that have a subset of common code. There is just one source file between them that’s different. Can I avoid having a different subdirectory for each one of these little baby tools?

Question #15:  I've got five subdirectories and they all use all the same headers. I want to put one precompiled header someplace and have all of them use it.

Question #16:  I do not like the idea of having a public folder on my machine. Do I have to follow the build model for Windows NT that uses this directory structure?


Glossary

GDI

GUIDs

Hardware Abstraction Layer (HAL)

IDL

MIDL


GUIDs

Global Unique Identifiers. A GUID is a 16-byte structure that you use to identify classes in OLE.


GDI

Graphics Device Interface


Hardware Abstraction Layer

It is a dynamic link library (DLL) that protects the Windows NT Executive from variations in different vendors' hardware platforms to maximize the operating system's portability. The HAL implements functions that abstract I/O interfaces, the interrupt controller, hardware caches, multiprocessor communication mechanisms, and so forth.


IDL

Interface Description Language. This is used for RPC code to handle stubs that specify how to marshal arguments between the client and server.


Answer #1
Answer

Usually, it is very simple.  Just add -M to the command line when you start the build utility.  If you want this as the default, add it to your BUILD_DEFAULT environment variable.  For more information, see Multi-processor Build Issues.


Answer #2
Answer

Send mail to BryanT or the NT build lab.


Answer #3
Answer

There are several ways to do this. The easiest is to create a sources file  which builds no target.  It can then call your existing build process. In this case, the Build Utility is used strictly to spawn nmake.  Here's an example:

======== Sources file ========

TARGETNAME=

TARGETTYPE=NOTARGET

TARGETPATH=

SOURCES=

NTTARGETFILES=MyOldBuild

MISCFILES=<List of images the existing build will generate>

======== makefile.inc ========

MyOldBuild:

    nmake <existing make command line>

Another option is to create a makefil0. It has the added advantage in that the build utility will execute the all rule for a regular build and the clean rule when the -c switch is used.  Here's an example:

======== dirs =========

DIRS= Win32Dir1 Win32Dir2 Win32Dir3

======== makefil0 ========

all:

    nmake <existing make command line>

clean:

   nmake <command to perform a clean build>


Answer #4

1. Generate a full build of the project with your existing build.  Make sure you can find all the switches passed to the compiler, include paths, linker options, resource compiler usage, extra utilities you use, directory processing order, etc.  Most builds try to hide all of this, but it's important for this purpose.

2. Take a look at the extra tools you use.  If they aren't available for all platforms (X86, Mips, Alpha, PPC, etc.), find the source code and start building it first.  If you can't get the tools for all platforms, don't waste your time converting more code.

3. Look over the output from Step1.  Many non-trivial builds will have common code.  Build library(s) with this code.  If you want to do dual builds while you're converting, your existing makefiles can have a wrapper added.  Here's an example:

======= Existing makefile =========

!ifdef NTMAKEENV

!include $(NTMAKEENV)\makefile.def

!else

# The current makefile go here

!endif

Now by defining NTMAKEENV, the subdir will use the build utility.  Otherwise, your existing build will still work.

4. Build the core DLLs next.  This will also generate import libraries.

5. Build the .exes and ancillary DLLs next.  These will probably use the common libraries you built in Step 3 and the import libraries from Step 4.

6. Add dirs files as needed to these together.  By using DIRS for projects you're sure build and OPTIONAL_DIRS to projects that you're converting, you can keep the build working for other users at the same time.  Try to list the directories that build libraries and DLL's first as it reduces the chance you'll need Multiprocessor synchronization.

7. Make sure you have someone else build on an alternate platform just to make sure you didn't introduce a platform dependency. Continue working until done.


Answer #5

The debugging information is controlled with the NTDEBUGTYPE environment variable which you set before you build the project. Usually, windbg or both is appropriate. All builds have debug symbolic information which is later stripped out into a .dbg file with the Binplace Utility as part of the build. If you want to generate PDBs for the Codeview information, set USE_PDB=1 in the sources file or in the environment when you build.


Answer #6

Think of them as Retail and Debug except the ONLY difference is whether DBG is defined or not. Checked defines DBG, Free doesn't. Optimizations are enabled all the time. You're welcome to change these based on the FREEBUILD setting in your sources file.  For instance:

====== sources file ========

...

!if !$(FREEBUILD)

C_DEFINES = $(C_DEFINES) /D_DEBUG

MSC_OPTIMIZATION=-Odi

!else

C_DEFINES = $(C_DEFINES) /DNDEBUG

!endif

...

The Free/Check setting is controlled by the NTDEBUG environment variable.  Set it to ntsd for a checked build, ntsdnodbg for a free build.

Note:  on the NTDEBUG page, all the blue text can be removed.  Also the last sentence ("Some groups, such as the VC group, define _DEBUG... version") can be deleted also.  A comment should be added that:

It is rarely used in the sources file, instead it should be set in the environment before building the project.


Answer #8
Answer

All directories still contain a makefile, but it just includes the standard makefile.def file. This makefile should not be edited. Instead look in the corresponding sources and makefile.inc files when you need to make local changes to how a component builds, or the sources.inc and makefile.inc files in directories above your component to make more global changes. When adding a new component, it will need at least a sources and the standard makefile, and may need a makefile.inc as well.


Answer #9
Answer

The .def files that need preprocessing have been renamed as .src files so the preprocessing happens automatically.


Answer #10
Answer

No. You can give directions to build on the command line, or in the environment variable BUILD_OPTIONS. So with the following dirs file:

DIRS=dir1

OPTIONAL_DIRS=dir2

build

-or-

build ~dir2

  builds dir1

build dir2

  builds dir1 and dir2

build dir2 ~dir1

  builds dir2 only

Or you can set BUILD_OPTIONS=dir2 ~dir1.


Answer #13
Answer

If you use the -e flag, you get BUILD.LOG, BUILD.ERR and BUILD.WRN in the directory in which you invoked build.exe.


Answer #14
Answer

Set BROWSER_INFO=1.


Answer #15
Answer

Yes. For more information, see Building Multiple Targets from One Subdirectory.


Answer #16
Answer

This may be more problematic than it's worth because you then get into issues where if the precompiled header changes, you've got to rebuild five subdirectories instead of just one. If you really want to do this, read makefile.def or send email to Bryan Tuttle to answer questions about how to do it.


Answer #17
Answer

No. You do not need to follow the same directory structure as Windows NT in which source code is in project directories under $(BASEDIR)\private and shared libraries and headers are under $(BASEDIR)\public. You can specify the following macros in your sources file. These macros enable you to eliminate the reliance on public:

BINPLACE_PLACEFILE
COFFBASE_TXT_FILE
COMPILER_WARNINGS
CRT_INC_PATH

CRT_LIB_PATH

MASTER_VERSION_FILE
MFC_INC_PATH
MFC_LIB_PATH
OAK_INC_PATH
SDK_INC_PATH

SDK_LIB_PATH


makefile0

This is a makefile you write that exists in the same subdirectory as a dirs file.  It is typically used to build header files needed in the subdirectories. The Build utility will spawn nmake to execute this file before traversing the directory list in the dirs file.