|
Compiling Compiling Code C Implementation C++ Implementation Language Extensions Mixing Languages Assembly Language Inline Assembler Optimizing Code Numerics Programming Regular Expressions Acrtused Pragmas Precompiled Headers Predefined Macros Warning Messages Error Messages Runtime Messages Linking Optlink Switches Module Definition Files Operation and Design Error Messages Win32 Programming Win32 Programming DOS and Win16 Programming Memory Models 16 Bit Pointer Types and Type Modifiers Handle Pointers DOS DOS 32 (DOSX) Win16 Win16 DLLs Win16 Prolog/Epilog C/C++ Extensions Contract Programming __debug statement __debug declaration Dynamic Profiling Embedding C in HTML Tools BCC CHMOD CL COFF2OMF COFFIMPLIB DMC DIFF DIFFDIR DUMP DUMPOBJ DUMPEXE EXE2BIN FLPYIMG GREP HC IMPLIB LIB LIBUNRES MAKE MAKEDEP ME OBJ2ASM PATCHOBJ RC RCC SC SHELL SMAKE TOUCH UNMANGLE WHEREIS Porting to DMC++ Switching to DMC++ from Microsoft from Borland Porting Guide |
Managing Code with smakeDigital Mars smake is a command processor for maintaining and updating project files. smake is compatible with Microsoft NMAKE. This chapter describes how smake builds a new version of a program by compiling only the files that have changed. For information on Digital Mars C++'s build system and source control system, see the User's Guide and Reference.This chapter discusses:
What is smake?smake automates program maintenance, instead of typing in commands to compile and link your program. A makefile describes how all the files in a project depend on each other and how to update a file (such as an object file) when the files it depends on (such as source files) change.smake is particularly useful for programs that have many source files, since it recompiles only those source files that have changed. It does this by looking at the date and time stamp of each relevant file before performing any tasks. Note: When using smake, always be sure your PC displays the correct date and time. Be especially careful when logging on to networks that change the time on the local machine, in case the network time is incorrect. smake differs from a batch file in that it performs only the commands required to rebuild your program, while a batch file executes all tasks, whether or not they are necessary. Writing MakefilesA makefile is a text file that tells smake how to build your program. By default, smake expects the makefile to be named makefile, with no extension. Any extension can be used, though .mak is commonly used.The makefile contains one or more dependence lines, each followed by one or more command lines. Each dependence line specifies a target (upon which the associated command lines act), followed by a colon and a (possibly empty) list of dependent files (files needed to create the target). For example, this dependence line: app.exe : app.obj app.re app.deftells smake to perform the commands that follow if any of app.obj, app.res, or app.def have a more recent date and time than app.exe. Command lines tell smake how to create the target. Command lines must begin with a tab or space character. For example: app.exe : app.obj app.res app.def link app,,NULL,lib,app rcc app.res app.exetells smake to run the linker and the resource compiler. A makefile can also contain comments, macros, preprocessing directives, operating system commands, and inference rules. Example of a simple makefileThis makefile creates a program that has only one source file.hello.exe: hello.obj # Dependence line 1 link hello.obj # Command line 1 hello.obj: hello.cpp # Dependence line 2 dmc -c hello.cpp # Command line 2Note: A makefile comment begins with the # character and continues until the end of the line. The first dependence line indicates that hello.exe depends on hello.obj. The first command line specifies how to make hello.exe by executing link hello.obj. The second dependence line indicates that hello.obj depends on hello.cpp. The second command line specifies how to make hello.obj by executing dmc -c hello.cpp. Suppose you just finished editing hello.cpp and typed smake to create a new version of your program. smake reads the dependence lines from the makefile. It determines that hello.cpp is newer than hello.obj, so it re-creates hello.obj by executing dmc -c hello.cpp. Then it determines that hello.obj is now newer than hello.exe. It re-creates hello.exe by executing link hello.obj. Makefile syntaxThe syntax for a basic makefile is:target-file : dependent-file1 dependent-file2 ... command 1 command 2 ...smake assumes that if a target file is older than any of the files needed to create it, then it must re-create the target file by executing the command lines that follow the dependence line. Target files are typically executable files or libraries, but they can also be labels for sets of commands (like all:); these are often called pseudo-targets. Similarly, a dependent file is usually a C or C++ source file, but can be a pseudo-target. For more information see "Specifying targets" below. Note: smake reads all the dependence lines in a makefile before executing any of the associated commands. It then compares the date and time of the dependents to the target and executes the commands for any target that is out of date. It also checks to see if that target has other dependents that might be more recent. Dependence line syntaxThe name of the target file must be the first thing on the dependence line, with no white space preceding it. The target and subsequent dependents are separated by a single colon, which can optionally be preceded by tabs or spaces. A dependence line can span multiple lines; all lines to be continued must end with a backslash (\) character.Specifying targetsThe dependence line can contain one or more target names separated by one or more spaces. Each target can be a fully qualified path and file name, or just a label. However, if the last target has a single character name (with no extension), at least one space is required before the colon to distinguish it from a drive letter.To build a complicated target that requires more than one set of dependence lines and commands, use double colons (::) to separate it from the dependents in each case. For example: app.exe :: app.obj app.def link app,,NULL,lib,app app.exe :: app.res rc app.res app.exeIf the same target, followed by a single colon, appears on two consecutive lines, and commands follow only one of those instances, smake interprets this as a single, cumulatively combined dependence line. For example: target.exe : file_1.obj target.exe : file_2.obj # is interpreted as # target.exe : file_1.obj file_2.objIf the same target, followed by a single colon, appears on two different lines in various places in the makefile, and commands follow only one of those instances, smake interprets this as if the dependence lines were adjacent. This means that smake does not apply an inference rule to the instance without commands. Use double colons (::) after the target to avoid this side effect. If a target is not specified on the smake command line, smake uses the first target it encounters in the makefile. smake always interprets a label used as a target name as being out of date; this is useful to avoid having to pass several targets on the command line. For example: all: app.exe app2.exe app3.exe Specifying dependent filesThe names of zero or more dependents can follow the target on the dependence line. As with targets, a dependent can be a fully qualified path name or a label, although it is usually a file that is used to build the target. Multiple dependents must be separated by one or more spaces or tabs.A search path can precede a dependent file; enclose the path in curly braces ({}) and separate the directories with semicolons (;). smake will search the specified directories in order for the dependent. (The search path applies only to the dependent it proceeds.) For example:
app.exe : app.obj app.res \
{c:\project; c:\default} app.def
Special characters in makefilessmake accepts the special characters listed below in makefiles. These characters have special meaning depending on their context. For any of these characters to be interpreted literally in a makefile, you must precede it with a caret (^) character. If ^ appears in front of a character that does not have special meaning to smake, it is interpreted literally.Note: A ^ at the end of a line includes the carriage return/line feed sequence in a macro or string. Table 13-1 Special characters in makefiles
Using % and $ in commandssmake interprets a percent sign (%) as the beginning of a file name specifier. To place a percent sign in a command, use two percent signs (%%). Similarly, to use a dollar ($) sign in a command, specify two consecutive dollar signs ($$). You can also specify multiple literal % and $ characters this way. For example, smake interprets $$$$ in a command as two consecutive dollar signs.Note: smake interprets the $ and @ symbols as special characters, do not use these symbols in file or directory names that will be processed by smake. Comments in makefilessmake interprets all characters following a # on a line as comment characters, and ignores them. Comments need not start at the beginning of a line; they can appear almost anywhere, including at the ends of lines defining macros, dependence lines, and inference rules. Comment are also permitted in command blocks, but cannot be on the same line as the command itself, even if the command spans multiple lines.Running smakeWhen you run smake (from an operating system command prompt), it prints your commands as it executes them. If you run smake and it doesn't need to update your files, it lets you know like this:Target is up to dateTo redirect the output of smake to a file, use the greater-than sign: smake > logNote: When smake calls another program, it redirects that program's output to the log file only if that program writes to stdout. The tools that come with Digital Mars C++, such as dmc and optlink, write to stdout. smake command line syntaxThe syntax for the smake command is:
smake {options} {macros} {targets}
where:
Command line optionssmake options are preceded by either a dash (-) or slash (/). Case is irrelevant when specifying options. If a required option is not specified, smake uses the default value for that option specified intools.ini. The following options are valid:
Specifying what targets to buildUsually smake creates the first target that it finds in your makefile. However, if you specify a target on the command line, smake creates that target instead. For example, this makefile creates several utility programs:all: count.exe write.exe read.exe count.exe: count.c dmc count.c write.exe: write.c dmc write.c read.exe: read.c dmc read.cTo create all the targets, don't specify a target on the command line. In the example above, smake encounters the target all first. Since the dependency list for all contains the executables for all the utilities, smake creates all the utilities. To create just some targets, specify them on the command line. For example, this command creates the programs write.exe and read.exe: smake write.exe read.exe makefileTo build a target only when you specify the target on the command line, make sure that target has no dependencies and is not the first target in the makefile. Such a target can delete files you no longer need or install software you just created. For example, suppose the makefile above ends with this target: clean: del *.objIf you type only smake, smake does not perform this target's command. But if you type smake clean, smake performs only this target's command and exits. Choosing Dependency FilesSince you use dependency files to create the target file, the names of the dependency files usually appear in the command lines that follow the dependence line. But if an object file depends on a source file and that source file includes a header file, the object file depends on that header file. If that header file changes, you must recompile the source file to create a new object file. It can be useful to include these kinds of files in dependency lists.Suppose that hello.cpp includes the file hello.h. The dependence line for hello.obj looks like this: hello.obj : hello.cpp hello.hIf a header file isn't likely to change, omit it from the dependency list. For example, system header files are unlikely to change. System header files include header files for standard libraries, such as stdio.h, and header files for operating system functions, such as windows.h. Dependencies can be automatically generated with MAKEDEP. Including filesTo textually include files in makefiles:!include filespecThe !include statement lets one makefile support several configurations of a program. Use SET commands to set environment variables for executed programs in the included file. Defining Macrossmake lets you define macros - identifiers that are replaced with text you specify. By combining the macros in a makefile with macros in tools. ini (see "Customizing smake Sessions with tools.ini" below), you can use a single makefile for multiple projects. Macros are useful for specifying compiler options, paths for targets, dependents, and inference rules.Define a macro by putting a line with the following syntax in the makefile, in tools.ini, or on the smake command line: macro=textmacro is a case sensitive combination of up to 1024 letters, digits, and underscore (_) characters. If a macro is to be used as a command, it cannot be null or undefined. The text can be any sequence of characters, including no characters, or white space (interpreted as a null string). It includes all the text between the equals sign and the end of the line. Note that a macro defined as a null string is not equivalent to an undefined macro; it is still defined in relation to directives like !IFDEF and !IFNDEF. To specify an instance of a macro that is to be expanded, enclose the macro name in parentheses and put a dollar sign in front of it, like this: If a macro name is only a single character, the parentheses are not required. Examples of when to use macrosMacros are especially useful for defining frequently repeated text. For example, if you need to make sure that all your source files are compiled with the same compiler options, define a macro that contains those options, like this:FLAGS=-c -g -DDEBUG=1 -ml file1.obj: file1.cpp file2.h dmc file1.cpp file2.obj: file2.cpp dmc file2.cppIf you need to refer frequently to the same directory path, put the path in a macro, like this: MYLIB=c:\dev\lib prog.exe: prog.obj \mylib.lib dmc prog.obj \mylib.lib Comments in macrosA hash character (#) on a line that defines a macro starts a comment. To use a # as part of a macro name, precede it with a caret (^). To continue a macro definition on another line, end the first line with a backslash (\). To specify a literal backslash at the end of a line, as for a directory name, precede the \ with a caret. To use a carriage return as part of a macro name, precede the carriage return with a ^; this also continues the macro on the next line.Specifying text to be substitutedSpecify text to be substituted when an instance of a macro is expanded by including a colon (:) followed by the string to be substituted for, an equal sign (=), and the string to substitute. For example:MODEL=L # defines macro # instance to be expanded # expands 'L' to 'S'The substitution applies only to the current instance, not to the original macro definition. Do not put white space characters before the colon; white space after the colon is interpreted as part of the string to be substituted. The text to be substituted is case sensitive. Overriding macros on the command lineOverride the macros defined in a makefile or tools.ini by specifying a new definition on the smake command line. For example, to override the definition of MYLIB in the example above, enter a command like this:smake MYLIB=c:\dev\test\libRefer to macros defined in the environment with the operating system command SET. For example, define temp with this command: set temp=c:\dosand refer to it like this: test.obj: test.cpp dmc -cod\test.cod test.cppIf you define a macro in more than one place, smake chooses definitions in this order of priority:
Recursively defined macrosOrdinarily, macros are defined only for the current smake session or iteration. The only macros that are defined recursively in calls to smake from within a makefile are:
Predefined macrossmake supports the following predefined macros, which you can use in your makefile:Macro Description
Modifiers for predefined macrosUse the following filename modifiers in combination with the predefined macros listed above:Table 13-5 Filename modifiers for use with predefined macros
For example, for the file c:\project\app.exe: $(@D) refers to c:\project $(@F) refers to app.exe $(@B) refers to app $(@R) refers to c:\project\app Predefined command and option macrostools.ini predefines macros that correspond to commands and command options. The option macros are undefined by default. Define these macros to expand to the commands and options to pass to the compiler and tools. (See tools.ini for a list of definitions.)Table 13-6 Predefined command and option macros
Macros for predefined environment variablesIn addition to the predefined macros listed above, every environment variable that is defined when smake starts up is equivalent to a predefined macro. This can cause unexpected results if the value of an environment variable used as a macro contains a $ character, because smake interprets $ as the beginning of a macro invocation.Macro precedenceThe order of precedence for macros in smake sessions is:
Using Operating System CommandsCommand lines that follow dependence lines, as well as inference rules, can contain any command that is valid on the command line. smake runs these commands when a target is out of date. Specify multiple commands by putting each command on its own line. If there are no commands following a dependence line, the dependency is checked against the inference rules.A command line must begin with one or more spaces or tabs, and must immediately follow the dependence line. No blank lines can separate them; however, a line containing only white space can be used to specify a null command. Blank lines can appear within a list of commands. Continue commands by ending the line to be continued with a backslash (\). If any characters, including spaces or tabs, follow the backslash, smake interprets them literally. Place single commands at the end of a dependence line by separating the dependency from the command with a semicolon (;). To let smake know how to execute a command line, precede a command with any of the following modifiers. More than one modifier can be used with a command: Table 13-7 Modifiers for smake commands Modifier Description - Tells smake to ignore the exit status from a command; processing continues no matter what value the command returns. Otherwise, smake stops executing if a command returns an error. -N Tells smake to halt execution only if the exit status a command returns is greater than the number N (even if .IGNORE or /I are not being used). Otherwise smake halts when a command returns a non-zero exit code. @ Tells smake not to display a command when it is executed, even if /S or .SILENT are not specified. Otherwise, smake displays commands as they are executed. ! Executes a command for each of the dependents in the dependency list. The command must use one of the file name macros $** or $?, or the ! prefix is ignored. $** causes the command to be executed for all of the dependent files. $? causes the command to be executed only for those dependent files which are more recent than the target. * Allows smake to accept long command lines. Causes all arguments to be assigned to the temporary variable $MAKE$, and all arguments to be replaced with @$MAKE$. <<file Specified after a command. If file is specified it must appear immediately after the angle brackets (<<), with no white space. If file is not specified, smake uses a unique filename. Tells smake to use inline files when processing a command. The file is created from the literal text beginning on the line immediately following the angle brackets. End the inline file by beginning a line with <<. Optionally, you can write one of the modifiers KEEP or NOKEEP immediately after the closing <<. NOKEEP (the default) tells smake to delete file at the end of the session. KEEP tells smake not to delete file at the end of the session (though file will be overwritten each time it is used).For example, in the makefile fragment below, smake continues even if the RM command returns an error, and smake executes the PROG command with command. com so you can use I/O redirection (with the greater than symbol > in this case): install: -rm \bin\progsmake always executes the commands in the table below by calling the operating system. The + modifier is not necessary with them. break cd chdir cls copy ctty date del dir echo erase exit if md mkdir pause rd rem rmdir ren rename time type verify volNote: smake handles del commands itself, unless they are followed by a file specification containing wildcard characters. This allows you to specify a command like: delwhere OBJS is a macro that expands to a list of file names. Preprocessing DirectivesPreprocessing directives are commands for smake. smake processes these directives before it processes dependency lines and commands. Preprocessing directives go in makefiles or in tools.ini.There are two types of preprocessing directives:
Table 13-8 ! preprocessing directives
Directive Description
!CMDSWITCHES{+/-} opt
Turns on or off one or more command line
options with the exception of /F, /HELP,
/NOLOGO, /X, or /?. In the makefile, only the
/D, /I, /N, and /S options are valid, though
tools.ini can contain the others.
!ELSE If the preceding !IF, !IFDEF or !IFNDEF
evaluated to zero, the statements between the
!ELSE and the next !ENDIF are processed. An
additional IF, IFDEF or IFNDEF can be
combined on the same line.
!ELSEIF Equivalent to the !ELSE IF directives.
!ELSEIFDEF Equivalent to the !ELSE IFDEF directives.
!ELSEIFNDEF Equivalent to the !ELSE IFNDEF directives.
!ENDIF Marks the end of a block beginning with an !IF,
!IFDEF, or !IFNDEF directive.
!ERROR text
Stops the smake session with a fatal error,
followed by the text. This directive will stop the
session even if other options, directives or
command modifiers, such as
/K, /I, .IGNORE, or -, are being used.
!IF expression
If the expression evaluates to other than zero, the
statements between the !IF and the next !ELSE
or !ENDIF are processed. See "Expressions in
preprocessing directives" below for information.
!IFDEF macro
If the macro is defined, even with a null value,
the statements between the !IFDEF and the next
!ELSE or !ENDIF are processed.
!IFNDEF macro
If the macro is not defined, the statements
between the !IFDEF and the next !ELSE or
!ENDIF are processed.
!INCLUDE <filename>
Reads and evaluates the filename and continues
the smake session. If angle brackets (<>) are
used, the directories in the INCLUDE macro is
searched to locate the filename. If angle brackets
are not used, the current directory or the
specified path is searched to locate the filename.
For compatibility with NMAKE and Digital Mars
MAKE, you can specify this directive without the
! prefix.
!MESSAGE text
Writes the text to the standard output and
continues the smake session.
!UNDEF macro
Removes the macro from the smake symbol
table.
smake supports these . preprocessing directives:
Table 13-9 . preprocessing directives Directives Description .IGNORE Directs smake to ignore exit codes from all the commands it processes from this point to the end of the file. You can also use !CMDSWITCHES+/I. See also /I, -, -number. .LONGCOMMANDLINE: tools Permits longer command lines. tools is a list of one or more executable program names, with no path or extension. Multiple occurrences of .LONGCOMMANDLINE are cumulative. If tools is not specified, the current list is cleared. Any tool on the tools list whose name appears in the makefile has its command line arguments passed in a temporary environment variable. For example: .LONGCOMMANDLINE: dmc link lib .PRECIOUS : targets Tells smake not to delete the target if the command to make it is interrupted. If a command is interrupted with a CTRL+C or CTRL+BREAK, smake deletes the target by default. Making a target .PRECIOUS: will make the target immune to deletion across the entire makefile, not just a portion of it. .SILENT Disables the display of command lines before they are executed. You can also use !CMDSWITCHES/S. See also /S, @. .SUFFIXES : lis Provides a list of file name suffixes for smake to use when applying inference rules. The predefined list (as defined in tools.ini) contains: .exe .obj .asm .c .cpp .cxx .res .rc. Additional suffixes can be added by using .SUFFIX; separate each suffix in the list with white space, one or more spaces, or tabs. To clear the suffix list, specify .SUFFIX without any suffixes. See also /P. Expressions in preprocessing directivesThe !IF and !ELSE IF directives use the result of an expression, which is evaluated when these directives are encountered. This expression can consist of any combination of string constants, integer constants, or the names of external programs to be run.Group subexpressions by enclosing them in parentheses. Any constant string in an expression must be enclosed in double quotation marks (""), even if it is a macro. Quoted strings can be compared using the equality (==) or inequality (!=) operators. Numeric values are treated as signed long integers. Numbers are assumed to be decimal values. Octal values must start with 0; hexadecimal values must start with 0x. Constant expressions can use any binary operators (see below); the integer constants can also use the unary operators. An expression can also consist of the name of an external program, enclosed in square brackets ([]). The program will be executed during the preprocessing phase of makefile processing, and that portion of the expression will be replaced by an integer value equal to the error level returned by the executed program. OperatorsUse the following operators in expressions:
Table 13-10 Operators used in smake expressions
Operator Description
DEFINED(macro)
Unary operator that evaluates to TRUE if the macro
is defined. The expression !IF DEFINED( macro) is
equivalent to the expression !IFDEF macro.
EXIST(path)
Unary operator that evaluates to TRUE if the path
exists. Some operating systems allow spaces within
the path name. If a space is used, the path must be
surrounded by double quotation marks (").
+ Addition
- Subtraction
* Multiplication
/ Division
== Equality
!= Inequality
> Greater than
>= Greater than or equal to
< Less than
<= Less than or equal to
& Bitwise AND
| Bitwise OR
^ Bitwise XOR
&& Logical AND
|| Logical OR
<< Left shift
>> Right shift
% Modulus
Running programs with preprocessing directivesWhen you run a program with a smake preprocessing directive, you typically obtain and test its exit code and execute other commands based on the result. For example:!if [c:\mydir\myprog] == 0 # continue processing !else # do something else !endifCommand line macros are expanded before smake executes the makefile. Inference RulesInference rules tell smake how to automatically create certain types of files. For example, to define rules that tell smake how to create an object file (.obj) from a C++ source file (.cpp) and how to create an executable file (.exe) from an object file (.obj). Inference rules reduce the number of actions needing to be typed in.smake interprets inference rules as templates for creating a target from dependent files, based on the extensions of the files involved. Use predefined inference rules or write your own; they can be specified in the makefile or in tools.ini. To determine priorities for applying inference rules, smake uses the list associated with the .SUFFIXES directive. When smake applies inference rulessmake applies inference rules when:
Inference rule syntaxThe dependence line for an inference rule contains the source file extension, the destination file extension, and a colon. Inference rules have the following syntax:
{dependent_path}.dependent_ext{target_path}target_ext:
commands
where dependent_path is the path for the dependent file and
dependent_ext its extension, and target_path is the path for the
target and target_ext its extension. If no paths are specified, smake
looks for the files in the current directory. commands are the steps
smake will take if the dependent file is out of date.
Use macros for paths and extensions. Use the macros in Table 13-4 to specify the arguments. Do not use white space in an inference rule. For example, this rule builds an object file from a C++ file: .cpp.obj : dmc -c $* # $* contains the name of # the target file without # an extensionA simple makefile can use inference rules to create a program from two source files, such as: .cpp.obj dmc -c $* .obj.exe dmc $** test.exe: test.obj util.obj test.obj: test.cpp util.h util.obj: util.cpp Levels of inference rulessmake can interpret no more than one level of inference rules. For example, this makefile does not produce an executable:.c.obj: ;dmc -c $ .obj.exe: ;dmc $ hello.exe: hello.c # ERROR How inference rules workInference rules work on targets and dependents with the same file name and different extensions; they do not match multiple files. For example, you can specify an inference rule to build myprog.obj from myprog.cpp, but not yourprog.obj from myprog.cpp. For example, given this inference rule:.cpp.obj: $<smake will apply this rule to any pair of target/dependency files in the current directory (or on the specified path) that have the same name, where one has the extension .cpp and the other .obj. smake will expand the predefined macros and run the resulting commands on those dependents that are newer than their corresponding targets (as specified by $<). If the target specified has a .exe extension, smake searches for a file with the same base name and an extension that is in the .SUFFIXES list to find which inference rule to use. If the dependence line is followed by commands but does not list dependents, smake will use the inference rules and the .SUFFIXES list to determine the dependent file and then apply the commands specified in the makefile for the target. Order of precedence for inference rulessmake determines the precedence of inference rules as follows:
Predefined inference rulesThe following inference rules are predefined in tools.ini:Table 13-11 Predefined inference rules
Customizing smake Sessions with tools.iniCustomize smake sessions by placing default values for command line options in the initialization file tools.ini. Any settings specified in tools.ini will be used for every smake session, unless /R is specified on the command line. The following is a sample of smake information in tools.ini:[SMAKE] # macro redefinitions CCFLAGS=-A -wx -mn DEBUGFLAGS=-gh # inference rule .c.obj: $<smake information must follow one of the tags [NMAKE] or [SMAKE]. Case is not significant. The format for comments is the same as in makefiles. tools.ini is read before the makefile; you can override macro definitions and inference rules specified in tools.ini in the makefile.
When it searches for tools.ini, smake searches the directory for
executable files first, then the current directory, and finally in the
directory specified by the INIT environment variable.
To write a line to a response file, use the command ECHO and redirect its output with one and two greater-than signs (>>). Write the first line with one greater-than sign so that ECHO creates a new file. Write the rest of the lines with two greater-than signs so that ECHO does not overwrite the file you just created. For example, this makefile creates the program main.exe from the source files main.cpp and funcs.cpp. It not only creates a linker response file, but also writes the linker's output to cmp.err: main.exe: main.obj funcs.obj echo main.obj+funcs.obj > linker.rsp echo main.exe,,, >> linker.rsp +link @linker.rsp > lnk.err main.obj: main.cpp +dmc -c main.cpp > cmp.err funcs.obj: funcs.cpp +dmc -c funcs.cpp >> cmp.err smake Error MessagesThis appendix lists and describes error messages produced by the smake utility.List of smake Error MessagesWhen smake encounters an error, it prints a message to the screen describing the error and then returns to the operating system. smake error messages begin with the text "SMAKE fatal error:" followed in most cases by the name of the makefile and the current line number in the makefile, followed by one of the messages described below.access deniedDOS could not perform the action specified in a command block.can't create response file filenamesmake could not find or open response file filename as specified on the command line (using the @ option).can't create temporary file filenamesmake could not create the temporary file filename.can't execute commandIn a command block, the specified (DOS) command could not be executed.can't nest response filesmake was passed a response file (using the @ option) that included another @ command.can't open error file filenamesmake could not open the error file filename.can't open include file filenamesmake could not open the #include file filename.can't open makefile filenamesmake could not open the makefile filename.can't reopen filename for inputsmake could not reopen the makefile filename after closing a #included file.command expression retured with error code numberIn a command block, the command expression failed; it returned error code (ERRORLEVEL) number.directory not foundIn a command block, the specified (DOS) directory was not found.don't know how to make filenamesmake did not have enough information to make target filename based on the makefile.error in macro substitution syntax: identifierThe macro identifier uses internal substitution (for example, ) incorrectly.exceeded max nesting level for conditionalsConditional directives (for example !IF) within the makefile were nested greater than 32 levels deep.extension ext too long in ruleIn a rule, smake encountered a file extension ext that was too long.file not foundIn a command block, the external (DOS) command was not found.illegal operator and/or operand in expressionA conditional expression was not written properly.illegal string expressionOn the specified line, a string expression within a conditional statement used invalid syntax.invalid option number in parameter numberThe number th option in the number th parameter on the smake command line was invalid.invalid parameter numberThe number th parameter on the smake command line was invalid.not enough memory for commandIn a command block, there was not enough memory to execute the specified (DOS) command.out of memorysmake could not allocate enough memory to continue.parameter number requires a filenameThe number th parameter on the smake command line requires a file name argument.special macro expression is undefined in this contextThe predefined macro expression was used incorrectly.syntax error: expressionOn the specified line, expression contained a syntax error.text found after !ELSEsmake encountered text on a line following a !ELSE directive.too many rules or blocks for target filenameTarget filename was associated with too many rules or blocks.unexpected directivesmake encountered an invalid conditional directive (one beginning with a ! character).unknown errorAn unexpected error occurred.unknown error number executing commandIn a command block, a command returned an error code number that smake could not interpret.unmatched quotes in command identifier filenamesmake was passed a response file (specified using @) that contained unmatched double quotation marks ("). |