The make utility is a powerful tool to manage the creation and maintenance of systems and libraries. The actions of the make utility are controlled by a "makefile" that describes:
There are two kinds of dependencies among the files that make up on object oriented system:
The FileChooser class is used to ilustrate these two kinds of dependencies. The definition of the FileChooser class (in FileChooser.h) uses the class File as a return type of the AskUser() method. Thus, the FileChooser.h class must include File.h and FileChooser.h depends on File.h (FileChooser.h --> File.h).
class FileChooser { private: char fileSpec[200]; char* choices[200]; void makeSpec(char* p, char* f); // utility function public: FileChooser(char* path, char* filter); //search at path with filter FileChooser(char* path); //search at path, no filter FileChooser(); //search at CWD, no filter File AskUser(); //get file via dialog ~FileChooser(); //clean up };
File FileChooser::AskUser() { Directory directory(thePath, theFilter); Selector selector(thePath); char* nextName = directory.First(); while (nextName) { selector.Add(nextName); nextName = directory.Next(); } char* fileChosen = selector.AskUser(); return File(fileChosen); }The AskUser method uses a Directory object and a Selector object. Thus, the FileChooser.cc file depends on the Directory.h file and the Selector.h file. A summary of these dependencies is:
FileChooser.h --> File.h FileChooser.cc --> FileChooser.h Directory.h Selector.h
FileChooser.o --> FileChooser.cc
FileChooser.o --> FileChooser.cc FileChooser.h Directory.h Selector.h File.h
{target}: {dependency list} {tab} {command list}The {target} names an object file or a complete system that make will build, or a utility function be be performed by make. The target must be followed by the required colon (":") character. The {dependency list} is a list of other elements on which the given target depends. The {command list} is a list of commands to be performed when the {target} is being built or performed by make. The {tab} is a required character that must begin the line on which the line containing the command list.
Both the dependency list and the command list must be a single "line". Either list, however, may be quite long. A standard technique is used to make the lists readable while preserving the view that each one appears as a single "line" to the make utility. A backslash ("\") character immediately preceeding a "new line" (or return) character will cause a second line when displayed on the screen or printed but, when read by the make utility, these two characters will appear as whitespace (a blank). Examples of this will be seen below.
The first kind of targets are those that name components of the system that make will build. A common target of this form is one that names an object file to be built by compiling one or more code files. For example, a rule to build the FileChooser.o object file might appear as:
FileChooser.o: FileChooser.cc, FileChooser.h, Directory.h, \{cr} Selector.h, File.h {cr} {tab} g++ {...} -o FileChooser.o FileChooser.cc {...}In this example, the target is named FileChooser.o. Since the list of dependencies is long, the backslash character is used to break the single logical "line" into two physical lines. The {tab} shows that a tab character must begin the line containing the command. In this case, a command to compile FileChooser.cc using the g++ compiler is shown in abbreviated form. The notation {...} is used to show where additional parts of the command would go. The full command is shown below.
The second type of target is one that names a complete system or
library to be built by make. For example, a target such as:
Program: FileChooser.o Directory.o Frame.o {...} g++ {...} -o Program *.o {...}describes how to build an executable program named Program by having g++ link all of the object files in the current directory. Note that g++ can be used both the compile code files and link object files. The target Program can be refered to in the invocation of make as
make Programwhich will cause the make utility to find and perform the actions required by a rule whose target is named "Program" in a file named "makefile". Alternatively, if "Program" is the first or only target in the makefile, then the same actions will occur simply by using the command "make" with no arguments.
The third type of target names a utility function performed by the makefile. A common target of this form is the "clean" target that "cleans up" after the make utility by removing intermediate files produced during the running of make that are not needed for longer term use. A typical example is:
clean: rm *.o core ./tmp/*which deletes all object files in the current directory, a core file that might have been produced when a test program crashed, and all files in a subdirectory named "tmp".
Variables are like simple macros. The value of a variable is a simple string. That string is inserted verbatim wherever the value of the variable is referenced.
By convention variables are given suggestive names that are written in capital letters such as OBJECTS, OBJDIR, TMPFILE. The value of a variable is a string of any length that is "assigned" to a variable Eusing an "=" operator. For example:
CC = g++ COMPLIBS= -lgen -ldl -lsocket -lnsl -lg++ CCFLAGS = -Wall -O INCLUDEPATH=-I/usr/include/X11 LIBPATH=-L/usr/lib/X11 OBJECTS = Base.o BasicFrame.o Button.o \ Counter.o Date.o Directory.o \ File.o FileQuery.o FileNavigator.o \ FileChooser.o Frame.o Location.o \ Message.o Selector.o Shape.o \ TextBox.o Timer.o Program.oThis example defines several make variables: OBJECTS is a list of .o files written over several lines using the "\{cr}" technique; CC defines what the C++ compiler is called on this system - variables like this one are often defined to aid in porting the software among different platforms that may use different compilers; COMPLIBS is a list of libraries to include when an executable program is built; CCFLAGS defines options to the g++ compiler indicating that all warning messages should be displayed (-Wall) and to optimize the compiled code (-O); INCLUDEPATH is a compiler option specifying where to look for header files (in this case header for the X windows system); LIBPATH is a variable that specifies where to look in the file system to find the X windows system library.
The value of a variable is obtained by enclosing the variable name in "$()" as in $(OBJECTS) or $(CC). Several examples of using the values of variables are these:
LDLIBS = -lwx_motif -lXm -lXt -lX11 -lm $(COMPLIBS) PATHS = $(INCLUDEPATH) $(LIBPATH) Program.o: Program.cc $(CC) -c $(CCFLAGS) -o $@ Program.cc all: $(OBJDIR) $(OBJECTS) $(CC) $(CCFLAGS) $(PATHS) -o Program $(OBJECTS) $(LDLIBS)The first two examples show how one variable can be used in defining the value of another variable. In each case the value of the variable is simply concatenated with the other characters around it to form the value of the variable being defined. The third example shows a rule where the command list uses several variables: the name of the compiler to use (CC), and the flags to be passed to the compiler (CCFLGS). The symbol "$@" is a built-in make variable that refers to the target's name without any suffix - in this case $@ would be "Program" because "Program.o" is the target and the ".o" is the suffix that is removed to define the current value of $@. The final example shows that variables can be used in both the command list and the dependency list. In this example the target "all" depends on everything that is named in the values of OBJDIR and OBJECTS.
|
Last updated: July 3, 1996 / kafura@cs.vt.edu