1
votes

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:

  • make sure I include the common directory properly in TEXINPUTS

  • compile the handout.tex into a PDF (using either pdflatex or xelatex) and have it in the output directory as week01-handout-student.pdf

  • compile the handout.tex with a line of LaTeX prepended to the beginning of the file (that sets a flag) into a PDF and have it in the output directory as week01-handout-teacher.pdf

  • clean everything up (the log, aux, etc. files)

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):

  • latexmk -pdf file.tex generates file.pdf
  • to add the line of code, I do a simple echo "line of code" > temp.tex and cat handout.tex >> temp.tex, then the same latexmk command
  • latexmk -c file.tex in a directory cleans all temporary files used to compile file.tex
  • TEXINPUTS is the TeX path variable, to let TeX find (in its path) the style files: I do TEXINPUTS=full-path-to/common and then export TEXINPUTS before compiling anything.

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

2
Can you provide the basic commands necessary to generate the LaTeX output you want? Is TEXINPUTS just a variable that needs to point to the common directory before running whatever latex processing command is run? Also samples of the log, aux, etc. filenames and locations? Does the cleaning need to happen automatically at generation time or is a separate clean target sufficient?Etan Reisner
@EtanReisner Thanks for your interest; I added some detail in my post. TEXINPUTS is TeX's path variable, and just needs to point to the full path of common. The log, aux, etc. files are file.log, file.aux (for "file.tex"). The tool I use already provides a convenient way to clean everything. A sufficient clean target is sufficient.Jérémie

2 Answers

1
votes

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.

1
votes

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.