MAKE Help This file contains details on using MAK. -------------------------------------------------------------------- TABLE OF CONTENTS - - - - - - - - - MAKE basics BUILTINS.MAK Using TOUCH.EXE MAKE options Setting options on as defaults Compatibility with Microsoft's NMAKE Using makefiles Symbolic targets Rules for symbolic targets Explicit and implicit rules Explicit rule syntax Single targets with multiple rules Implicit rule syntax Explicit rules with implicit commands Commands syntax Command prefixes Using @ Using -num and - Using & Command operators Debugging with temporary files Using MAKE macros Defining macros Using a macro String substitutions in macros Default MAKE macros Modifying default macros Using MAKE directives .autodepend !error Summing up error-checking controls !if and other conditional directives !include !message .path.ext .precious .suffixes !undef Using macros in directives -------------------------------------------------------------------- MAKE.EXE is a command-line project-manager utility that helps you quickly compile only those files in a project that have changed since the last compilation. (MAKER is a real-mode version of MAKE.) This chapter covers the following topics: o MAKE basics o Makefile contents o Using explicit and implicit rules o Using MAKE macros o Using MAKE directives MAKE basics =========== MAKE uses rules from a text file (MAKEFILE or MAKEFILE.MAK by default) to determine which files to build and how to build them. For example, you can get MAKE to compile an .EXE file if the date-time stamps for the .CPP files that contain the code for the .EXE are more recent than the .EXE itself. MAKE is very useful when you build a program from more than one file because MAKE will recompile only the files that you modified since the last compile. Two types of rules (explicit and implicit) tell MAKE what files depend on each other. MAKE then compares the date-time stamp of the files in a rule and determines if it should execute a command (the commands usually tell MAKE which files to recompile or link, but the commands can be nearly any operating system command). The general syntax for MAKE is: MAKE [options...] [targets[s]] (To get command-line help for MAKE, type MAKE -? or MAKE -h.) "Options" are MAKE options that control how MAKE works, and "targets" are the names of the files in a makefile that you want MAKE to build. Options are separated from MAKE by a single space. Options and targets are also separated by spaces. If you type MAKE at the command prompt, MAKE performs the following default tasks: To place MAKE instructions in a file other than MAKEFILE, see the section titled "MAKE options." MAKE looks in the current directory for a file called BUILTINS.MAK (this file contains rules MAKE always follows unless you use the -r option). If it can't find the file in the current directory, it looks in the directory where MAKE.EXE is stored. After loading BUILTINS.MAK, MAKE looks for a file called MAKEFILE or MAKEFILE.MAK. If MAKE can't find any of these files, it gives you an error message. When MAKE finds a makefile, it tries to build only the first target file in the makefile (although the first target can force other targets to be built). MAKE checks the time and date of the dependent files for the first target. If the dependent files are more recent than the target file, MAKE executes the target commands, which update the target. See the section called "Using makefiles" for more information on instructions in makefiles. 1) If a dependent file for the first target appears as a target elsewhere in the makefile, MAKE checks its dependencies and builds it before building the first target. This chain reaction is called linked dependency. 2) If the MAKE build process fails, MAKE deletes the target file it was building. To get MAKE to keep a target when a build fails, see the .precious directive. You can stop MAKE by using or . BUILTINS.MAK ------------ BUILTINS.MAK contains standard rules and macros that MAKE uses before it uses a makefile (you can use the -r option to tell MAKE to ignore BUILTINS.MAK). Use BUILTINS.MAK for instructions or macros you want executed each time you use MAKE. Here's the default text of BUILTINS.MAK: # # Borland C++ - (C) Copyright 1993 by Borland International # # default is to target 32BIT # pass -DWIN16 to make to target 16BIT !if !$d(WIN16) CC = bcc32 RC = brcc32 AS = tasm32 !else CC = bcc RC = brcc AS = tasm !endif .asm.obj: $(AS) $(AFLAGS) $&.asm .c.exe: $(CC) $(CFLAGS) $&.c .c.obj: $(CC) $(CFLAGS) /c $&.c .cpp.exe: $(CC) $(CFLAGS) $&.cpp .cpp.obj: $(CC) $(CPPFLAGS) /c $&.cpp .rc.res: $(RC) $(RFLAGS) /r $& .SUFFIXES: .exe .obj .asm .c .res .rc !if !$d(BCEXAMPLEDIR) BCEXAMPLEDIR = $(MAKEDIR)\..\EXAMPLES !endif Using TOUCH.EXE --------------- Sometimes you'll want to force a target file to be recompiled or rebuilt even though you haven't changed it. One way to do this is to use the TOUCH utility. TOUCH changes the date and time of one or more files to the current date and time, making it "newer" than the files that depend on it. You can force MAKE to rebuild a target file by touching one of the files that target depends on. To touch a file (or files), type the following at the command prompt: touch filename [filename...] TOUCH updates the file's creation date and time. Before you use TOUCH, make sure your system's internal clock is set correctly. If it isn't, TOUCH and MAKE won't work properly. MAKE options ------------ Command-line options control MAKE behavior. Options are case-sensitive. Type options with either a preceding - or /. For example, to use a file called PROJECTA.MAK as the makefile, type MAKE -fPROJECTA.MAK (a space after -f is optional). Many of the command-line options have equivalent directives that are used in the makefile. The following table describes MAKE's command-line options. Option Description ------ ----------- -h or -? Displays MAKE options and shows defaults with a trailing plus sign. -B Builds all targets regardless of file dates. -D Defines as a single character, causing an expression written in the makefile to return true. [-D]=[string] Defines as "string." If "string" contains any spaces or tabs, enclose "string" in quotation marks. The -D is optional. -I Searches for include files in the current directory first, then in . -K Keeps temporary files that MAKE creates (MAKE usually deletes them). -N Executes MAKE like Microsoft's NMAKE (see the section following this table for more information). -U Undefines previous definitions of . -W Writes the current specified non-string options to MAKE.EXE making them defaults. -f Uses or .MAK instead of MAKEFILE (space after -f is optional). -a Checks dependencies of include files and nested include files associated with .OBJ files and updates the .OBJ if the .H file changed. See also -c. -c Caches autodependency information, which can improve MAKE's speed. Use with -a; don't use if MAKE changes include files (such as using TOUCH from a makefile or creating header or include files during the MAKE process). -d Used with -S to specify the drive and directory MAKE uses when it swaps out of memory. The option is ineffective when used with the MAKER. -e Ignores a macro if its name is the same as an environment variable (MAKE uses the environment variable instead of the macro). -i Ignores the exit status of all programs run from MAKE and continues the build process. -m Displays the date and time stamp of each file as MAKE processes it. -n Prints the commands but doesn't actually perform them, which is helpful for debugging a makefile. -p Displays all macro definitions and implicit rules before executing the makefile. -q Returns 0 if the target is up-to-date and nonzero if is is not (for use with batch files). -r Ignores any rules defined in BUILTINS.MAK. -s Suppresses onscreen command display. -S Swaps MAKER out of memory while commands are executed, reducing memory overhead and allowing compilation of large modules. This option has no effect on MAKER. -W Sets MAKE defaults. Setting options on as defaults - - - - - - - - - - - - - - - - The -W option lets you set some MAKE options on as defaults so that each time you use MAKE, those options are used. To set MAKE options, type: make -option[-] [-option][-] . . . -W For example, you could type "MAKE -m -W" to always view file dates and times. Type "MAKE -m- -W" to turn off the default option. When MAKE asks you to write changes to MAKE.EXE, type Y. The -W option doesn't work when the DOS Share program is running. The message "Fatal: unable to open file MAKE.EXE" is displayed. The -W option doesn't work with the following MAKE options: o -D o -D= o -d o -U o -f o -? or -h o -I Compatibility with Microsoft's NMAKE - - - - - - - - - - - - - - - - - - - Use the -N option if you want to use makefiles that were originally created for Microsoft's NMAKE. The following changes occur when you use -N: MAKE interprets the << operator like the && operator: temporary files are used as response files, then deleted. To keep a file, either use the -K command-line option or use KEEP in the makefile. < Stop processing commands in the makefile when the exit code returned from command exceeds . Normally, MAKE aborts if the exit code is nonzero. No white space is allowed between - and . - Continue processing commands in the makefile, regardless of the exit code returned by them. & Expand either the macro $**, which represents all dependent files, or the macro $?, which represents all dependent files stamped later than the target. Execute the command once for each dependent file in the expanded macro. Using @ - - - - The following command uses the modifier @, which prevents the command from displaying onscreen when MAKE executes it. diff.exe : diff.obj @bcc diff.obj Using -num and - - - - - - - - - - The "-num" and "-" modifiers control MAKE processing under error conditions. You can choose to continue with the MAKE process if an error occurs or only if the errors exceed a given number. In the following example, MAKE continues processing if BCC isn't run successfully: target.exe : target.obj target.obj : target.cpp bcc -c target.cpp Using & - - - - The & modifier issues a command once for each dependent file. It is especially useful for commands that don't take a list of files as parameters. For example, copyall : file1.cpp file2.cpp © $** c:\temp results in COPY being invoked twice as follows: copy file1.cpp c:\temp copy file2.cpp c:\temp Without the & modifier, COPY would be called only once. Command operators - - - - - - - - - You can use any operating system command in a MAKE commands section. MAKE uses the normal operators (such as +, -, and so on), but it also has other operators you can use. Operator Description -------- ----------- < Take the input for use by "command" from "file" rather than from standard input. > Send the output from "command" to "file". >> Append the output from "command" to "file". << Create a temporary, inline file and use its contents as standard input to "command". && Create a temporary file and insert its name in the makefile. delimiter Any character other than # and \ used with << and && as a starting and ending delimiter for a temporary file. Any characters on the same line and immediately following the starting delimiter are ignored. The closing "delimiter" must be written on a line by itself. Debugging with temporary files - - - - - - - - - - - - - - - - Temporary files can help you debug a command set by placing the actual commands MAKE executes into the temporary file. Temporary file names start at MAKE0000.@@@, where the 0000 increments for each temporary file you keep. You must place delimiters after && and at the end of what you want sent to the temporary file (! is a good delimiter). The following example shows && instructing MAKE to create a file of the input to TLINK. prog.exe: A.obj B.obj TLINK /c &&! c0s.obj $** prog.exe prog.map maths.lib cs.lib ! The response file created by && contains these instructions: c0s.obj a.obj b.obj prog.exe prog.map maths.lib cs.lib Using MAKE macros ================= A MAKE macro is a string that is expanded (used) wherever the macro is called in a makefile. Macros let you create template makefiles that you can change to suit different projects. For example, to define a macro called LIBNAME that represents the string "mylib.lib," type "LIBNAME = mylib.lib". When MAKE encounters the macro "$(LIBNAME)", it uses the string "mylib.lib". If MAKE finds an undefined macro in a makefile, it looks for an operating-system environment variable of that name (usually defined with SET) and uses its definition as the expansion text. For example, if you wrote "$(path)" in a makefile and never defined "path", MAKE would use the text you defined for PATH in your AUTOEXEC.BAT. (See the manuals for your operating system for information on defining environment variables.) Defining macros --------------- The general syntax for defining a macro in a makefile is: MacroName = expansion_text o "MacroName" is case-sensitive and is limited to 512 characters. o "expansion_text" is limited to 4096 characters consisting of alpha-numeric characters, punc-tuation, and white space. Each macro must be on a separate line in a makefile. Macros are usually put at the top of the makefile. If MAKE finds more than one definition for a "macroName", the new definition replaces the old one. Macros can also be defined using the command-line option -D. More than one macro can be defined by separating them with spaces. The following examples show macros defined at the command line: make -Dsourcedir=c:\projecta make command="bcc -c" make command=bcc option=-c The following differences in syntax exist between macros entered on the command line and macros written in a makefile. Makefile Command line -------- ------------ Spaces allowed before and after = Yes No Space allowed before macroName No Yes Using a macro ------------- To use a macro in a makefile, type "$(MacroName)" where MacroName is the name of a defined macro. You can use braces {} and parentheses () to MAKE expands macros at various times depending on where they appear in the makefile: o Nested macros are expanded when the outer macro is invoked. o Macros in rules and directives are expanded when MAKE first looks at the makefile. o Macros in commands are expanded when the command is executed. String substitutions in macros ------------------------------ MAKE lets you temporarily substitute characters in a previously defined macro. For example, if you defined a macro called SOURCE as "SOURCE = f1.cpp f2.cpp f3.cpp", you could substitute the characters .OBJ for the characters .CPP by using "$(SOURCE:.CPP=.OBJ)". The substitution doesn't redefine the macro. Rules for macro substitution: o Syntax: $(MacroName:original_text=new_text) o No whitespace before or after the colon. o Characters in "original_text" must exactly match the characters in the macro definition; this text is case-sensitive. MAKE now lets you use macros within substitution macros. For example: MYEXT=.C SOURCE=f1.cpp f2.cpp f3.cpp $(SOURCE:.cpp=$(MYEXT)) #Changes f1.cpp to f1.C, etc. Default MAKE macros ------------------- MAKE contains several default macros you can use in your makefiles. The following table lists the macro definition and what it expands to in explicit and implicit rules. Macro Expands in implicit: Expands in explicit: Example ----- -------------------- -------------------- ------- $* path\dependent file path\target file C:\PROJ\MYTARGET $< path\dependent file+ext path\target file+ext C:\PROJ\MYTARGET.OBJ $: path for dependents path for target C:\PROJ $. dependent file+ext target file + ext MYSOURCE.C $& dependent file target file MYSOURCE $@ path\target file+ext path\target file+ext C:\PROJ\MYSOURCE.C $** path\dependent file+ext all dependents file+ext F1.CPP F2.CPP F3.CPP $? path\dependent file+ext old dependents FILE1.CPP Macro Expands to: Comment ----- ----------- ------- __MSDOS__ 1 If running under DOS. __MAKE__ 0x0370 MAKE's hex version number. MAKE make MAKE's executable file name. MAKEFLAGS options The options typed at the command line. MAKEDIR directory Directory where MAKE.EXE is located. Modifying default macros ------------------------ When the default macros listed in the preceding table doesn't give you the exact string you want, macro modifiers let you extract parts of the string to suit your purpose. To modify a default macro, use this syntax: $(MacroName [modifier]) The following table lists macro modifiers and provides examples of their use. Modifier Part of file name expanded Example Result -------- -------------------------- -------------- D Drive and directory $( You can enclose in quotation marks ("") or angle brackets (<>) and nest directives to unlimited depth, but writing duplicate !include directives in a makefile isn't permitted--you'll get the error message "cycle in the include file". Rules, commands, or directives must be complete within a single source file; you can't start a command in an !include file, then finish it in the makefile. MAKE searches for !include files in the current directory unless you've specified another directory with the -I option. !message -------- The !message directive lets you send messages to the screen from a makefile. You can use these messages to help debug a makefile that isn't working the way you'd like it to. For example, if you're having trouble with a macro definition, you could put this line in your makefile: !message The macro is defined here as: $() When MAKE interprets this line, it will print onscreen "The macro is defined here as: .CPP", if the macro expands to .CPP at that line. Using a series of !message directives, you can debug your makefiles. .path.ext --------- The .path.ext directive tells MAKE where to look for files with a certain extension. The following example tells MAKE to look for files with the .c extension in C:\SOURCE or C:\CFILES and to look for files with the .obj extension in C:\OBJS. .path.c = C:\CSOURCE;C:\CFILES .path.obj = C:\OBJS .precious --------- If a MAKE build fails, MAKE deletes the target file. The .precious directive prevents the file deletion, which is desired for certain kinds of targets such as libraries. When a build fails to add a module to a library, you don't want the library to be deleted. The syntax for .precious is: .precious: target [target] . . . [target] .suffixes --------- The .suffixes directive tells MAKE the order (by file extensions) for building implicit rules. The syntax of the .suffixes directive is: .suffixes: .ext [.ext] [.ext] . . . [.ext] .ext represents the dependent file extension in implicit rules. For example, you could include the line ".suffixes: .asm .c .cpp" to tell MAKE to interpret implicit rules beginning with the ones dependent on .ASM files, then .C files, then .CPP files, regardless of what order they appear in the makefile. The following example shows a makefile containing a .suffixes directive that tells MAKE to look for a source file (MYPROG.EXE) first with an .ASM extension, next with a .C extension, and finally with a .CPP extension. If MAKE finds MYPROG.ASM, it builds MYPROG.OBJ from the assembler file by calling TASM. MAKE then calls TLINK; otherwise, MAKE searches for MYPROG.C to build the .OBJ file, and so on. .suffixes: .asm .c .cpp myprog.exe: myprog.obj tlink myprog.obj .cpp.obj: bcc -P $< .asm.obj: tasm /mx $< .c.obj: bcc -P- $< !undef ------ The syntax of the !undef directive is: !undef MacroName !undef (undefine) clears the given macro, MacroName, causing an !ifdef MacroName test to fail. Using macros in directives -------------------------- The macro $d is used with the !if conditional directive to perform some processing if a specific macro is defined. The $d is followed by a macro name, enclosed in parentheses or braces, as shown in the following example. !if $d(DEBUG) #If DEBUG is defined, bcc -v f1.cpp f2.cpp #compile with debug information; !else #otherwise (else) bcc -v- f1.cpp f2.cpp #don't include debug information. !endif Don't use the $d macro when MAKE is invoked with the -N option. /**************************** END OF FILE ********************************/