I am able to iterate over pdf files (pictures) in my makefile to crop the margins. For this I am using the pdfcrop function of TexLive on Windows 10. But now I am not able to create a dependency. If a pdf file is not cropped or there is a new pdf file that is not cropped in my picture folder, pdfcrop shall crop the margins and save it with the same name in the same folder (so actually override the old pdf file). I think this might be easy, but I just can't figure out how to do this. This is my Code in the makefile.
MAIN_FILE = Dissertation
FIG_DIR = ./Bilder/Abbildungen
FIG_FILES := $(wildcard $(FIG_DIR)/*.pdf)
all: $(MAIN_FILE).pdf
$(MAIN_FILE).pdf: $(MAIN_FILE).tex $(CROP_FILES)
pdflatex $(MAIN_FILE).tex
CROP_FILES = ${FIG_FILES:%=%.crop}
$(CROP_FILES): $(FIG_FILES) # this line doesn't seem work correctly
$(foreach FIG_FILE, $(FIG_FILES), $(call CROP, $(FIG_FILE)))
define CROP
pdfcrop $(1) $(1).crop
endef
Alternative solution, which will (hopefully) check timestamp for each PDF file, and activate CROP only on updated/new files.
The cropped file is left in the same file name. If the timestamp of the '.crop' file is newer that the 'pdf' file, it means file is cropped, otherwise, PDF file will be cropped, and the '.crop' file will be touched.
MAIN_FILE = Dissertation
FIG_DIR = ./Bilder/Abbildungen
FIG_FILES := $(wildcard $(FIG_DIR)/*.pdf)
all: $(MAIN_FILE).pdf
# The '.crop' timestamp capture the time the file was cropped
CROP_FILES=${FIG_FILES:%=%.crop}
%.crop: %
pdfcrop $< $<
touch $#
$(MAIN_FILE).pdf: $(MAIN_FILE).tex $(CROP_FILES)
pdflatex $(MAIN_FILE).tex
Modification to place 'crop' files to timestamp folder
TS_DIR=ts
CROP_FILES = ${FIG_FILES:${FIG_DIR}/%=${TS_DIR}/%.crop}
${TS_DIR}/%.crop: ${FIG_DIR}/%
#mkdir -p ${TS_DIR}
pdfcrop $< $<
touch $#
Suggesting more testing, as logic is more complex. The '%.crop' target is replaced with a rule to generate them at ${TS_DIR}
If you stored the cropped file in the same name as the original PDF file, Make will not be able to tell if a specific file is cropped. As an alternative, consider naming the cropped files differently (e.g., filename.pdf.crop)
# Add '.crop' suffix to the original file name
CROP_FILES = ${FIG_FILES:%=%.crop}
# Recreate ALL CROPPED files, on changes to ANY source file
$(CROP_FILES): $(FIG_FILES) # this line doesn't seem work correctly
$(foreach FIG_FILE, $(FIG_FILES), $(call CROP, $(FIG_FILE)))
# Based on doc, 2nd parameter to pdfcrop name the output file.
define CROP
pdfcrop $(1) $(1).crop
endef
Note that this version will re-crop all PDF files when a single PDF files is added, recreated. If this is a time consuming operation, you can extend the Makefile to perform the check on each, and improve performance.
Related
I have few txt files in a directory. I want to run a shell script only on the files which have been modified. How can I achieve this through Makefile?
Have written the following part but it builds all the txt files in the directory. Would be great to get some pointers on this.
FILENAME:= $(wildcard dir/txts/*/*.txt)
.PHONY: build-txt
build-txt: $(FILENAME)
sh build-txts.sh $^
I'm guessing you want something like this:
files := $(wildcard dir/txts/*/*.txt)
dummies := $(addprefix .mod_,$files)
all:$(dummies)
$(dummies): .mod_% : %
sh build-txts.sh $^
touch $#
For any new text file, it will run the script, and create a .mod counterpart. For any non-new text file, it will check if the timestamp is newer than the .mod files timestamp. If it is, it runs the script, and then touches the .mod (making the .mod newer than the text). For any text file that has not been modified since the last make, the .mod file will be newer and the script will not run. Notice that the .mod files are NOT PHONY targets. They are dummy files who exist solely to mark when the text file was last modified. You can stick them in a dummy directory for easy cleaning as well.
If you need something where you don't want to rebuild the text files by default on a fresh checkout, or your script criteria isn't based on timestamps, you would need something a bit more tricky:
files := $(wildcard dir/txts/*/*.txt)
md5s:= $(addprefix .md5_,$files)
all:$(md5s)
.PHONY:$(md5s)
$(md5s):
( [ -e $# ] && md5sum -c $# ) || \
( sh build-txts.sh $# && md5sum $(#:.md5_=) > $# )
Here, you run the rule for all text files regardless, and you use bash to determine if the file is out of date. If the text file does not exist, or the md5sum is not correct, it runs the script, then updates the md5sum. Because the rules are phony, they always run for all the .md5sum files regardless of whether they already exist.
Using this method, you could submit the .md5 files to your repository, and it would only run the script on those files whose md5 sum changed after checkout.
(Similar question here). For every .x file in the directory I want to run a command to generate an HTML file. The command already works fine, it's the Makefile that I'm having trouble with. Here's what I came up with:
all: $(OBJECTS)
OBJECTS := $(patsubst %.x,%.html,$(wildcard *.x))
%.html: %.x
generate $< > $#
The OBJECTS variable is meant to contain all html files I need to generate. Invoking make states nothing to be done for 'all', and there are no HTML files already in the directory.
Turns out make is sensitive to the order of your variable definitions. The Makefile works when the first two lines are switched!
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.
I have a simple makefile that I use to build some latex files. The syntax looks like this:
pdf: thesis.tex chapters/a.tex chapters/b.tex chapters/c.tex
latexmk -pdf -pdflatex="pdflatex thesis.tex
open:
open thesis.pdf
The files inside chapters folder can increase further with d.tex, e.tex and may even contain subfolders f\section1.tex, f\section2.tex etc.
I manually add all the requried tex files inside my thesis.tex like this which is not a problem.
\input{chapters/a.tex}
\input{chapters/b.tex}
\input{chapters/c.tex}
\input{chapters/d.tex}
\input{chapters/e.tex}
How can I get make target pdf to depend upon any file changes inside chapters and its subdirectories?
How do I write inter task dependency in makefile. If target open depends upon target pdf, how do I write it?
open: pdf will sort-of do what you want for your second question.
Though it would be better to not use the phony pdf target for this.
Instead have a thesis.pdf: target which depends on the right prerequisites and have both pdf: thesis.pdf and open: thesis.pdf targets.
For the first question you can either use something like:
SRCS := $(shell find chapters -name '*.tex')
or use from here:
rwildcard=$(strip $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)))
SRCS := $(call rwildcard,chapters,*.tex)
and then:
thesis.pdf: thesis.tex $(SRCS)
to use that variable as the prereq.
If you wanted to get even fancier you could write a script to pull out the actual filenames from the \input{} directives in thesis.tex and use that as your SRCS variable (but that's probably not worth the effort unless you know you will have other, unrelated, .tex files).
I'm trying to produce some graphs using GNUplot with a makefile. I would like for every *.plt file in the directory to be run through GNUplot, however I can't see to get it to work.
Here's my makefile so far:
all: %.tex
%.tex: %.plt
<tab> gnuplot < $<
The recipe is working fine if I specify a .plt file individually but I want it to pick up my new plots as I produce them.
EDIT:
I think I've got it working now:
# plots all files in the folder with .plt extensions
SOURCES = $(wildcard *.plt)
TARGETS = $(SOURCES:.plt=.tex)
all: $(TARGETS)
%.tex: %.plt
gnuplot < $<
Can someone confirm whether my reasoning (as follows) is correct?
Previously I hadn't specified any files for all (I'm a little confused by %). Now assigning the variable SOURCES by picking up any .plt files using the wildcard (why doesn't it work when using .plt instead of *.plt?). Having assigned SOURCE, the TARGETS variable is then set, now all: has files specified to build. and the matching rule is now run.
all : %.tex won't work because there is no percent in the target name, in other words, it is not a patter rule.
Use wildcard function to get the list of all .plt files and add an all dependence on these files with the extension replaced by .tex:
PLT_FILES := $(wildcard *.plt)
TARGETS := $(PLT_FILES:%.plt=%.tex)
all: $(TARGET)
%.tex: %.plt
gnuplot < $<