The Make utility:
To use Make you must create a file named makefile or Makefile. A Makefile contains a collection of rules, each of which includes:
Here's an example Makefile:
examples.class: examples.java IO.class Sequence.class javac -g examples.java Sequence.class: Sequence.java NoCurrentException.class javac -g Sequence.java NoCurrentException.class: NoCurrentException.java javac -g NoCurrentException.java IO.class: IO.java javac -g IO.java
In this example, each rule consists of 2 lines (so there are 4 rules total). In each rule, the file name to the left of the colon is the target. To the right of the colon are listed the files needed to create that target. The line that starts with "javac -g ..." is the command to create the target.
Note that the first character of every "command" line must be a tab! If you use spaces instead, you'll get an obscure error message when you try to use the Makefile.
How do you know what to use for the "list of files on which the target depends"? To understand that, you need to know that "A depends on B" means: if B changes, then A may need to be recreated (recompiled in our example). So for Java programs, for the rule with target xxx.class (created by compiling xxx.java), the list should include all files that define classes that are used in xxx.java, (except the ones from the standard Java library). So the above example makes sense if the following hold:
File | Classes Used |
IO.java | -- none -- |
NoCurrentException.java | -- none -- |
Sequence.java | NoCurrentException |
examples.java | IO, Sequence |
To create an up-to-date target file, type:
Make will:
For example, the dependency graph for our running example is:
Suppose you "make examples.class", then edit Sequence.java, then "make examples.class" again. Here are the steps that make will carry out:
Things to note:
clean: rm -f *.class *~
JC = /s/std/bin/javac JFLAGS = -gand used like this:
IO.class: IO.java $(JC) $(JFLAGS) IO.javaOne reason for using variables is the same as for using named constants in a program: if you decide to change the value, you only need to make a change in one place in your Makefile. Another use for variables is to allow a value to be specified at make time. For example if the Makefile includes this rule:
test: examples.class java examples $(INPUT)then typing make test INPUT=in.data causes the program to be run with one command-line argument (the string "in.data").
examples.class: examples.java Sequence.java NoCurrentException.java IO.java javac -g examples.java Sequence.java NoCurrentException.java IO.java Sequence.class: Sequence.java NoCurrentException.class javac -g Sequence.java NoCurrentException.class: NoCurrentException.java javac -g NoCurrentException.java IO.class: IO.java javac -g IO.javaThis Makefile allows you to compile Sequence.java, NoCurrentException.java, and IO.java individually (e.g., if you want to make sure they have no errors), but when you are ready to run your program, you would simply type: make, and if any .class file is not up to date, all .java files would be recompiled.