Contained WithinFind More DocumentationFeatured Support Resources | PDF로 이 문서 다운로드 (580 KB)
Appendix A System V makeNote - This version of make (/usr/ccs/lib/svr4.make) is included for those users who have makefiles that rely on the older, System V version of make. However, it is recommended that you use the default version of make (/usr/ccs/bin/make) where possible. See also Chapter 4, make Utility , on Chapter 4, make Utility . To use this version of make, set the system variable $ USE_SVR4_MAKE="" ; export USE_SVR4_MAKE (Bourne Shell) % setenv USE_SVR4_MAKE (C shell) For more information on this version of make, see also the sysV-make(1) man page. The trend toward increased modularity of programs means that the project manager may have to work with a large assortment of individual files. A wide range of generation procedures may be needed to turn the assortment of individual files into the final executable product. make provides a method for maintaining up-to-date versions of programs that consist of a number of files that can be generated in a variety of ways. An individual programmer can easily forget:
In a description file, make keeps track of the commands that create files and the relationship between files. Whenever a change is made in any of the files that constitiute a program, the make command creates the finished program by recompiling only those portions directly or indirectly affected by the change. The basic operation of make is to:
The description file that holds the information on interfile dependencies and command sequences is conventionally called makefile, Makefile, s.makefile, or s.Makefile. If this naming convention is followed, the simple command make is usually sufficient to regenerate the target regardless of the number of files edited since the last make. In most cases, the description file is not difficult to write and changes infrequently. Even if only a single file has been edited, rather than entering all the commands to regenerate the target, entering the make command ensures that the regeneration is done in the prescribed way. Basic FeaturesThe basic operation of make is to update a target file by ensuring that all of the files on which the target file depends exist and are up-to-date. The target file is regenerated if it has not been modified since the dependents were modified. The make program searches the graph of dependencies. The operation of make depends on its ability to find the date and time that a file was last modified. The make program operates using three sources of information:
To illustrate, consider a simple example in which a program named prog is made by compiling and loading three C language files x.c, y.c, and z.c with the math library, libm. By convention, the output of the C language compilations is found in files named x.o, y.o, and z.o. Assume that the files x.c and y.c share some declarations in a file named defs.h, but that z.c does not. That is, x.c and y.c have the line #include "defs.h" The following specification describes the relationships and operations: prog : x.o y.o z.o
cc x.o y.o z.o -lm -o prog
x.o y.o : defs.h H
If this information were stored in a file named makefile, the command $ make would perform the operations needed to regenerate prog after any changes had been made to any of the four source files x.c, y.c, z.c, or defs.h. In the previous example, the first line states that prog depends on three .o files. After these object files are current, the second line describes how to load them to create prog. The third line states that x.o and y.o depend on the file defs.h. From the file system, make discovers that there are three .c files corresponding to the needed .o files and that they use built-in rules on how to generate an object from a C source file (that is, issue a cc c command). If make did not have the ability to determine automatically what needs to be done, the following longer description file would be necessary: prog : x.o y.o z.o
cc x.o y.o z.o -lm -o prog
x.o : x.c defs.h
cc -c x.c
y.o : y.c defs.h
cc -c y.c
z.o : z.c
cc -c z.c
If none of the source or object files have changed since the last time prog was made, and all of the files are current, the command make announces this fact and stops. If, however, the defs.h file has been edited, x.c and y.c (but not z.c) are recompiled; and then prog is created from the new x.o and y.o files, and the existing z.o file. If only the file y.c had changed, only it is recompiled; but it is still necessary to reload prog. If no target name is given on the make command line, the first target mentioned in the description is created; otherwise, the specified targets are made. The command $ make x.o would regenerate x.o if x.c or defs.h had changed. A method often useful to programmers is to include rules with mnemonic names and commands that do not actually produce a file with that same name. These entries can take advantage of make's ability to generate files and substitute macros (for information about macros, see "Description Files and Substitutions ".) Thus, an entry save might be included to copy a certain set of files, or an entry clean might be used to throw away unneeded intermediate files. If a file exists after such commands are executed, the file's time of last modification is used in further decisions. If the file does not exist after the commands are executed, the current time is used in making further decisions. You can maintain a zero-length file purely to keep track of the time at which certain actions were performed. This technique is useful for maintaining remote archives and listings. A simple macro mechanism for substitution in dependency lines and command strings is used by make. Macros can either be defined by command-line arguments or included in the description file. In either case, a macro consists of a name followed by the symbol = followed by what the macro stands for. A macro is invoked by preceding the name by the symbol $. Macro names longer than one character must be enclosed in parentheses. The following are valid macro invocations: $(CFLAGS) $2 $(xy) $Z $(Z) The last two are equivalent. Four special macros $*, $@, $?, and $< change values during the execution of the command. (These four macros are described under "Description Files and Substitutions ".) The following fragment shows assignment and use of some macros: OBJECTS = x.o y.o z.o
LIBES = -lm
prog: $(OBJECTS)
cc $(OBJECTS) $(LIBES) -o prog
...
The command $ make LIBES="-ll -lm" loads the three objects with both the lex (-ll) and the math (-lm ) libraries, because macro definitions on the command line override definitions in the description file. (In operating system commands, arguments with embedded blanks must be quoted.) As an example of the use of make, a description file that might be used to maintain the make command itself is given. The code for make is spread over a number of C language source files and has a yacc grammar. The description file contains the following: # Description file for the make command
FILES = Makefile defs.h main.c doname.c misc.c \
files.c dosys.c gram.y
OBJECTS = main.o doname.o misc.o files.o dosys.o gram.o
LIBES =
LINT = lint -p
CFLAGS = -O
LP = lp
make: $(OBJECTS)
$(CC) $(CFLAGS) -o make $(OBJECTS) $(LIBES)
@size make
$(OBJECTS): defs.h
cleanup:
-rm *.o gram.c
-du
install:
make
@size make /usr/bin/make
cp make /usr/bin/make && rm make
lint: dosys.c doname.c files.c main.c misc.c gram.c
$(LINT) dosys.c doname.c files.c main.c misc.c gram.c
# print files that are out-of-date
# with respect to "print" file.
print: $(FILES)
pr $? | $(LP)
touch print
The make program prints each command before issuing it. The following output results from entering the command make in a directory containing only the source and description files: cc -O -c main.c cc -O -c doname.c cc -O -c misc.c cc -O -c files.c cc -O -c dosys.c yacc gram.y mv y.tab.c gram.c cc -O -c gram.c cc -o make main.o doname.o misc.o files.o dosys.o gram.o \ 13188 + 3348 + 3044 = 19580 The last line results from the size make command. The printing of the command line itself was suppressed by the symbol @ in the description file. Description Files and SubstitutionsThe following section explains the most commonly used elements of the description file. CommentsThe # symbol marks the beginning of a command, and all characters on the same line after it are ignored. Blank lines and lines beginning with # are ignored. Continuation LinesIf a noncomment line is too long, the line can be continued by using the symbol \, which must be the last character on the line. If the last character of a line is \, then it, the new line, and all following blanks and tabs are replaced by a single blank. Macro DefinitionsA macro definition is an identifier followed by the symbol =. The identifier must not be preceded by a colon (:) or a tab. The name (string of letters and digits) to the left of the = (trailing blanks and tabs are stripped) is assigned the string of characters following the =+ (leading blanks and tabs are stripped). The following are valid macro definitions: 2 = xyz abc = -ll -ly -lm LIBES = The last definition assigns LIBES the null string. A macro that is never explicitly defined has the null string as its value. Remember, however, that some macros are explicitly defined in make's own rules. (See "Internal Rules ".) General FormThe general form of an entry in a description file is: target1 [target2 ...] :[:] [dependent1 ...] [; commands] [# ...] [ \t commands] [# ...] . . . Items inside brackets can be omitted and targets and dependents are strings of letters, digits, periods, and slashes. Shell metacharacters such as * and ? are expanded when the commands are evaluated. Commands can appear either after a semicolon on a dependency line or on lines beginning with a tab (denoted above as \t) immediately following a dependency line. A command is any string of characters not including #, except when # is in quotes. Dependency InformationA dependency line can have either a single or a double colon. A target name can appear on more than one dependency line, but all of those lines must be of the same (single or double colon) type. For the more common single colon case, a command sequence can be associated with at most one dependency line. If the target is out of date with any of the dependents on any of the lines and a command sequence is specified (even a null one following a semicolon or tab), it is executed; otherwise, a default rule can be invoked. In the double colon case, a command sequence can be associated with more than one dependency line. If the target is out of date with any of the files on a particular line, the associated commands are executed. A built-in rule can also be executed. The double-colon form is particularly useful in updating archive-type files, where the target is the archive library itself. (An example is included in the "Archive Libraries " section.) Executable CommandsIf a target must be created, the sequence of commands is executed. Normally, each command line is printed and then passed to a separate invocation of the shell after substituting for macros. The printing is suppressed in the silent mode (-s option of the make command) or if the command line in the description file begins with an @ sign. make normally stops if any command signals an error by returning a nonzero error code. Errors are ignored if the -i flag has been specified on the make command line, if the fake target name .IGNORE appears in the description file, or if the command string in the description file begins with a hyphen (-). If a program is known to return a meaningless status, a hyphen in front of the command that invokes it is appropriate. Because each command line is passed to a separate invocation of the shell, care must be taken with certain commands (cd and shell control commands, for instance) that have meaning only within a single shell process. These results are forgotten before the next line is executed. Before issuing any command, certain internally maintained macros are set. The In addition, a description file can also use the following related macros: Extensions of $*, $@, and $<The internally generated macros cd $(<D); $(MAKE) $(<F) Output TranslationsThe values of macros are replaced when evaluated. The general form, where brackets indicate that the enclosed sequence is optional, is as follows: $(macro[:string1=[string2]]) The parentheses are optional if there is no substitution specification and the macro name is a single character. If a substitution sequence is present, the value of the macro is considered to be a sequence of ``words'' separated by sequences of blanks, tabs, and new-line characters. Then, for each such word that ends with string1, string1 is replaced with string2 (or no characters if string2 is not present). This particular substitution capability was chosen because make is sensitive to suffixes. The usefulness of this type of translation occurs when maintaining archive libraries. Now, all that is necessary is to accumulate the out-of-date members and write a shell script that can handle all the C language programs (that is, files ending in .c). The following fragment optimizes the executions of make for maintaining an archive library: $(LIB): $(LIB)(a.o) $(LIB)(b.o) $(LIB)(c.o)
$(CC) -c $(CFLAGS) $(?:.o=.c)
$(AR) $(ARFLAGS) $(LIB) $?
rm $?
A dependency of the preceding form is necessary for each of the different types of source files (suffixes) that define the archive library. These translations are added to offer more general use of the wealth of information that make generates. Recursive MakefilesAnother feature of make concerns the environment and recursive invocations. If the sequence $(MAKE) appears anywhere in a shell command line, the line is executed even if the -n flag is set. Since the -n flag is exported across invocations of make (through the MAKEFLAGS variable), the only thing that is executed is the make command itself. This feature is useful when a hierarchy of makefiles describes a set of software subsystems. For testing purposes, make -n can be executed and everything that would have been done is printed, including output from lower-level invocations of make. Suffixes and Transformation Rulesmake uses an internal table of rules to learn how to transform a file with one suffix into a file with another suffix. If the -r flag is used on the make command line, the internal table is not used. The list of suffixes is actually the dependency list for the name .SUFFIXES. make searches for a file with any of the suffixes on the list. If it finds one, make transforms it into a file with another suffix. Transformation rule names are the concatenation of the before and after suffixes. The name of the rule to transform a .r file to a .o file is thus .r.o. If the rule is present and no explicit command sequence has been given in the user's description files, the command sequence for the rule .r.o is used. If a command is generated by using one of these suffixing rules, the macro The order of the suffix list is significant because the list is scanned from left to right. The first name formed that has both a file and a rule associated with it is used. If new names are to be appended, the user can add an entry for .SUFFIXES in the description file. The dependencies are added to the usual list. A .SUFFIXES line without any dependencies deletes the current list. It is necessary to clear the current list if the order of names is to be changed. Implicit Rulesmake uses a table of suffixes and a set of transformation rules to supply default dependency information and implied commands. The default suffix list (in order) is as follows:
Figure A-1 summarizes the default transformation paths. If two paths connect a pair of suffixes, the longer one is used only if the intermediate file exists or is named in the description. Figure A-1 Summary of Default Transformation Path
If the file x.o is needed and an x.c is found in the description or directory, the x.o file would be compiled. If there is also an x.l, that source file is run through lex before compiling the result. However, if there is no x.c but there is an x.l, make discards the intermediate C language file and uses the direct link, as shown in Figure A-1. It is possible to change the names of some of the compilers used in the default or the flag arguments with which they are invoked by knowing the macro names used. The compiler names are the macros $ make CC=newcc The macros $ make CFLAGS=-g causes the cc command to include debugging information. Archive LibrariesThe make program has an interface to archive libraries. A user can name a member of a library in the following manner: projlib(object.o) or projlib((entry_pt)) where the second method actually refers to an entry point of an object file within the library. (make looks through the library, locates the entry point, and translates it to the correct object filename.) To use this procedure to maintain an archive library, the following type of makefile is required: projlib:: projlib(pfile1.o)
$(CC) -c $(CFLAGS) pfile1.c
$(AR) $(ARFLAGS) projlib pfile1.o
rm pfile1.o
projlib:: projlib(pfile2.o)
$(CC) -c $(CFLAGS) pfile2.c
$(AR) $(ARFLAGS) projlib pfile2.o
rm pfile2.o
and so on for each object. This is tedious and prone to error. Obviously, the command sequences for adding a C language file to a library are the same for each invocation; the filename being the only difference each time. This is true in most cases. The make command also gives the user access to a rule for building libraries. The handle for the rule is the .a suffix. Thus, a .c.a rule is the rule for compiling a C language source file, adding it to the library, and removing the .o file. Similarly, the .y.a, the .s.a, and the .l.a rules rebuild yacc, assembler, and lex files. The archive rules defined internally are .c.a, .c~.a, .f.a, .f~.a, and .s~.a. (The tilde (~) syntax will be described shortly.) The user can define other needed rules in the description file. The above two-member library is then maintained with the following shorter makefile: projlib: projlib(pfile1.o) projlib(pfile2.o)
@echo projlib up-to-date.
The internal rules are already defined to complete the preceding library maintenance. The actual .c.a rule is as follows: c.a:
$(CC) -c $(CFLAGS) $<
$(AR) $(ARFLAGS) $@ $*.o
rm -f $*.o
Thus, the It is useful to go into some detail about exactly what make does when it executes the construction projlib: projlib(pfile1.o)
@echo projlib up-to-date
Assume the object in the library is out of date with respect to pfile1.c. Also, there is no pfile1.o file.
To enable pfile1.o to have dependencies, the following syntax is required: projlib(pfile1.o): $(INCDIR)/stdio.h pfile1.c There is also a macro for referencing the archive member name when this form is used. The Source Code Control System (SCCS) FilenamesThe syntax of make does not directly permit referencing of prefixes. For most types of files on operating operating system machines, this is acceptable since nearly everyone uses a suffix to distinguish different types of files. SCCS files are the exception. Here, s. precedes the filename part of the complete path name. To allow make easy access to the prefix s., the symbol ~ is used as an identifier of SCCS files. Hence, .c~.o refers to the rule which transforms an SCCS C language source file into an object file. Specifically, the internal rule is $(GET) $(GFLAGS) $< $(CC) $(CFLAGS) -c $*.c rm -f $*.c . Thus, ~ appended to any suffix transforms the file search into an SCCS filename search with the actual suffix named by the dot and all characters up to (but not including the tilde symbol. The following SCCS suffixes are internally defined:
The following rules involving SCCS transformations are internally defined:
Obviously, the user can define other rules and suffixes that can prove useful. The ~ provides a handle on the SCCS filename format so that this is possible. The Null SuffixMany programs consist of a single source file. make handles this case by the null suffix rule. To maintain the operating system program cat, a rule in the makefile of the following form is needed: $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $< In fact, this .c: rule is internally defined so no makefile is necessary at all. The user only needs to enter $ make cat dd echo date (these are all operating system single-file programs) and all four C language source files are passed through the above shell command line associated with the .c: rule. The internally defined single suffix rules are:
Others can be added in the makefile by the user. Included FilesThe make program has a capability similar to the #include directive of the C preprocessor. If the string include appears as the first seven letters of a line in a makefile and is followed by a blank or a tab, the rest of the line is assumed to be a filename, which the current invocation of make reads. Macros can be used in filenames. The file descriptors are stacked for reading include files so that no more than 16 levels of nested includes are supported. SCCS MakefilesMakefiles under SCCS control are accessible to make. That is, if make is typed and only a file named s.makefile or s.Makefile exists, make performs a get on the file, then reads and removes the file. Dynamic-Dependency ParametersA dynamic-dependency parameter has meaning only on the dependency line in a makefile. The $$@ refers to the current ``thing'' to the left of the : symbol (which is $@). Also the form $$(@F) exists, which allows access to the file part of $@. Thus, in the following example: cat: $$@.c the dependency is translated at execution time to the string cat.c. This is useful for building a large number of executable files, each of which has only one source file. For instance, the operating system software command directory could have a makefile such as: CMDS = cat dd echo date cmp comm chown
$(CMDS): $$@.c
$(CC) $(CFLAGS) $? -o $@
Obviously, this is a subset of all the single file programs. For multiple file programs, a directory is usually allocated and a separate makefile is made. For any particular file that has a peculiar compilation procedure, a specific entry must exist in the makefile. The second useful form of the dependency parameter is $$(@F). It represents the filename part of $$@. Again, it is evaluated at execution time. Its usefulness becomes evident when trying to maintain the /usr/include directory from makefile in the /usr/src/head directory. Thus, the /usr/src/head/makefile would look like: INCDIR = /usr/include
INCLUDES = \
$(INCDIR)/stdio.h \
$(INCDIR)/pwd.h \
$(INCDIR)/dir.h \
$(INCDIR)/a.out.h
$(INCLUDES): $$(@F)
cp $? $@
chmod 0444 $@
This would completely maintain the /usr/include directory whenever one of the above files in /usr/src/head was updated. Command UsageThe make CommandThe make command takes macro definitions, options, description filenames, and target filenames as arguments in the form: $ make [ options ] [ macro definitions and targets ] The following summary of command operations explains how these arguments are interpreted. First, all macro definition arguments (arguments with embedded = symbols) are analyzed and the assignments made. Command line macros override corresponding definitions found in the description files. Next, the option arguments are examined. The permissible options are as follows:
Finally, the remaining arguments are assumed to be the names of targets to be made and the arguments are done in left-to-right order. If there are no such arguments, the first name in the description file that does not begin with the symbol . is made. Environment VariablesEnvironment variables are read and added to the macro definitions each time make executes. Precedence is a prime consideration in doing this properly. The following describes make's interaction with the environment. A macro, When executed, make assigns macro definitions in the following order:
Suggestions and WarningsThe most common difficulties arise from make's specific meaning of dependency. If file x.c has the following line: #include "defs.h" then the object file x.o depends on defs.h; the source file x.c does not. If defs.h is changed, nothing is done to the file x.c while file x.o must be recreated. To discover what make would do, the -n option is very useful. The command $ make -n orders make to print out the commands that make would issue without actually taking the time to execute them. If a change to a file is absolutely certain to be mild in character (adding a comment to an include file, for example), the -t (touch) option can save a lot of time. Instead of issuing a large number of superfluous recompilations, make updates the modification times on the affected file. Thus, the command $ make -ts (touch silently) causes the relevant files to appear up to date. Obvious care is necessary because this mode of operation subverts the intention of make and destroys all memory of the previous relationships. Internal RulesThe standard set of internal rules used by make are reproduced below. Suffixes recognized by make are:
The following are predefined macros:
Special RulesThis section covers special make rules with either single or double suffixes. markfile.o : markfile
A=@; echo "static char _sccsid[]=\042`grep $$A'(#)' \
markfile`\042;" > markfile.c
$(CC) -c markfile.c
rm -f markfile.c
Single-Suffix RulesThe following are single-suffix rules: .c: $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< .c~: $(GET) $(GFLAGS) $< $(CC) $(CFLAGS) $(LDFLAGS) -o $* $*.c rm -f $*.c .s: $(AS) $(AFLAGS) -o $@ $< .s~: $(GET) $(GFLAGS) $< $(AS) $(AFLAGS) -o $@ $*.s rm -f $*.s .sh: cp $< $@; chmod 0777 $@ .sh~: $(GET) $(GFLAGS) $< cp $*.sh $*; chmod 0777 $@ rm -f $*.sh .f: $(F77) $(FFLAGS) $(LDFLAGS) -o $@ $< .f~: $(GET) $(GFLAGS) $< $(F77) $(FFLAGS) -o $@ $(LDFLAGS) $*.f rm -f $*.f .C~: $(GET) $(GFLAGS) $< $(C++C) $(C++FLAGS) -o $@ $(LDFLAGS) $*.C rm -f $*.C .C: $(C++C) $(C++FLAGS) -o $@ $(LDFLAGS) $< Double-Suffix RulesThe following are double-suffix rules:
$(GET) $(GFLAGS) $< .c.a: $(CC) -c $(CFLAGS) $< $(AR) $(ARFLAGS) $@ $*.o rm -f $*.o c.a~: $(GET) $(GFLAGS) $< $(CC) -c $(CFLAGS) $*.c $(AR) $(ARFLAGS) $@ $*.o rm -f $*.[co] .c.o: $(CC) $(CFLAGS) -c $< .c~.o: $(GET) $(GFLAGS) $< $(CC) $(CFLAGS) -c $*.c rm -f $*.c .y.c: $(YACC) $(YFLAGS) $< mv y.tab.c $@ .y~.c: $(GET) $(GFLAGS) $< $(YACC) $(YFLAGS) $*.y mv y.tab.c $*.c rm -f $*.y .y.o: $(YACC) $(YFLAGS) $< $(CC) $(CFLAGS) -c y.tab.c rm -f y.tab.c mv y.tab.o $@ .y~.o: $(GET) $(GFLAGS) $< $(YACC) $(YFLAGS) $*.y $(CC) $(CFLAGS) -c y.tab.c rm -f y.tab.c $*.y mv y.tab.o $*.o .l.c: $(LEX) $(LFLAGS) $< mv lex.yy.c $@ .l~.c: $(GET) $(GFLAGS) $< $(LEX) $(LFLAGS) $*.l mv lex.yy.c $@ rm -f $*.l .l.o: $(LEX) $(LFLAGS) $< $(CC) $(CFLAGS) -c lex.yy.c rm -f lex.yy.c mv lex.yy.o $@ .l~.o: $(GET) $(GFLAGS) $< $(LEX) $(LFLAGS) $*.l $(CC) $(CFLAGS) -c lex.yy.c rm -f lex.yy.c $*.l mv lex.yy.o $@ .s.a: $(AS) $(ASFLAGS) -o $*.o $*.s $(AR) $(ARFLAGS) $@ $*.o .s~.a: $(GET) $(GFLAGS) $< $(AS) $(ASFLAGS) -o $*.o $*.s $(AR) $(ARFLAGS) $@ $*.o rm -f $*.[so] .s.o: $(AS) $(ASFLAGS) -o $@ $< .s~.o: $(GET) $(GFLAGS) $< $(AS) $(ASFLAGS) -o $*.o $*.s rm -f $*.s .f.a: $(F77) $(FFLAGS) -c $*.f $(AR) $(ARFLAGS) $@ $*.o rm -f $*.o .f~.a: $(GET) $(GFLAGS) $< $(F77) $(FFLAGS) -c $*.f $(AR) $(ARFLAGS) $@ $*.o rm -f $*.[fo] .f.o: $(F77) $(FFLAGS) -c $*.f .f~.o: $(GET) $(GFLAGS) $< $(F77) $(FFLAGS) -c $*.f rm -f $*.f .C.a: $(C++C) $(C++FLAGS) -c $< $(AR) $(ARFLAGS) $@ $*.o rm -f $*.o .C~.a: $(GET) $(GFLAGS) $< $(C++C) $(C++FLAGS) -c $*.C $(AR) $(ARFLAGS) $@ $*.o rm -f $*.[Co] .C.o: $(C++C) $(C++FLAGS) -c $< .C~.o: $(GET) $(GFLAGS) $< $(C++C) $(C++FLAGS) -c $*.C rm -f $*.C .Y.C: $(YACC) $(YFLAGS) $< mv y.tab.c $@ .Y~.C: $(GET) $(GFLAGS) $< $(YACC) $(YFLAGS) $*.Y mv y.tab.c $*.C rm -f $*.Y .Y.o $(YACC) $(YFLAGS) $< $(C++C) $(C++FLAGS) -c y.tab.c rm -f y.tab.c mv y.tab.o $@ .Y~.o: $(GET) $(GFLAGS) $< $(YACC) $(YFLAGS) $*.Y $(C++C) $(C++FLAGS) -c y.tab.c rm -f y.tab.c $*.Y mv y.tab.o $*.o .L.C: $(LEX) $(LFLAGS) $< mv lex.yy.c $@ .L~.C: $(GET) $(GFLAGS) $< $(LEX) $(LFLAGS) $*.L mv lex.yy.c $@ rm -f $*.L .L.o: $(LEX) $(LFLAGS) $< $(C++C) $(C++FLAGS) -c lex.yy.c rm -f lex.yy.c mv lex.yy.o $@ .L~.o: $(GET) $(GFLAGS) $< $(LEX) $(LFLAGS) $*.L $(C++C) $(C++FLAGS) -c lex.yy.c rm -f lex.yy.c $*.L mv lex.yy.o $@ |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||