MAKE Directives

From RAD Studio
Jump to: navigation, search

Go Up to MAKE.EXE


MAKE directives resemble directives in languages such as C and Pascal. In MAKE, directives perform various control functions, such as displaying commands onscreen before executing them. MAKE directives begin either with an exclamation point or a period, and they override any options given on the command line. Directives that begin with an exclamation point must appear at the start of a new line.

MAKE Directives and Their Command-Line Options

The following table lists the MAKE directives and their corresponding command-line options:

Directive Option (if available) Description/Example

.autodepend

-a

Turns on autodependency checking. Autodependencies are the files that are automatically included in the targets you build, such as the header files included in your C++ source code. With .autodepend on, MAKE compares the dates and times of all the files used to build .OBJ, including the autodependency files. If the dates or times of the files used to build .OBJ are newer than the date/time stamp of the .OBJ file, the .OBJ file is recompiled. You can use .autodepend (or -a) in place of forming linked dependencies.

.cacheautodepend

-c

Turns on autodependency caching.

!cmdswitches

Uses + or - followed by nonstring option letters to turn each option on or off. Spaces or tabs must appear before the + or - operator; none can appear between the operator and the option letters.

!elif

Acts like a C else if.

!else

Acts like a C else.

!endif

Ends an !if, !ifdef, or !ifndef statement.

!error

Stops MAKE and prints an error message. The syntax of the !error directive is:

!error <message>

MAKE stops processing and prints the following string when it encounters this directive: Fatal makefile exit code: Error directive - <message>

Embed !error in conditional statements to abort processing and print an error message, as shown in the following example:

!if !$d(MYMACRO) #if MYMACRO isn't defined
!error MYMACRO isn't defined 
! endif

If MYMACRO is not defined, MAKE terminates and prints:

Fatal makefile 4: Error directive - MYMACRO isn't defined

Error-Checking Controls MAKE offers four different error-checking controls:

  • The .ignore directive turns off error checking for a selected portion of the makefile.
  • The -i command-line option turns off error checking for the entire makefile.
  • The -num prefix, which is entered as part of a rule, turns off error checking for the related command if the exit code exceeds the specified number.
  • The - prefix turns off error checking for the related command regardless of the exit code.

!if

Begins a conditional statement.

!ifdef

Acts like a C #ifdef, testing whether a given macro has been defined.

!ifndef

Acts like a C #ifndef, testing whether a given macro is undefined.

.ignore

-i

MAKE ignores the return value of a command.

!include

This directive is like the #include preprocessor directive for the C or C++ language -- it lets you include the text of another file in the makefile:

!include <filename>

You can enclose the file name in quotation marks " " or angle brackets < > and nest directives to unlimited depth.

However, writing duplicate !include directives in a makefile is not permitted -- you will get the error message cycle in the include file.

Rules, commands, or directives must be complete within a single source file; you cannot start a command in an !include file, then finish it in the makefile. MAKE searches for !include files in the current directory unless you have specified another directory with the -I command-line option.

.keep

-K

Keeps temporary files that MAKE creates (MAKE usually deletes them.)

!message

Prints a message to stdout while MAKE runs the makefile.

The !message directive lets you send messages to the screen from a makefile. You can use these messages to help debug a makefile that is not working properly. 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: $(MacroName)

When MAKE interprets this line, it will print onscreen (assuming the macro expands to .CPP):

The macro is defined here as: .CPP

.noautodepend

-a-

Turns off autodependency checking.

.nocacheautodepend

-c-

Turns off autodependency caching.

.noIgnore

-i-

Turns off .Ignore.

.nokeep

-K-

Does not keep temporary files that MAKE creates.

.nosilent

-s-

Displays commands before MAKE executes them.

.noswap

-S-

Tells MAKE not to swap iteself out of memory before executing a command.

.path.ext

Tells MAKE to search for files with the extension .ext in path directories.

To tell 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

Saves the targets even if the build fails.

If a MAKE build fails, MAKE deletes the target file. The .precious directive prevents the file deletion, which you might want for certain kinds of targets. For example, if your build fails to add a module to a library, you might not want the library to be deleted. The syntax for .precious is:

.precious: <target> [<target>...]

.silent

-s

MAKE executes commands without printing them first.

.suffixes

Determines the implicit rule for ambiguous dependencies. The .suffixes directive tells MAKE the order (by file extensions) for building implicit rules. The syntax of .suffixes is:

.suffixes: .<ext> [.<ext> ...]

where .<ext> represents the dependent file extensions you list in your 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 .suffixes example tells MAKE to look for a source file 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 ILINK32; otherwise, MAKE searches for MYPROG.C to build the .OBJ file or it searches for MYPROG.CPP.

.suffixes: .asm .c .cpp 
myprog.exe: myprog.obj
bcc32 myprog.obj
.cpp.obj: 
bcc32 -P -c $<
.asm.obj: 
tasm /mx $
.c.obj:
bcc32 -P- -c $<

.swap

-S

Tells MAKE to swap itself out of memory before executing a command.

!undef

Clears the definition of a macro. After this, the macro is undefined. The !undef (undefine) directive causes an !ifdef MacroName test to fail.

The syntax of the !undef directive is: !undef MacroName


Using Macros in Directives

You can use the $d macro with the !if conditional directive to perform some processing if a specific macro is defined. Follow $d with a macro name enclosed in parentheses or braces, as shown in the following example:

!if $d(DEBUG)            #If DEBUG is defined,
bcc32 -v f1.cpp f2.cpp   #compile with debug information;
!else                    #otherwise
bcc32 -v- f1.cpp f2.cpp   #don't include debug information.
!endif

Null Macros

While an undefined macro name causes an !ifdef MacroName test to return false, MacroName defined as null will return true. You define a null macro by following the equal sign = in the macro definition with either spaces or a return character. For example, the following line defines a null macro in a makefile:

NULLMACRO =

Either of the following lines can define a null macro on the MAKE command line:

NULLMACRO =""
-DNULLMACRO

!if and Other Conditional Directives

The !if directive works like C if statements. As shown here, the syntax of !if and the other conditional directives resembles compiler conditionals:

!if condition

!if condition

!if condition

!ifdef macro

!endif

!else

!elif condition

!endif

!endif

!endif


The following expressions are equivalent:

!ifdef macro /* is equivalent to */ !if $d(macro)
ifndef macro /* is equivalent to */ !if !$d(macro) 

These rules apply to conditional directives:

  • One !else directive is allowed between !if, !ifdef, or !ifndef and !endif.
  • Multiple !elif directives are allowed between !if, !ifdef, or !ifndef, !else and !endif.
  • You cannot split rules across conditional directives.
  • You can nest conditional directives.
  • !if, !ifdef, and !ifndef must have matching !endif directives within the same file.

The following information can be included between the !if and !endif directives:

  • Macro definition
  • Explicit rule
  • Implicit rule
  • Include directive
  •  !error directive
  •  !undef directive

In an if statement, a conditional expression consists of decimal, octal, or hexadecimal constants and the operators shown in the following table:

Operator Description Operator Description

-

Negation

?:

Conditional expression

~

Bit complement

!

Logical NOT

+

Addition

>>

Right shift

-

Subtraction

<<

Left shift

*

Multiplication

&

Bitwise AND

/

Division

|

Bitwise OR

%

Remainder

^

Bitwise XOR

&&

Logical AND

>+

Greater than or equal to *

||

Logical OR

<+

Less than or equal to *

>

Greater than

==

Equality *

<

Less than

!=

Inequality *

The operators marked with the * sign also work with string expressions.

MAKE evaluates a conditional expression as either a 32-bit signed integer or a character string.

See Also