# How To Create a Makefile # ~~~~~~~~~~~~~~~~~~~~~~~~ # Large C programs are built out of header (.h), source (.c), object (.o), and # library (.a) files. make is a rule-based expert system that determines which # of these files must be created (because they do not exist) or recompiled / # relinked (because they are not up to date) and issues the commands to do so. # These commands and the dependencies among the files (which are used to decide # what files must be (re)compiled or (re)linked) are specified in a file whose # name can be either "Makefile" or "makefile". This sample Makefile is somewhat # contrived. Consult the entry for make in the info system for full details. # Within a Makefile lines that are blank or begin with # are ignored. The rest # contain macro definitions and rules. # A macro definition has the form # # VARIABLE = VALUE # # and causes any subsequent occurrences of the string "${VARIABLE}" to be # replaced by the string "VALUE". For example, the macros CC = gcc CFLAGS = -g3 -std=c99 -pedantic -Wall HWK = /c/cs223/Hwk1 # specify # # * the C compiler to use (the default is cc); # # * the options to pass to the C compiler (-g3 generates supplementary # information needed by ddd and gdb, -std=c99 specifies the C99 standard, and # -pedantic and -Wall check for certain questionable coding practices); and # # * the class directory for the first programming assignment (${HWK} is thus # shorthand for /c/cs223/Hwk1). # # Note that macro definitions must begin in the first column. # A rule has the form # # TARGET: # COMMAND # # and specifies that the file TARGET depends upon each file in the list of # prerequisites and that, if TARGET does not exist or is older than at least # one of these files, it can be created/updated by issuing the shell command # COMMAND. For example, the rule squash: squash.o myLibs.o ${HWK}/common.o ${CC} ${CFLAGS} -o squash squash.o myLibs.o ${HWK}/common.o # states that the executable squash depends on your object files squash.o and # myLibs.o and on the object file common.o in the class directory (*). The # command invokes the C compiler to create or relink squash (without the -o # option the executable would be called a.out). Note: Delete myLibs.o and # ${HWK}/common.o from the rule above if your squash does not use them. # ----- # (*) The executable does not depend directly on squash.c or myLibs.c so # the command to create it should not refer to them either. Rules to create # object files from source files are discussed below. The object file # ${HWK}/common.o should not be recreated even if the source is available. # Note that the name of the target file must begin in the first column; the # list of prerequisite files is delimited by whitespace and may be empty; and # the command (which may be omitted) MUST BE PRECEDED BY A TAB CHARACTER (*). # ----- # (*) GOTCHA: Each command line must begin with a tab character, NOT eight # space characters, even though they look the same when output. Otherwise # make will get confused and generate an incomprehensible error message. # The source file squash.c must be recompiled whenever it changes, or more # generally whenever squash.o does not exist or is older than squash.c. This # dependency could be specified by the rule # # squash.o: squash.c # ${CC} ${CFLAGS} -c squash.c # # where the -c option specifies compilation but no linking. However, it occurs # sufficiently often that this rule is built into make and thus is almost never # stated explicitly. # If the source files squash.c and myLibs.c #include the header file myLibs.h, # then squash.c and myLibs.c must be recompiled whenever that header file is # modified. This is specified by the rules squash.o: myLibs.h myLibs.o: myLibs.h # where the command to recompile is implicit and is thus omitted (see above). # These dependencies can also be written as the single rule # # squash.o myLibs.o: myLibs.h # # Note that the targets are the .o files, not the .c files, which do NOT depend # upon myLibs.h. # Finally assume that a second executable psched depends upon the object files # psched.o and myLibs.o, and that psched.c also #include-s the header file # myLibs.h. This could be specified by the rules psched: psched.o myLibs.o ${CC} ${CFLAGS} $^ -o $@ psched.o: myLibs.h # where the special macro $@ expands to the target of the rule (here psched); # and the special macro $^ expands to the list of prerequisites (here psched.o # and myLibs.o). The dependence of myLibs.o on myLibs.h was specified earlier. # make is invoked as # # % make # # which causes each of the named targets to be updated. For example, # # % make psched # # (re)links psched. If no target is specified, then the targets of the first # rule to appear in the Makefile is assumed. Thus with this Makefile # # % make # # is equivalent to # # % make squash # A few more details: # # * A file may appear in the target list of more than one rule, in which case # it depends on all of the files in the prerequisite lists of these rules. # However, only one of these rules may be followed by a shell command. # # * If a prerequisite file is itself a target, then it may have prerequisites # of its own. Thus make recursively creates/updates each prerequisite of a # target BEFORE checking whether that target is older than any of its # prerequisites. However, no file is updated more than once. # # * The shell command can be a sequence of commands, one per line, but each # line must begin with a tab. A blank line ends the sequence. # CS-223-09/23/18