Cross referencing across LaTeX documents in one project

A common scenario we come across is that we have a main manuscript document and a supplementary information document, each of which have their own sections, tables and figures. The question then becomes – how do we effectively cross-reference between the documents without having to tediously count all the numbers ourselves every time we make a change and recompile the documents?

The answer: cross referencing!

This solution is based on the tex stackexchange thread found here: https://tex.stackexchange.com/questions/62142/latexmk-with-external-references

Create two *.tex files that will contain the source code for you documents. For example: main.tex for your manuscript and SI.tex for your supplementary information.

Add the following code to the header of both files.

\usepackage{xr}
\makeatletter

\newcommand*{\addFileDependency}[1]{
    \typeout{(#1)}
    \@addtofilelist{#1}
    \IfFileExists{#1}{}{\typeout{No file #1.}}
}\makeatother

\newcommand*{\myexternaldocument}[1]{%
    \externaldocument{#1}%
    \addFileDependency{#1.tex}%
    \addFileDependency{#1.aux}%
}

Then, create a new file called “latexmkrc” and paste the following code into it:

$sub_doc_output = 'output-subdoc';

@sub_doc_options = ();

push @sub_doc_options, '-pdf'; # Use pdflatex for compilation of external documents.
# Replace '-pdf' by '-pdfdvi', 'pdfxe', or 'pdflua' if needed.

push @file_not_found, '^No file\\s*(.+)\s*$';

add_cus_dep( 'tex', 'aux', 0, 'makeexternaldocument' );
sub makeexternaldocument {
    if ( $root_filename ne $_[0] )  {
        my ($base_name, $path) = fileparse( $_[0] );
        pushd $path;
        my $return = system "latexmk",
                            @sub_doc_options,
                            "-aux-directory=$sub_doc_output",
                            "-output-directory=$sub_doc_output",
                            $base_name;
        if ( ($sub_doc_output ne ' ') && ($sub_doc_output ne '.') ) {

             rdb_add_generated( "$sub_doc_output/$base_name.aux" );
             copy "$sub_doc_output/$base_name.aux", ".";
        }
        popd;
        return $return;
   }
}

Finally, add a command declaring the external document before the \begin{document} statement in each of the files. So in main.tex add:

\myexternaldocument{SI}

And to SI.tex add:

\myexternaldocument{main}

After recompiling you can now reference labels across documents using the usual:

\ref{my_item_label}

Here is a minimal working example with main.tex:

\documentclass{article}
\usepackage{graphicx} 

\usepackage{xr}
\makeatletter

\newcommand*{\addFileDependency}[1]{
\typeout{(#1)}
\IfFileExists{#1}{}{\typeout{No file #1.}}
}\makeatother

\newcommand*{\myexternaldocument}[1]{%
\externaldocument{#1}%
\addFileDependency{#1.tex}%
\addFileDependency{#1.aux}%
}

\myexternaldocument{SI}

\title{mini cross reffing example}
\author{npq15 }
\date{November 2024}

\begin{document}

\maketitle

\section{Introduction}

\begin{figure}
    \centering
   
    \caption{Caption}
    \label{fig:main}
\end{figure}

I am referencing a SI figure: \ref{fig:SI}

\end{document}

… and SI.tex:

\documentclass{article}
\usepackage{graphicx} % Required for inserting images
\usepackage{lipsum}
\usepackage{xr}
\makeatletter

\newcommand*{\addFileDependency}[1]{
    \typeout{(#1)}
    \@addtofilelist{#1}
    \IfFileExists{#1}{}{\typeout{No file #1.}}
}\makeatother

\newcommand*{\myexternaldocument}[1]{%
    \externaldocument{#1}%
    \addFileDependency{#1.tex}%
    \addFileDependency{#1.aux}%
}

\myexternaldocument{main}

\title{mini cross reffing example SI}
\author{npq15 }
\date{November 2024}


\begin{document}

\maketitle

\section{SI}

\begin{figure}
    \centering
    
    \caption{SI figure}
    \label{fig:SI}
\end{figure}

I am referencing a main figure: \ref{fig:main}

\end{document}

Happy LaTEXing 🙂

Author