1

I have a latex file including a lot of files which are initially not present but which are created in the course of the latexmk run.

\documentclass{article}
\usepackage{functional}
\usepackage{import}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{transparent}
\usepackage{listings}

...

\begin{document}

% \lstinputlisting[language=tex, basicstyle=\tiny, % breaklines, lastline=25, % float, captionpos=b, label={lst:ptx}, % caption={The ptx-file for a fig-file}]{F4_01fig2dev.ptx}

\fileIfExistTF{F4_01fig2dev.ptx}{x\lstinputlisting{F4_01fig2dev.ptx}}{\input{F4_01fig2dev.ptx}} %\lstinputlisting{F4_01fig2dev.ptx} \import{}{F4_01fig2dev.ptx} %\import{}{F4_04mp2mps.ptx}

\import{}{F4_03someGnuplot.ptx}

\includegraphics{F4_05someMetapost.mps}

%\import{}{F4_06svg2pdf.ptx}% \def\svgwidth{0.5\textwidth}% \import{}{F4_07someSvg.ptx}

\end{document}

Seemingly, latexmk runs lualatex until the first file to be included is not present. It ends with a fatal error but goes on creating the first included file. Then it runs lualatex second ending up in the second fatal error because of the second missing file. Again in some rule this is created and that way it goes on.

This causes one run more than there are files to be included. Additional runs may be needed to stabilize.

I think this is not satisfying. How to solve this? I wonder whether it is possible to proceed completely different? Or to make lualatex not stop for each missing file? So the number of lualatex runs does not depend on the number of included files.

Based on suggestions below, I modified my solution: In front of \begin{document} I added

\usepackage{functional}
\usepackage{letltxmacro}
\LetLtxMacro\latexlstinputlisting\lstinputlisting
\renewcommand{\lstinputlisting}[2][]{\fileIfExistTF{#2}{\latexlstinputlisting[#1]{#2}}{\typeout{No file #2.}}}
\LetLtxMacro\lateximport\import
\renewcommand{\import}[2]{\fileIfExistTF{#2}{\lateximport{#1}{#2}}{\typeout{No file #1#2.}}}
\LetLtxMacro\latexincludegraphics\includegraphics
\renewcommand{\includegraphics}[2][]{\fileIfExistTF{#2}{\latexincludegraphics[#1]{#2}}{\typeout{No file #2.}}}

For this special file, the number of runs of lualatex is really reduced. But I am not content. Redefine seems quite dangerous. For example, redefining \input naively seems to affect \includegraphics.

Even worse, \input can be used with a file xxx.tex without ending. Accordingly for \includegrapics. With this normal usage, the current solution does not work.

Any suggestions?

Maybe my .latexmkrc file is helpful

#!/usr/bin/env perl

to create pdf via lualatex

#$pdflatex = 'lualatex -file-line-error %O %S';

PDF-generating modes are:

1: pdflatex, as specified by $pdflatex variable (still largely in use)

2: postscript conversion, as specified by the $ps2pdf variable (useless)

3: dvi conversion, as specified by the $dvipdf variable (useless)

4: lualatex, as specified by the $lualatex variable (best)

5: xelatex, as specified by the $xelatex variable (second best)

$pdf_mode = 4;# specifies creation of pdf via lualatex

If additional parameters must be passed to lualatex

#'svg' package.

It converts raw SVG files to the PDF+PDF_TEX combo using InkScape.

$lualatex = "lualatex --shell-escape";

note that -recorder is implicitly added

$latex2pdfOptions = "-interaction=nonstopmode -synctex=1 -shell-escape"; $lualatex = "lualatex $latex2pdfOptions %O %S";

#$postscript_mode = $dvi_mode = 0;

to configure bibtex

$bibtex_use=2;

this cannot be done according to the according latex maven plugin,

because the according parameter maxNumReRunsLatex may be set to -1

which signifies an infinite number of runs.

$max_repeat=30;

default are tex and eps, but could also be pdf and ptx and mps

Currently, all those files are given with explicit endings,

so no extensions to be added.

#add_input_ext('');

It is what it seems to be: clean inludes what was generated by cus

$cleanup_includes_cusdep_generated = 1; $cleanup_includes_generated = 1;

#$makeindex = 'makeindex %O -o %D %S'; # the default

TBD: clarify: xdv and dvi seem to be internal.

maybe missing other extensions in conjunction with synctex

$clean_ext .= " %R.synctex.gz";

bbl does not work

#@generated_exts = (@generated_exts, 'lol', 'bbl', 'glo', 'ist') #print "Hello!" #foreach (@generated_exts) { #print "Generated exts: $_\n"; #} #print "clean_ext\n";

Here @generated_exts is ('aux', 'fls', 'log', # generated by latex already

'toc', 'lof', 'lot', 'out', # generated by latex conditionally

'idx', 'ind', 'blg', 'ilg', # concerning indices

# strange enough: nothing for bibtex

'xdv', 'bcf'

extensions ext to be deleted by latexmk -c

Note that the file names are %R.ext.

this may cause problems with extensions containing a dot.

Also this is not general enough

if the generated file deviates from %R by more than an extension.

In this case, use $clean_ext$

Here, $clean_ext is empty.

list of listings, whereas lof and lot are already present.

push @generated_exts, "lol"; push @generated_exts, "dvi", "xdv";

for beamer class

push @generated_exts, "nav", "snm", "vrb";

why are .ist and xdy not under generated_exts?

note that currently, either %R or what is present is the extension only!

this does not make sense very much.

$clean_ext .= " stateMachine.log"; does not work, because stateMachine.log is the extension!

should be under indexing

$clean_ext .= " %R.ist %R.xdy %R-.ind %R-.idx %R-.ilg %R-.ind";

add_cus_dep('fig', 'ptx', 0, 'fig2dev'); sub fig2dev { $file = $_[0]; print("$file"); rdb_add_generated("$file.eps", "$file.pdf", "$file.ptx"); my $GenOptions = ""; my $PtxOptions = ""; my $PdfEpsOptions = ""; print("create from $file.fig"); rdb_add_generated("$file.ptx", "$file.pdf", "$file.eps"); #fig2dev -L pstex <fig2devGenOptions> <fig2devPdfEpsOptions> xxx.fig xxx.eps
#fig2dev -L pdftex <fig2devGenOptions> <fig2devPdfEpsOptions> xxx.fig xxx.pdf
#fig2dev -L pdftex_t <fig2devGenOptions> <fig2devPtxOptions> -p xxx xxx.fig xxx.ptx

my $ret1 = system("fig2dev -L pstex $GenOptions $PdfEpsOptions $file.fig $file.eps"); my $ret2 = system("fig2dev -L pdftex $GenOptions $PdfEpsOptions $file.fig $file.pdf"); my $ret3 = system("fig2dev -L pdftex_t $GenOptions $PtxOptions -p $file $file.fig $file.ptx");

return ($ret1 or $ret2 or $ret3); }

add_cus_dep('gp', 'ptx', 0, 'gnuplot'); sub gnuplot { $file = $_[0]; print("create from $file.gp"); rdb_add_generated("$file.ptx", "$file.pdf", "$file.eps"); my $nuplotOptions = ""; my $ret1 = system("gnuplot -e &quot;set terminal cairolatex pdf $gnuplotOptions;
set output '$file.ptx';
load '$file.gp'&quot;");

my $ret2 = system("gnuplot -e &quot;set terminal cairolatex eps $gnuplotOptions;\

set output '$file.ptx';\

load '$file.gp'&quot;");

return $ret; }

metapost rule from http://tex.stackexchange.com/questions/37134

#add_cus_dep('mp', 'mps', 0, 'mpost'); add_cus_dep('mp', 'mps', 0, 'mpost'); sub mpost { my $file = $_[0]; print("create from $file.mp"); rdb_add_generated("$file.mps", "$file.fls", "$file.log"); my ($name, $path) = fileparse($file); pushd($path); my $return = system("mpost -interaction=nonstopmode -recorder -s prologues=2 -s 'outputtemplate=&quot;%j.mps&quot;' $name"); popd(); return $return; }

add_cus_dep('svg', 'ptx', 0, 'inkscape'); sub inkscape { my $file = $_[0]; print("create from $file.svg"); rdb_add_generated("$file.ptx", "$file.pdf"); my $ret1 = system("inkscape -D --export-filename=$file.pdf --export-latex $file.svg "); #my $ret2 = system("inkscape -D --export-filename=$file.eps --export-latex $file.svg "); #use File::Copy;

This works only for pdf, not for eps.

#unlink($file.pdf_tex) or die "cannot unlink $file.pdf_tex"; rename("$file.pdf_tex", "$file.ptx");# or die "cannot move $file.pdf_tex"; return $ret1;# or $ret2; }

graphics for xfig (not appropriate for mixed tex/pdf)

add_cus_dep('fig', 'pdf', 0, 'fig2pdf');

sub fig2pdf {

system( "fig2dev -Lpdf &quot;$[0].fig&quot; &quot;$[0].pdf&quot;" );

}

use splitindex

$makeindex = 'internal splitindex';

sub splitindex {

Use splitindex instead of makeindex.

The splitindex programe starts from an .idx file, makes a set of

other .idx files for separate indexes, and then runs makeindex to

make corresponding .ind files.

However, it is possible that the document uses the splitindex

package, but in a way compatible with the standard methods

compatible with makeindex, i.e., with a single index and with the

use of the \printindex command.

Then we need to invoke makeindex.

In addition, latexmk assumes that makeindex or its replacement makes

an .ind file from an .idx file, and latexmk gives an error if it

doesn't exist, we need to make an .ind file.

Both problems are solved by running makeindex and then splitindex.

Note: errors are returned by makeindex and splitindex for things

like a missing input file. No error is returned for lines in an

input file that are in an incorrect format; they are simply

ignored. So no problem is caused by lines in the .idx file

that are generated by splitindex in a format incompatible with

makeindex.

my $ret1 = system( "makeindex", $$Psource ); my $ret2 = system( "splitindex", $$Psource ); return $ret1 || $ret2; }

add_cus_dep( 'acn', 'acr', 0, 'makeglossaries' ); add_cus_dep( 'glo', 'gls', 0, 'makeglossaries' ); push @generated_exts, 'glo', 'gls', 'glg'; push @generated_exts, 'acn', 'acr', 'alg'; push @generated_exts, "ist"; # index stylefile created by the glossaries package

#$clean_ext .= " acr acn alg glo gls glg";# TBD: clarify: better in @generated_exts?

sub makeglossaries { my ($base_name, $path) = fileparse( $_[0] ); my @args = ( "-q", "-d", $path, $base_name ); if ($silent) { unshift @args, "-q"; } return system "makeglossaries", "-d", $path, $base_name; }

sub run_makeglossaries { my ($base_name, $path) = fileparse( $_[0] ); #handle -outdir param by splitting path and file, ... pushd $path; # ... cd-ing into folder first, then running makeglossaries ...

if ( $silent ) {
    # system &quot;makeglossaries -q '$base_name'&quot;; #unix
    system &quot;makeglossaries&quot;, &quot;-q&quot;, &quot;$base_name&quot;; #windows
}
else {
    # system &quot;makeglossaries '$base_name'&quot;; #unix
    system &quot;makeglossaries&quot;, &quot;$base_name&quot;; #windows
};

popd; # ... and cd-ing back again

}

!!! ONLY WORKS WITH VERSION 4.54 or higher of latexmk

#TBD: take into account: modified:

'$_[0]'->

# makeindex

@ist = glob("*.ist");

if (scalar(@ist) > 0) {

$makeindex = "makeindex -s $ist[0] %O -o %D %S";

}

glossaries new with bib2gls

push @generated_exts, 'glstex', 'glg';

add_cus_dep('aux', 'glstex', 0, 'run_bib2gls');

sub run_bib2gls {

if ( $silent ) {

my $ret = system "bib2gls --silent --group $_[0]";

} else {

my $ret = system "bib2gls --group $_[0]";

};

my ($base, $path) = fileparse( $_[0] );

if ($path && -e "$base.glstex") {

rename "$base.glstex", "$path$base.glstex";

}

# Analyze log file.

local *LOG;

$LOG = "$_[0].glg";

if (!$ret && -e $LOG) {

open LOG, "<$LOG";

while (<LOG>) {

if (/^Reading (.*.bib)\s$/) {

rdb_ensure_file( $rule, $1 );

}

}

close LOG;

}

return $ret;

}

$pythontex = 'pythontexW %R';#'pythontexW %O %R'; push @generated_exts, "pytxcode", "plg"; push @generated_exts, "depytx", "dplg";

$clean_ext .= " pythontex-files-%R/* pythontex-files-%R"; #$extra_rule_spec{'pythontex'} = [ 'internal', '', 'mypythontex', "%Y%R.pytxcode", "%Ypythontex-files-%R/%R.pytxmcr", "%R", 1 ]; $extra_rule_spec{'pythontex'} = [ 'internal', '', 'mypythontex', "%R.pytxcode", "pythontex-files-%R/%R.pytxmcr", "%R", 1 ];

sub mypythontex { my $result_dir = $aux_dir1."pythontex-files-$$Pbase"; my $ret = Run_subst( $pythontex, 2 ); rdb_add_generated( glob "$result_dir/*" ); #my $fh = new FileHandle $$Pdest, "r"; open( my $fh, "<", $$Pdest ); if ($fh) { print "path: $ENV{PATH}"; while (<$fh>) { if ( /^%PythonTeX dependency:\s+'([^']+)';/ ) { print "Found pythontex dependency '$1'\n"; rdb_ensure_file( $rule, $aux_dir1.$1 ); } } undef $fh; } else { warn "mypythontex: I could not read '$$Pdest'\n", " to check dependencies\n"; } return $ret; }

for htlatex

push @generated_exts, "4tc", "4ct", "tmp", "xref", "css", "idv", "lg";

TBD: for -C remove also html and xhtml

TBD: check that this plugin also removes all these extensions.. think of lg.

biblatex

push @generated_exts, "run.xml";# does run.xml work?

$clean_ext .= " %R-blx.bib";

  • 1
    It sounds very wrong to force an error to trigger some latexmk processing. Write the line latexmk is looking for manually to the log if the file doesn't exist. – Ulrike Fischer May 12 '23 at 05:54
  • @ulrike: this is a misunderstanding. I do not force. – user2609605 May 13 '23 at 21:39
  • 1
    sure you are forcing it by loading a file that doesn't exist. If you know that they don't exist, you can test that without triggering an error. – Ulrike Fischer May 13 '23 at 21:42
  • ok. well depends what forcing means. What is the alternative? How can latexmk find out which dependent files shall be created? By running lualatex or that like? in some other way? if with lualatex: how without forcing an error because the files do not exist? I know for some kinds of files there are ways to do within one lualatex run. – user2609605 May 13 '23 at 21:46
  • @ulrike: I know how to test existence of a file.. Maybe.. just writing it into the fls file. Is this possible programmatically???

    What else is your idea?

    – user2609605 May 13 '23 at 21:47
  • as I wrote above: write to the log whatever latexmk needs. – Ulrike Fischer May 13 '23 at 22:37
  • @ulrike: Do you answer with the intention to be helpful? – user2609605 May 14 '23 at 20:55
  • @user2609605 "Redefine seems quite dangerous." You don't need to redefine anything? Just define your own \customlstinputlisting etc. and use it instead of the original \lstinputlisting. – user202729 May 14 '23 at 23:52

1 Answers1

2

There's a simple solution: replace

\input{F4_01fig2dev.ptx}

with

\wlog{No file F4_01fig2dev.ptx.}

It does exactly what it reads -- write that string in the log file, which will be processed by latexmk.

An alternative is \typeout which will usually type in both log file and the terminal.

(as hinted by Ulrike in the comment, but it does take some effort to figure out what "latexmk needs" exactly other than by reading through the source code...)

Another possible magic string is ! LaTeX Error: File F4_01fig2dev.ptx not found.} as normally printed by \input, however there isn't really a "built-in" function to print out this string.

snip from source2e


Admittedly this trick is not very satisfying as in it hard codes the magic string "No file", but it's what many packages do...

  • there's a similar trick suggested by latexmk documentation

    latexmk documentation

  • pythontex source code:

    pythontex source code

  • LaTeX source code:

    LaTeX source code

  • A handful of answers suggesting the trick: 1 2 3 4 5 6

user202729
  • 7,143
  • Actually this is borderline duplicate of the question [1] linked in the answer except that in this case OP does not explicitly want to \input the other file. – user202729 May 14 '23 at 09:20
  • I took your solution into account modifying my question. I tried to develop a solution out of your hints. But so far I did not succeed. – user2609605 May 14 '23 at 23:07