0

This is the first time that I use GNU make to try to do something a bit less basic. I'd like the default target of a Makefile to look for any one of a number of matching filenames, a naming scheme for what I consider to be root tex files, expressed like this:

#!/usr/bin/env bash
# this is just a sketch, I know this is inaccurate
# and simplified by make's standard...

# mainfiles := main letter report course
mainfiles=(main letter report course)

_readable(){
  if ([ -f "$1" ] && [ -r "$1" ]); then
    return 0
  fi
  return 1
}

# how to make all of these existing targets using GNU make?
# all: $(patsubst %, %.tex, $$(mainfiles))
all() {
  for base in $mainfiles[@]; do
    if _readable "${base}.tex"; then
      latexmk -pdfxe "${base}.tex"
    fi
  done
}

# clean:
#   latexmk -c
clean(){
  latexmk -c
}

I'm unsure how to turn this into a makefile.

edit:

@G-Man pointed out that my question was unclear at best. Indeed I was in a hurry, and I don't exactly know what I want. I guess want to be lazy, and use :make instead of the fancy autocompile plugins from vim.

The point is that I used to edit a JOBNAME variable in a generic Makefile that relies on latexmk for all of my (la|xe|lua)tex projects. When I open either of the non-existing files main.tex letter.tex course.tex etc in vim, I have it trigger an autocommand to read in a corresponding skeleton file, copy over my generic Makefile and run git init if there's no .git folder. Usually I only have one of those .tex files in a folder, but there could be more of them.

I want a makefile because of a precompilation step (using mylatexformat), some more granular cleaning commands and something like a FILTER = 2>&1 | sed -n '/^\(Running\|Package\|Beginning\|Underfull\)/p;/^! /,$$p' that I can prepend to the compiler commands. The precompilation step, for example, checks @if ((grep -c endofdump $(TMP)/$(JOBNAME).tex== 1 )); then ....

My question is to be understood in a lazy attempt to avoid having to specify JOBNAME, so that any of the files main.tex letter.tex course.tex etc are treated with the same dependencies, possibly an rsync and a precompilation step that perform checks, and a compilation step that requires $JOBNAME.pdf to be made.

I use curly braces in ${mainfiles[@]} for what I think is good practice. I included the -f and -r test because I assume that make checks this, too.

Anyway, @meuh's answer was helpful, but I revisited my use of make, in that I think it remains a better choice to just edit JOBNAME because of flexibility and future use. I now change it with the power of vim (see my vim repo on github)

  • So basically you want to have a make rule which applies to all existing files out of a list of file names, correct? – nohillside Sep 20 '18 at 18:43
  • 2
    That is bash, not make. Can you explain what you want to do? Just creating something form TeX files should be straight forward. – RalfFriedl Sep 20 '18 at 18:44
  • (1) Are you trying to generate main.pdf, letter.pdf, report.pdf, and course.pdf from the corresponding .tex files?  Are you talking about using make because you don’t want to run latexmk over and over again on a .tex file that hasn’t changed?  What do you want to do about files that don’t exist?  We can’t read your mind, and people who are highly knowledgeable about make might know little or nothing about latexmk.  Please explain (in English sentences) what you are trying to accomplish in your question.  … (Cont’d) – G-Man Sep 24 '18 at 23:26
  • (Cont’d) …  (Please do not respond in comments; edit your question to make it clearer and more complete.)   … (Cont’d) – G-Man Sep 24 '18 at 23:26
  • (Cont’d) …  (2) I understand that you are, essentially, using the above bash script as pseudo-code to describe the functionality that you want. But, for future reference,  (2a) you can say if [ -f "$1" ] && [ -r "$1" ] (you don’t need the parentheses),  (2b) if [ -r "$1" ] is probably good enough (unless you’re concerned that you might someday have a directory or a dangling symbolic link called main.tex),  (2c) you can say "$base.tex" (you don’t need the curly braces here), and  (2d) you need curly braces in ${mainfiles[@]}. – G-Man Sep 24 '18 at 23:26
1

This is not a particularly good use of make, as there are no dependencies, but perhaps you are going to add them later, so here is a possible start:

MAINFILES = main letter report course
T = $(addsuffix .tex,$(MAINFILES))

default: ${T}
${T}:
        @if [ -f "$@" -a -r "$@" ]; then latexmk -pdfxe "$@"; else :;fi
clean:
        latexmk -c
.PHONY: ${T} clean

The default target is main.tex etc. To build that file or the others there are no dependencies, so the one-line shell script is run to do the test for file existence and readability, then the wanted command is run. The else part is so that make does not stop with an error if the file does not exist.

There is a complication needing a .PHONY target, otherwise when the files exist make will see there is no dependency and will do nothing. This applies to the clean target too, in case you have a file called clean in the directory.

  • Won't that re-make every target, even if it's already up to date? – Toby Speight Sep 28 '18 at 7:36
  • @TobySpeight I agree, but that seems to be what the OP wants, and is what the script version does. As I said, there are no dependencies. – meuh Sep 28 '18 at 7:42
0

It sounds like you just need a simple Makefile that knows how to make PDF from TeX:

all: $(patsubst %.tex,%.pdf,$(wildcard *.tex))

%.pdf: %.tex
        latexmk -pdfxe $<

.PHONY: all
.DELETE_ON_ERROR:
  • Thanks, but I'd like to traverse directories and I want only the source files from my list to be compiled, which then creates its .pdf equivalent in the same directory. There could be *.tex files that are meant to be included in the source of the root file, or standalone files that are compiled manually only once. – Bart Sep 27 '18 at 17:54
  • That's fairly easy to arrange - just change the $(wildcard *.tex) in the all rule to match the files you're interested in - probably using $(shell find ...), I expect. – Toby Speight Sep 28 '18 at 7:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.