# # This is a simple makefile. # # There are several good reasons for using a makefile. One is that # you can speed up compilation and improve version control by breaking # up your code into multiple files. If, for example, you have already # compiled "zz.c" into a "zz.o"file, so that the "zz.o" file is still # available, and you have NOT edited the "zz.c" file since the last # compilation, then using the makefile will not cause the "zz.o" file # to be created again. The only parts of a program that need to be # recompiled are those parts whose source code has been edited. What # you do in the first line of the pair of lines for a given file is # to tell the shell what the dependencies are. # # The other good reason is that typing in all the options is a pain. # The makefile is a script that lets you type in the stuff only once # and not every time you need to do a compile. # # The usage of this makefile is as follows. # To create the executable file "progthis", issue to the shell the command # make progthis # # To create the executable file "progthat", issue to the shell the command # make progthat # # The difference between the two executables is that the compilation of # the two has been done one with the symbol "THIS" defined to the compiler # and one with the symbol "THAT" defined. # # Here's what the makefile does. # # First, as might be obvious, the "#" symbol indicates that that line # is a comment. # # Next, we declare the symbol "I" to be equal to the symbol "io.h", # and the symbol "A" to be equal to the symbol "zthis.o", # and the symbol "B" to be equal to the symbol "zthat.o", # and the symbol "ZZ" to be equal to the symbol "zz.o". # In later usage we refer to these symbols with the dollar sign. # Note the syntax: If the symbol is a single letter, like "A" or "B", # then we need only write "$A" or "$B", but if the symbol is longer # than one character then we need to enclose the symbol in parentheses, # as in $(ZZ)$. # There isn't any special case-sensitivity; I use capital letters for # symbols just to make them stand out a little more in the makefile. I = io.h A = zthis.o B = zthat.o ZZ = zz.o # Now, here's how we read the following. # # We remember that in unix a file such as "z.c" with a "dot c" extension # is taken to be a program in C. If we compile that program but do not # do the link and load step, we get a "z.o" object file with a "dot o" # extension. If we compile "dot c" and "dot o" files, we wind up with # an "a.out" file by default. What follows in this makefile are # instructions to the shell to control that process. # # The first line of each pair of lines says the following: # foo: bar1 bar2 bar3 # means that the file "foo" depends on the files "bar1" and "bar2". # To create file "foo" we need to have "bar1" and "bar2" available # and up to date, and if either "bar1" or "bar2" have changed since the # last time we created "foo" then we need to re-create "foo". # The lines after the first are instructions to the shell on *how* # to create or re-create "foo". # # The first pair says that to create the "progthis" file we need to have # available the files referred to by "$I", "$A" and "$(ZZ)", namely the # "io.h", "zthis.o", and "zz.o" files. If we have those files available, # then what we do is a C compile (the "cc" command), naming the output # of the compilation the file "progthis" (the "-o progthis" part), # compiling the files referred to by "$A" and $(ZZ)", and supplying # to the compilation the symbol "THIS" for use in the "ifdef" statements # in the C code. # # The second pair of lines is entirely similar to the "this" lines, but # are "that" lines. To see the effect, look at the "ifdef" parts of the # C code. progthis: $I $A $(ZZ) cc -o progthis -DTHIS $A $(ZZ) progthat: $I $B $(ZZ) cc -o progthat -DTHAT $B $(ZZ) # Ok. We said in the "progthis" line that we needed to have defined # two files named by "$A" and "$(ZZ)", namely the files "zthis.o" and # "zz.o". The following lines tell the shell how to create those files. # # To create the "$A" file, namely the "zthis.o" file, we need to have # available the "z.c" file. If we have available the "z.c" file, then # what we want to do with it is a C compile (the "cc" part), but ONLY # the compile, not the link-load (this is the "-c" option). We want to # call the output file "zthis.o" (this is the "-o $A" part); we want to # compile the file "z.c", and we want to define the symbol "THIS" to # the compiler with the "-DTHIS" option. $A: $I z.c cc -c -o $A -DTHIS z.c # This is exactly as above but is "that" instead of "this". Look # at the "ifdef" lines in the C code to see what the difference is. $B: $I z.c cc -c -o $B -DTHAT z.c # Finally, we tell the shell how to create the "zz.o" file. This # one is a vanilla compilation. The default output of the compile # step with the "-c" option is a "dot o" file. $(ZZ): $I zz.c cc -c zz.c # Now, normally I am not devious, but I have been deliberately devious # in this instance because I want to make sure you read to the end of # this file. # # BE VERY SURE that the whitespace character (the one before the "cc" # commands in this makefile) is a TAB character and not blank spaces. # If you use blanks instead of the tab, you will get one of the more # obscure error messages in all of unix. #