0

I'm currently writing a large document with many included files. I'm using the command % !TEX root = main.tex at the beginning of the included files, as in the following example:

subfile1.tex:

% !TEX root = main.tex
\section{Algebra}
(...)

subfile2.tex:

% !TEX root = main.tex
\section{Analysis}
(...)

main.tex:

\documentclass{book}

\begin{document}
\include{subfile1.tex}
\include{subfile2.tex}
\end{document}

I would like to compile only the content of subfile1.tex, subfile2.tex when editing these files.

I'm wondering if there is a way to tell to the master document to compile only the calling document, via a command similar to % !TEX root = main.tex.

Ideally, I'm looking for commands such as

% !TEX \def\compileOnlyOneFile{YES}
% !TEX \def\nameFile{CURRENT_FILE}

PS: I'm using TeXShop on macOS.

8
  • Since you are using \include I would suggest that you look up what the \includeonly command does.
    – daleif
    Commented Jun 29, 2021 at 10:21
  • Thanks @daleif. I know \includeonly but I would like to be able to compile subfile1, subfile2, without modifying main.tex.
    – Colas
    Commented Jun 29, 2021 at 10:22
  • Then you should use a different approach. I see no issues in altering \includeonly in main.tex, it is simple and the editors understand it. The rest is just making things more complicated for yourself (and those who makes the editors)
    – daleif
    Commented Jun 29, 2021 at 10:35
  • Then imagine I have hundreds of subfiles and I am compiling several of them at the same time.
    – Colas
    Commented Jun 29, 2021 at 10:44
  • 1
    if you are processing multiple subfiles at the same time and want to generate separate pdf you don't want to set root to main.tex as that will mean they all make main.pdf and over-write. give each subfile its own mainfile eg subfile one has root subfile1-main where subfile1-main is just \includeonly{subfile1}\input {main} Commented Jun 29, 2021 at 11:43

2 Answers 2

1

You can write a file jobnameredirector.tex which checks

  • whether the \documentclass-command was already used and therefore redefined equal to the macro \@twoclasseserror and
  • whether \begin{document} was already processed and therefore \AtBeginDocument is redefined equal to \@onlypreamble

and performs appropriate actions in these different situations.

Via \input load that file jobnameredirector.tex in the preamble of your main.tex and right at the beginnings of your subfiles.

In case of being "inside the preamble" the command \@include can be patched to ensure that when reading sub-.aux-files takes place, with hyperref being loaded the circumstance is taken into account that destinations coming from other sub-files need to be redirected to the main.pdf where they exist.

In case of being "before the preamble" \jobname can be redirected and the real underlying mechanism for including the URL of main.pdf with cross-references coming from other sub-files can be defined.

This way compiling

  • main.tex yields a .pdf-file main.pdf where everything is \included, and thus containing everything. You also get main.log and main.aux and main.toc and main.lof and main.lot etc.
  • subfile1.tex yields a .pdf-file subfile1.pdf containing everything from main.tex whereby all \include-commands but the \include-command for subfile1.tex are ignored. Additionally you get subfile1.log and main.aux and main.toc and main.lof and main.lot etc.
  • subfile2.tex yields a .pdf-file subfile2.pdf containing everything from main.tex whereby all \include-commands but the \include-command for subfile2.tex are ignored. Additionally you get subfile2.log and main.aux and main.toc and main.lof and main.lot etc.

If you want cross-references from one file to another to work out, main.tex must have been compiled, whereby all files were included and thus all partial .aux-files subfile1.aux, subfile2.aux etc were created.

If the hyperref-package is loaded, hyperlinks created due to cross-referencing-commands and directing to destinations that in main.pdf come into being due to \includeing sub-files other than the one currently compiled and therefore not available within the .pdf-file resulting from the current compilation are directed to main.pdf, assuming that main.pdf and all subfile.pdf are in the same directory.
If this is not the case, within jobnameredirector.tex look up the line \newcommand\URLofMainFile{./main.pdf}% and change that definition so that it suits your directory-structure of .pdf-files.

Hyperlinks coming into being due to bookmarks and/or \tableofcontents/\listoffigures/\listoftables are not taken into account. Therefore when compiling sub-files you may still easily encounter warning-messages like

pdfTeX warning (dest): name{section.1.2} has been refer
enced but does not exist, replaced by a fixed one

No warranties. Try at your own risk.

main.tex

\documentclass{book}
\usepackage{hyperref}

%======================================================================
% In case of loading hyperref do this _after_ loading hyperref:
\input jobnameredirector.tex
%======================================================================

\begin{document}

\chapter{A chapter in main document}
\section{Section in main document}\label{main}

References: \ref{main}/\ref{Algebra}/\ref{Analysis}

\include{subfile1.tex}
\include{subfile2.tex}
\end{document}

subfile1.tex

\input jobnameredirector.tex
%======================================================================
\section{Algebra}\label{Algebra}
References: \ref{main}/\ref{Algebra}/\ref{Analysis}

(...)

subfile2.tex

\input jobnameredirector.tex
%======================================================================
\section{Analysis}\label{Analysis}
References: \ref{main}/\ref{Algebra}/\ref{Analysis}

(...)

jobnameredirector.tex

\edef\restoreat{\noexpand\catcode`\noexpand\@=\the\catcode`\@\relax}%
\makeatletter
\ifx\documentclass\@twoclasseserror
  % Document-Preamble / \documentclass has already been processed.
  \ifx\AtBeginDocument\@onlypreamble\else
    % \begin{document} is not reached yet.
%    \@ifpackageloaded{hyperref}\iftrue{\csname iffalse \endcsname}%
      \RequirePackage{etoolbox}%
      \providecommand\patchnewlabel[1]{}%
      \providecommand\resetnewlabel{}%
      \patchcmd{\@include}%
               {\immediate\write\@mainaux{\string\@input{#1.aux}}}%
               {%
                 \immediate\write\@mainaux{\string\patchnewlabel{#1}}%
                 \immediate\write\@mainaux{\string\@input{#1.aux}}%
                 \immediate\write\@mainaux{\string\resetnewlabel}%
               }%
               {\message{Success with patching \string\include!!!}}%
               {\message{Problem patching \string\include!!!}}%
%    \fi
  \fi
  \restoreat
\else
  % Document-Preamble / \documentclass has not yet been processed:
  \@ifdefinable\savedjobname{\edef\savedjobname{\jobname}}%
  \def\jobname{main}%
  \@onelevel@sanitize\jobname  \global\let\jobname=\jobname
  %=======================================================================
  \newcommand\URLofMainFile{./main.pdf}%
  \newcommand\patchnewlabel[1]{%
    \let\Saved@newl@bel=\@newl@bel
    \def\@newl@bel{\@newl@bel@addURL{#1}}%
  }%
  \newcommand\@newl@bel@addURL[4]{%
    \ifnum\pdfstrcmp{#1}{\savedjobname}=0 \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
    {\Saved@newl@bel{#2}{#3}{#4}}{\split@newl@bel@addURL#4{}{}{}\\{\Saved@newl@bel{#2}{#3}}}%
  }%
  \@ifdefinable\split@newl@bel@addURL{%
    \long\def\split@newl@bel@addURL#1#2#3#4#5\\#6{%
       \ifcat$\detokenize{#4}$\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
       {#6{{#1}{#2}}}%
       {%
         \expandafter\Exchange\expandafter{\expandafter{%
            \romannumeral
            \expandafter\Exchange\expandafter{\expandafter{\URLofMainFile}}{0 {#1}{#2}{#3}{#4}}%
         }}{#6}%
       }%
    }%
  }%
  \newcommand\Exchange[2]{#2#1}%
  \newcommand\resetnewlabel{\let\@newl@bel=\Saved@newl@bel}%
  \newcommand\Saved@newl@bel{}%
  %=======================================================================
  \restoreat
  \includeonly{\savedjobname.tex}%
  \Exchange{\input{\jobname.tex}}%
\fi
1

Rather than using the root comment you can make the subfiles \include themselves via \includeonly

subfile1

\ifnum\pdfstrcmp{\jobname}{subfile1}=0
\AtBeginDocument{\includeonly{subfile1}}
\def\jobname{subfile1-main}
\def\tmp{\input{main}}
\expandafter\tmp
\fi
\section{Algebra}
(...)

subfile2

\ifnum\pdfstrcmp{\jobname}{subfile2}=0
\AtBeginDocument{\includeonly{subfile2}}
\def\jobname{subfile2-main}
\def\tmp{\input{main}}
\expandafter\tmp
\fi
\section{Analysis}
(...)

main

\documentclass{book}

\begin{document}
\include{subfile1.tex}
\include{subfile2.tex}
\end{document}
6
  • @UlrichDiez that block is skipped completely on the second reading once main.tex is input. Although I suppose technically you are right about the \endinput it doesn't actually matter does it?, the file closes anyway. Commented Jun 29, 2021 at 13:50
  • @UlrichDiez since now you mentioned it I know someone will add \tracingifs=1 to get a warning I'll have to re-arrange to finish the if earlier :-) Commented Jun 29, 2021 at 14:00
  • Another problem might be hyperref's error-messages about missing destinations when compiling subfiles. :-) Commented Jun 29, 2021 at 14:06
  • @UlrichDiez yes sorry I'd updated the code without \endinput following your first comment Commented Jun 29, 2021 at 14:06
  • 2
    Like you and some others, Ulrike represents an idol for me and therefore a priori is unblameable. :-) Commented Jun 29, 2021 at 14:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .