For more details, and talks in past semesters, consult the full schedule of talks.
Past topics can (and should) be repeated occasionally. In addition, here are some topics people might like to hear about:
To give a talk, please contact swig@math.arizona.edu.
make utility (available on all departmental LINUX
systems).
Make is a tool that is designed to help you
manage software projects; here, project means a set of
files that depend on one another in some way. The canonical
example of a project is a set of C (or FORTRAN or whatever)
source files and associated header files. The .c files depend
on the .h files, .o files depend on .c files, and the final
executable depends on the .o files.
In this document, we'll consider a slightly different example: a LaTeX project. For concreteness, suppose we have four files:
gnuplot> set term post portrait monochrome "Times-Roman" 18 gnuplot> set size .5,.5 gnuplot> set output "fig.ps" gnuplot> plot "fig.dat" with linespoints gnuplot> quitThe figure looks like this:
Make is designed to automatically run commands
like these for you whenever necessary. What does "necessary"
mean? For example, if you want the most up to date diss.dvi,
you will need to run LaTeX on diss.tex if you have modified
diss.tex since the last time you LaTeX'ed it. If you need
diss.ps, it may be necessary to run LaTeX on diss.tex, run
gnuplot to rebuild fig.ps, and finally run dvips to get the
latest diss.ps. For nontrivial projects it is annoying (if
not impossible) to keep track of these details in your head;
just imagine having to keep track of 10 TeX files, 20 data
files, and 10 figures! If you rerun your Matlab code and
update three of the data files, which of the 10 figures needs
to be rebuilt?
Make decides which commands to run based on the
modification times of the files involved and a project
description file (provided by you) that describes the
dependency relationships among your files. When you run
make, it reads this input file (named "Makefile"
or "makefile", usually) and checks the timestamps on the
files required to build your project. It then executes the
minimum number of commands necessary to bring everything up
to date.
For projects consisting of more than a couple of files, it
can be more efficient to spend thirty minutes writing a
makefile than to type the same commands over and over again,
all the while trying to remember if figure 7 uses data3.out
in any way. Your investment in make pays off
when you type
In the rest of this document, we'll look at various ways to
automate and simplify the build process with
make.
1: ########################################
2: # Makefile -- version 0
3:
4: # diss.dvi depends on diss.tex
5: diss.dvi: diss.tex
6: make fig.ps
7: latex diss.tex
8:
9: # fig.ps depends on fig.dat and fig.gnu
10: fig.ps: fig.dat fig.gnu
11: gnuplot < fig.gnu
12:
13: # diss.ps depends on diss.dvi and fig.ps
14: diss.ps: diss.dvi fig.ps
15: dvips -o diss.ps diss.dvi
First, a "#" denotes a comment; anything from a "#" to the
end of the current line is ignored by make.
This Makefile defines three explicit rules (there are
also implicit rules). Line 5 says that the file diss.dvi
depends on diss.tex (the colon can be read "depends on").
Lines 6 and 7 tell make what commands to run if
diss.dvi is older than diss.tex. In this case, we rebuild the
figure and run LaTeX on diss.tex. In make's
terminology, the target diss.dvi has the
prerequisite or dependent diss.tex. This rule
is called explicit because all of the filenames are spelled
out in full.
Why do we need to rebuild the figure? Diss.tex includes the figure as follows:
Lines 10 and 11 are similar: they tell make how
to build the figure fig.ps from fig.dat and fig.gnu (fig.gnu
contains the commands we entered at the gnuplot prompt
eariler). To regenerate the figure, we run gnuplot and tell
it to read commands from fig.gnu. Fig.gnu in turn tells
gnuplot to send PostScript output to the file fig.ps. Note
that make will rebuild the figure for two
reasons: because fig.dat has changed or because
fig.gnu has changed. If we rerun the code that produced
fig.dat, make will automatically rebuild fig.ps.
If, on the other hand, we modify fig.gnu, make
will also rebuild fig.ps. In other words, having fig.ps
depend on both files causes the figure to be rebuilt when
Finally, lines 13 and 14 tell make that diss.ps
depends on both diss.dvi and fig.ps. To build diss.ps, we run
dvips with the -o <output_file> option; otherwise, the
PostScript output gets sent to the printer, which is not
(necessarily) what we want.
So how does all this work? Well, let's suppose you start with only diss.tex, fig.dat, and fig.gnu. If you type
make will execute the following:
gnuplot < fig.gnu
latex diss.tex
dvips -o diss.ps diss.dvi
Make looks at the diss.ps rule and sees that it
needs to build diss.dvi first. The rule for diss.dvi causes
make to run another copy of make to build
fig.ps. Since fig.ps doesn't exist, the second copy of
make runs gnuplot and exits. Back in the diss.dvi
rule, the original make runs LaTeX to produce
diss.dvi. Having done all this, make continues
scanning the diss.ps rule. The next prerequisite is fig.ps.
Make looks at the timestamps on fig.dat, fig.gnu,
and fig.ps, and decides that fig.ps is up to date (we just
built it), so there's nothing to do. Now that all of the
prerequisites of diss.ps are in place, make runs
dvips to produce diss.ps.
What happens if you type "make diss.ps" again?
Make issues the message
indicating that nothing needs to be done (since all of the prerequisites of diss.ps are older than diss.ps).
Now, suppose that you edit fig.dat and remove an "outlier" data point. If you type
make executes the following commands:
gnuplot < fig.gnu
dvips -o diss.ps diss.dvi
Instead of running "make fig.ps" in line 6, we could have
made diss.dvi depend on fig.ps on line 5. If you use LaTeX2e,
doing this would ensure that you would always have the most
up to date figures in xdvi. However, it would also mean that
make would have also run LaTeX above, which,
strictly speaking, isn't necessary.
There are a few format restrictions that you should observe in your Makefiles. Lines that state dependencies (like line 5) should not have any whitespace at the beginning of the line. The colon should be followed by a TAB (even when there are no dependents), and the dependents can be separated by arbitrary whitespace. If the list of dependents (or targets) is longer than one line, you can use the line continuation character, "\" to split the list across multiple lines; for example,
diss.dvi: diss.tex ch1.tex ch2.tex \
ch3.tex ch4.tex ch5.tex ch6.tex
latex diss
The "\" must be the last character on the line. Lines
that list commands to run (like lines 6 and 7) must begin
with a TAB character (this is how make tells where the
list begins and ends). There are actually many versions of
make; this list of rules takes the low road and will
hopefully keep you out of trouble.
make
will rebuild a target for two reasons:
The commands for "dummy targets" do not actually create the
target; instead, they perform some other action. Since the
target never exists, make always executes
these commands. This is best illustrated by example.
1: ########################################################################
2: # Makefile -- version 1
3:
4: all: view
5:
6: diss.dvi: diss.tex
7: make fig.ps
8: latex diss.tex
9:
10: fig.ps: fig.dat fig.gnu
11: gnuplot < fig.gnu
12:
13: diss.ps: diss.dvi fig.ps
14: dvips -o diss.ps diss.dvi
15:
16: clean:
17: /bin/rm -f diss.dvi diss.aux diss.log diss.ps fig.ps
18:
19: view: diss.dvi
20: xdvi diss.dvi
21:
22: psview: diss.ps
23: ghostview diss.ps
24:
25: print: diss.dvi fig.ps
26: dvips diss.dvi
Lines 6-14 are the same as in the previous Makefile.
First, consider the dummy target "view" defined on lines 19
and 20. "View" depends on diss.dvi, and so make
rebuilds diss.dvi if necessary. The command that ostensibly
builds the file "view" instead runs xdvi on diss.dvi. The
file "view" never gets built, so any time you type
make will run xdvi for you (possibly
running LaTeX first). What if there is a file named
"view"? Then things get goofy because make uses
that file's timestamp to decide what to build. Dummy targets
(by definition) never exist as files.
Similarly, lines 2-26 define the dummy targets "psview" and "print", which run ghostview on diss.ps (so you can preview the final product) and print out diss.dvi, respectively. The print target also updates fig.ps so that we always the most current set of figures.
Lines 16 and 17 define a target "clean" which removes all of the files generated by LaTeX, dvips, and gnuplot. This is convenient when you want a clean slate or want to recover some disk space. It is of course important that you only remove things that can be rebuilt :-)
Line 4 gives a rule (with no commands) for the dummy target
"all". "All", in turn, depends on the dummy target "view"
(which runs xdvi). This rule also exists for convenience. If
you type "make" (or "make all") instead of "make
<target>", make builds the first target it
finds in the Makefile. If you are actively editing diss.tex,
you can view your progress by simply typing "make".
Make lets you define and use macros
(simple variables) in your Makefiles. In this section, we'll
see how to use macros to eliminate some of the repetitiveness
in the previous Makefile and construct a simple LaTeX Makefile
template.
1: ########################################################################
2: # Makefile -- version 2
3:
4: all: view
5:
6: ########################################
7: # base filename of the project
8: base=diss
9:
10: # files included by $(base).tex
11: texdeps=ch1.tex
12:
13: # list of figures -- THEY ARE ALL REMOVED BY "make clean"!!
14: # if you don't have any figures, set it to "nofigures"
15: figures=fig.ps
16:
17: ########################################
18: # put rules to build individual figures here
19:
20: fig.ps: fig.dat fig.gnu
21: gnuplot < fig.gnu
22:
23: ########################################
24: # boilerplate follows...
25:
26: texfile=$(base).tex
27: dvifile=${base}.dvi
28: psfile =$(base).ps
29:
30: # things removed by "make clean"
31: junk=$(dvifile) $(base).aux $(base).log $(figures) $(psfile)
32:
33: nofigures:
34:
35: $(dvifile): $(texfile) $(texdeps)
36: $(MAKE) $(figures)
37: latex $(texfile)
38:
39: $(psfile): $(dvifile) $(figures)
40: dvips -o $@ $(dvifile)
41:
42: clean:
43: /bin/rm -f $(junk)
44:
45: view: $(dvifile) $(figures)
46: xdvi $(dvifile)
47:
48: psview: $(psfile)
49: ghostview $(psfile)
50:
51: print: $(dvifile) $(figures)
52: dvips $(dvifile)
Line 8 defines a macro called "base" whose value is "diss".
This macro is used, for example, on lines 26 and 27. To
reference a macro, you refer to it as $(name) or ${name}.
These two lines also illustrate that macros can be used to
define other macros. Recursive macros (ones that directly or
indirectly reference themselves) are not allowed. References
to nonexistent macros are replaced with the empty string "".
Finally, macros do not have to be defined in any particular
order: make processes all macro definitions
before doing any expansions. This implies that the last
definition of a macro is the one that gets used.
How is this helpful? For simple projects, you only have to
edit lines 8, 11, 15, and tell make how to build
your figures after line 19. This Makefile assumes that you
have one main LaTeX file that \input's all of the other LaTeX
files. It also assumes that everything is in the current
directory (actually, this is a limitation imposed by
make itself).
In line 8, you give the name of your main LaTeX file, without
an extension. The Makefile uses this in lines 26-28 to
construct the specific names of .tex, .dvi, and .ps files
that go with your project. In line 11, you list the files
included by the main LaTeX file; these are used in the
dependency list to produce the .dvi file. Line 15 is a list
of figures to be automatically generated by
make, based on the rules you supply after line
19. This list is used in the dependencies for the .ps file
and for printing.
make.
There is one other new feature in this Makefile: the "$@" macro used in line 40. $@ always evaluates to the current target.