Jérémie
Jérémie

Reputation: 1373

Makefile: building LaTeX files in subdirectories with two versions of each file

I have the following folder structure

   1st-grade-math-class/
      common/
        mystyle.sty
        mysubstyle.sty
        fonts/
          font1.ttf
          font2.ttf
          font3.ttf
      week01/
        handout.tex
        image1.pdf
        image2.pdf
      week02/
        handout.tex
        image1.pdf
        image2.pdf
      ...
      week13/
        handout.tex
      output/
        [empty]

And I would like to create a Makefile - in the best way - to do the following:

I am not sure I know how to this in any other way than manually duplicating an elementary Makefile/bash script in every subdirectory, then calling each of them one by one with a for loop.

I would appreciate help on how to build this process, ideally with a single Makefile in the root directory. Thanks.

UPDATE: I purposefully did not want to give any details about how I compile LaTeX, in case somebody has a better suggestion than my current usage. Right now I am using Latexmk (which is already a make-like wrapper of LaTeX):

If anybody has a better suggestion, I am a willing taker.

Upvotes: 1

Views: 3848

Answers (2)

Norman Gray
Norman Gray

Reputation: 12514

Technique 1. The echo foo >$@; cat $< >>$@ thing is something I've done before; I think it's reasonable.

Technique 2. Another technique is to have your .tex document, or a package file it uses, include a line like:

\InputIfFileExists{lecturenotes.config}{}{}

That allows you to make certain adjustments in a makefile, as in for example:

# any bits of configuration that should be in all the .config files
SWITCHES=\makeindex

%-notes.pdf: %.tex
        printf '$(SWITCHES)\\ExecuteOptions{sidenotes}\n' >lecturenotes.config
        TEXINPUTS=styles: pdflatex $<
        mv ${<:.tex=.pdf} $@    
        rm lecturenotes.config

%-single.pdf: %.tex
        printf '$(SWITCHES)\\ExecuteOptions{oneside}\n' >lecturenotes.config
        TEXINPUTS=styles: pdflatex $<
        mv ${<:.tex=.pdf} $@
        rm lecturenotes.config

Technique 3. A third technique for controlling LaTeX from outside is to include in your document (or in a package file):

\newif\ifdemonstrator
\expandafter\ifx\csname demonstrator\endcsname\relax
  \demonstratorfalse
\else
  \demonstratortrue
\fi
...
\ifdemonstrator
    \typeout{Demonstrator is TRUE}
\else
    \typeout{Demonstrator is FALSE}
\fi

Then call latex with:

%-plain.pdf: %.tex
    latex $<
    mv ${<:.tex=.pdf} $@

%-demo.pdf: %.tex
    latex --jobname ${<:.tex=} '\def\demonstrator{x}\input{$<}`
    mv ${<:.tex=.pdf} $@

Technique 1 is a bit of a blunt instrument, but if that's all that's needed, it's pretty lightweight.

Technique 2 is probably the most neatly engineered, but it is slightly more effort.

Technique 3 is probably the one I use most in this sort of circumstance.

Upvotes: 1

Etan Reisner
Etan Reisner

Reputation: 80931

Something like this should do what you want I believe:

OUTDIR := output

# Tell make to export this environment variable to all recipe lines it runs.
export TEXINPUTS := $(abspath common)

# Get the list of all of our week directories.
weekdirs := $(wildcard week*)
#$(info weekdirs:$(weekdirs))

# Create student output filenames from week directory names.
STUDENT_HANDOUTS := $(patsubst %,$(OUTDIR)/%-handout-student.pdf,$(weekdirs))
#$(info STUDENT_HANDOUTS:$(STUDENT_HANDOUTS))

# Create teacher output filenames from week directory names.
TEACHER_HANDOUTS := $(patsubst %,$(OUTDIR)/%-handout-teacher.pdf,$(weekdirs))
#$(info TEACHER_HANDOUTS:$(TEACHER_HANDOUTS))

# Default target depends on all output files.
all: $(STUDENT_HANDOUTS) $(TEACHER_HANDOUTS)

# Pattern rule for building pdf files.
%.pdf:
        @echo + Making $@ from $^
        @echo cd $(@D) && echo latexmx -pdf $(abspath $<)
        @echo cd $(@D) && echo latexmk -c $(abspath $<)

# Static pattern rule mapping student output files to input files.
$(STUDENT_HANDOUTS) : $(OUTDIR)/%-handout-student.pdf : %/handout.tex

# Pattern rule to generate temporary input files from original input files.
%/handout-tmp.tex: %/handout.tex
        @echo echo 'line of code' '>' $@
        @echo cat $^ '>>' $@

# Static pattern rule mapping teacher output files to (temporary) input files.
$(TEACHER_HANDOUTS) : $(OUTDIR)/%-handout-teacher.pdf : %/handout-tmp.tex

Uncomment the $(info) lines to see a bit of how the variables are put together.

This uses latexmk -c to clean up auxiliary files after creating the output files.

Upvotes: 1

Related Questions