Question: How do I get a makefile that can check an arbitrary number of *.eps and *.gp (gnuplot codes) and has a rule to build new *.eps and *.tex files from the newly edited *.gp files?
Goal:
Create a Makefile that checks if any of my chapters (.tex), plots (.eps, .tex), or gnuplot codes (.gp) have changed since last compile. Create a generic rule that executes necessary *.gp codes before compiling document.
EDIT: More details on GOAL: I would like Make to build Thesis.pdf but before doing so execute any foo.gp files that have been altered since the last build. the .gp files may be updated for a number of reasons including changing of an axis label, a legend entry, added data...
Background: I am writing my dissertation and intend to make use of both LaTex and GNUplot. Due to the large number of figures it seems like a good call to put together a makefile that insures if any of my gnuplot codes (*.gp) are changed that the necessary codes are executed (and the unchanged *.gp codes are not) before compiling the latex document. I am using epslatex to generate *.eps and *.tex files (to be used with \input --- not standalone). If it's not abundantly clear from the sample code this is my first stab at a makefile.
EDIT: More details on GNUplot
gnuplot foo.gp produces foo.eps (includes all graphic portions of a plot) and foo.tex (a tex file that formats the figure and adds all necessary text). foo.gp is a script that builds a plot (much like plotting in MatLab or with MatPlotLib in python). The foo.tex file is used as \intut{foo.tex} in the latex figure environment. I will likely have in the neighborhood of 100figures that my advisor will no doubt have me edit to ad nauseum meaning I will be repeatedly be editing many different gnuplot scripts.
Dir structure:
Root Dir: ~/dissertation
Latex files Dir: ~/dissertation/text (this is also where my makefile currently is)
Gnuplot codes Dir: ~/dissertation/figures/gnuplot_codes
Gnuplot output Dir: ~/dissertation/figures/figs
Here is my code thus far:
PAPER=Thesis
CODES=$(wildcard ../figures/gnuplot_codes/*.gp) # list of all gnuplot scripts
EPSES=$(wildcard ../figures/figs/*.eps) # list of all eps files
FIGTEX=$(wildcard ../figures/figs/*.tex) # list of all associated tex files
all: $(EPSES) $(FIGTEX) $(CODES) $(PAPER).pdf
evince $(PAPER).pdf
# This is the line I can't figure out ---
# if any of the gnuplot codes are updated it runs all of them
$(EPSES) $(FIGTEX): $(CODES)
gnuplot $(CODES)
# compiles the latex document using latexmk
$(PAPER).pdf: $(PAPER).tex $(EPSES) $(FIGTEX) $(CODES)
latexmk -latex="latex -interaction=nonstopmode" -use-make $<
dvips $(PAPER).dvi -Ppdf
ps2pdf $(PAPER).ps
# This catches any missing *.eps files thrown back from latexmk
# I feel like I should have a way of checking before
# running $(PAPER).pdf rule
../figures/figs/%.eps: ../figures/gnuplot_codes/%.gp
gnuplot $<
# same as the rule above but for *.tex
../figures/figs/%.tex: ../figures/gnuplot_codes/%.gp
gnuplot $<
# this cleans all the latex files
clean:
latexmk -CA
We'll start with the list of existing gp files:
CODES=$(wildcard ../figures/gnuplot_codes/*.gp)
So far, so good. This list tells us which gp files exist, and therefore which eps and tex files can be built. (We don't care which ones already exist.)
EPSES=$(patsubst ../figures/gnuplot_codes/%.gp,../figures/figs/%.eps, $(CODES))
FIGTEX=$(patsubst ../figures/gnuplot_codes/%.gp,../figures/figs/%.tex, $(CODES))
Now for the rule to run gnuplot and produce those files. The trouble with this version:
$(EPSES) $(FIGTEX): $(CODES)
gnuplot $(CODES)
is that it makes all gp files prerequisites of every eps and tex file; change one gp file, and you must rebuild everything. So get rid of it and replace it with a pattern rule:
../figures/figs/%.eps ../figures/figs/%.tex: ../figures/gnuplot_codes/%.gp
gnuplot $<
(I don't know how gnuplot knows where to put its output files; you didn't specify, so I'll assume you have that part worked out. If you're having trouble with that, I'll be happy to help.)
Now for the Thesis.pdf rule:
# compiles the latex document using latexmk
$(PAPER).pdf: $(PAPER).tex $(EPSES) $(FIGTEX)
latexmk -latex="latex -interaction=nonstopmode" -use-make $<
dvips $(PAPER).dvi -Ppdf
ps2pdf $(PAPER).ps
I removed the prerequisite $(CODES) because it appears to be redundant. The recipe could probably be improved (and generalized to produce other pdf files) but hey, if it ain't broke...
Finally the rule that runs the show (and should come first, if you want it to be the default):
all: $(EPSES) $(FIGTEX) $(CODES) $(PAPER).pdf
evince $(PAPER).pdf
Unless evince actually uses the gp, eps and tex files, we can do without those prequisites:
all: $(PAPER).pdf
evince $<
Give all that a try.
Related
I want to let makefile manage the compilation of figures with metapost.
The source file is file.mp. This generates .mps files file.1, file.2 etc. that are then converted to file-1.pdf, file-2.pdf etc.
Here are my rules:
export TEX = latex
%: %.1
mptopdf $*
%.1: %.mp
mpost $*
So that when I run make file it creates all the files.
However, I am not satisfied with this solution. Namely, I'd like to be able to let only one of the files be compiled (say file-2.pdf) by entering make file-2.
Unfortunately, I don't know how to write the rule for this, although I suspect it might be trivial.
I thought the problem could be solved by extracting the number from the file name given in the command line (i.e. extract 2 from file-2) but it is not clear to me how to do it either.
I'm trying to make a make file for a static page generator, and I'm using jinja and pandoc so far, and the idea is to have a file structure as such
.
|-content
|-public
|-templates
|-Makefile
VPATH=public
TARGETS=$(find content -regex ".*(htm|md)" | sed -e "s/md$/htm/g;s/^content/public/g")
all: $(TARGETS)
#echo fullbuild
public/%: content/%
content/%.md:
# Pandoc script
pandoc -i $# -o ${${#:.md=.htm}:content=public}
content/%.htm:
# Jinja Script
The problem I'm having (At least I think that's it) is that according to me the syntax is
# For a final result
target: dependency
commands
# A rule for dependency
dependency:
commands
My dependencies are in the content dir and my targets are in the public dir that may or may not exist yet, and almost all the files I generate will be htm files, and in that case if the target is public/some/route/to/file.htm the dependency will be any of this two content/some/route/to/file.(htm|md).
I can easily generate by walking the content dir, and changing extensions.
How should I write the rules properly, so
- Make knows where to "watch" for changes every time I do a make, because right now it points that every file is up to date
- How do I indicate properly the dependency of a file to it's content file.
This rule:
public/%: content/%
does nothing because pattern rules without recipes delete existing pattern rules, they don't define new pattern rules.
It's very simple, you should write two rules like this:
public/%.htm: content/%.md:
# Pandoc script
pandoc -i $< -o $#
public/%.htm: content/%.htm
# Jinja Script
Here's a hint: whenever you're writing a makefile recipe and you discover that you need to create a target which is different than exactly $#, unmodified, immediately stop what you're doing and back up: you've taken a wrong turn.
We need to modularise some of our lab documents so that standard pieces of text can be kept in one place (a library of test methods), and which we can pull in as necessary (test method descriptions, boiler plate terms and conditions etc).
I have had a look at bookdown but it seems over-complex for what we need to do. I know that I could use the m4 macro processor to pull in multiple .Rmd files using a Makefile, but our staff are used to using rstudio to build their documents.
i.e., I can do this in the top level document:
changequote([', ]')
undivert([../../Library/testmethod1summary.Rmd])
and use the Makefile to preprocess the top-level file and include all subsequent files. I've done something like this with pandoc previously:
%.pdf: %.md
m4 $< > _tmp.md
pandoc _tmp.md -o $#
Is there any way to add the m4 program into the rstudio build pipeline so that you can use the usual rstudio knitR commands (SHIFT-CTRL-K or SHIFT-CTRL-B) ?
Pete
Pretty new to GNU Make. This is a less complex example of something more general I have been trying to get to work.
I have many input files that have similar name format .txt, and I have a shell script that will take the input file and generate an output of the same name but with a different extension .wc. I have written the following Make file.
# name of dependencies
SRC = $(wildcard *.txt)
# get name of targets (substitute .wc for .txt)
TAR = $(SRC:.txt=.wc)
all: $(TAR)
%.wc: %.txt
sh word_count.sh $<
This runs fine, and will generate all the .wc output files. However, if I modify one of the input(dependency) files, they are all rebuilt. So the question is; what is the best way to get GNU Make to only process the modified .txt files in the directory?
This question is based on another question of mine here: Getting basename and notdir to work in prerequisite (dependency) list.
I'm using a Makefile to generate some figures automatically and
efficiently.
My figures are generated in ../thesis/figures using Octave .m
files that are in the current directory where the Makefile also is.
Each .m file, e.g. figure1.m, may generate several figures, e.g.
figure1.p1.tex and figure1.p2.tex (and their dependecies, which
are also generated by figure1.m). These .tex files are then to be compiled using LaTeX (a single run of pdflatex figure1.p1.tex suffices in this case; so, there is no need for latexmk or other alternatives).
The Makefile I have so far is
OCTAVE = octave --jit-compiler --no-gui --quiet
PDFLATEX = pdflatex
FIGDIR = ../thesis/figures
TEXTARGETS = $(wildcard $(FIGDIR)/*.tex)
.PHONY: figures
figures: $(TEXTARGETS)
.SECONDEXPANSION:
$(TEXTARGETS): %.tex : $$(basename $$(notdir %)).m
$(OCTAVE) $<
$(PDFLATEX) $#
A dry run with make -n shows me
octave --jit-compiler --no-gui --quiet figure1.m
pdflatex ../thesis/figures/figure1.p1.tex
octave --jit-compiler --no-gui --quiet figure1.m
pdflatex ../thesis/figures/figure1.p2.tex
make: *** No rule to make target `figure2.m', needed by `../thesis/figures/figure2.tex'. Stop.
There are two issues here:
1) Both figure1.p1.tex and figure.p2.tex are generated by the first run of figure1.m by octave. Is there a way to treat all targets with the same basename (or other pattern) as a prerequisite as one, so that there is no more than one invocation of octave per .m file?
2) figure2.tex was made using some other means than an .m file. How can I tell make to ignore a rule if its prerequisite does not exist. I know how to do that for an explicit prerequisite:
target: prereq
recipe
prereq:
But what to do in this case with the prerequisite being derived from the target's name?
GNU make can be taught that multiple targets are created by one command invocation by using a pattern rule for those targets.
From Pattern Rule Examples:
This pattern rule has two targets:
%.tab.c %.tab.h: %.y
bison -d $<
This tells make that the recipe ‘bison -d x.y’ will make both x.tab.c and x.tab.h. If the file foo depends on the files parse.tab.o and scan.o and the file scan.o depends on the file parse.tab.h, when parse.y is changed, the recipe ‘bison -d parse.y’ will be executed only once, and the prerequisites of both parse.tab.o and scan.o will be satisfied. (Presumably the file parse.tab.o will be recompiled from parse.tab.c and the file scan.o from scan.c, while foo is linked from parse.tab.o, scan.o, and its other prerequisites, and it will execute happily ever after.)
So you could use something like
figure1.%1.tex figure1.%2.tex: figure1.m
$(OCTAVE) $<
but to do that for N output files where N is variable would require generating an included makefile that pulled that information out of the .m file (or similar).
If a file exists that matches a target but no matching prerequisite file is found make will just use the file it found and ignore the rule (the rule doesn't apply). You shouldn't have to do anything for that.
If, however, the file would otherwise match the rule (but you don't want make to follow the rule for that file) then you can cancel just that application by giving that file an explicit target. Like this.
figure2.tex: ;