# How do I determine in which order packages have been loaded?

The \listfiles command will give the list of all loaded files (and therefore also packages) at the end of the .log file, but how do I determine from inside LaTeX, whether package A was loaded before package B or vice versa?

-
Please note: While the question is about packages, the answers are also usable for other files! –  Stephen Feb 25 '12 at 13:51

You can access the list as a comma separated list of filenames in \@filelist

If you need this check after \begin{document} use \listfiles so LaTeX saves that information.

\listfiles does

  \@for\@currname:=\@filelist\do{%
.....


to iterate over this list.

So for example you could define

\makeatletter

\def\test#1#2{%
\def\hmma{#1.sty}%
\let\hmmb\@empty
\@for\@currname:=\@filelist\do{%
\ifx\@currname\hmma
\def\hmmb{#2.sty}%
\fi
\ifx\@currname\hmmb
\fi}}


then using this as:

\test{marginnote}{geometry}


will type out

marginnote loaded before geometry


if that is in fact the case.

As noted in the comments you might want to use different comand names in production code, also if the two .sty are removed from the test you can test other files such as class and def files that are listed by LaTeX, but would need to explicitly use the extension, so \test{marginnote.sty}{geometry.sty}

-
\@filelist was the information I was missing! Thanks! \@currname collides with the hyperref package: ! Undefined control sequence. \@currname ->\@nil Replacing \@currname by \@dc (or something longer, which is probably better to make sure it is not used elsewhere) works (got that \hmma/\hmmb ;-)). \newcommand{\test}[2] instead of \def\test#1#2 might be considered, too. –  Stephen Feb 25 '12 at 13:47
While my question was about packages, you might want to add a note that your answer also works for any files, if .sty is removed from the code and \test{marginnote.sty}{geometry.sty} is used. For other files e.g. \test{subdocumentabcd.tex}{subdocumentzyxw.tex} or checking for .cfg or included .pdf or whatsoever is then possible. Your solution is robust but not complicated. A really nice answer. (Your new badge already says so.) +1 (yesterday) and now also accepted. –  Stephen Feb 25 '12 at 13:47

A way to check for file order is to check the order of the files loaded in the @filelist.

\documentclass{book}
\usepackage{graphicx}
\usepackage{longtable}
\usepackage{verse}
\usepackage{hyperref}
\usepackage{caption}
\newcounter{ctr}
\makeatletter
\let\afilelist\@filelist
\begin{document}
% Just to see files
\@for\next:=\afilelist\do{%
\next, \par
}
% Command factory
\stepcounter{ctr}
\@for\next:=\afilelist\do{%
\expandafter\edef\csname @\next\endcsname{\thectr}
\stepcounter{ctr}
}

% Define macro to check order
\def\checkpkgorder#1#2{%
\edef\X{\csname @#1\endcsname}
\edef\Y{\csname @#2\endcsname}
\expandafter\ifnum\X\expandafter<\Y
\else
\fi
}

\checkpkgorder{book.cls}{ifxetex.sty}
\end{document}

-
+1 and thanks for moving! –  Stephen Feb 24 '12 at 17:38
For checking after \begin{document} and to cover a before b as well as b before a in one step your code is really useful, but because I need neither of those I accepted the answer of David Carlisle. –  Stephen Feb 25 '12 at 13:48
@Stephen Not to worry, David's answer was very elegant. It deserved to be accepted. Upvoted it myself also. –  Yiannis Lazarides Feb 25 '12 at 15:31

Here's a way: the code from \usepackage{xparse} to \ExplSyntaxOff should go before checking any package, of course. The definition of the \test command is just for showing that the code works, though, and can be removed.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \l_pkgfirst_list_seq
\bool_new:N \l_pkgfirst_tmpa_bool
\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx }
\NewDocumentCommand{\ifpackagefirst}{mmmm}
{
\bool_set_false:N \l_pkgfirst_tmpa_bool
\seq_set_split:Nnx \l_pkgfirst_list_seq {,} { \use:c { @filelist} }
\seq_if_in:NnT \l_pkgfirst_list_seq {#1} { \bool_set_true:N \l_pkgfirst_tmpa_bool }
\seq_if_in:NnT \l_pkgfirst_list_seq {#2} { \bool_set_true:N \l_pkgfirst_tmpa_bool }
\bool_if:NTF \l_pkgfirst_tmpa_bool
{ \pkgfirst_compare:nnnn {#1}{#2}{#3}{#4} }
}
\cs_new:Npn \pkgfirst_compare:nnnn #1 #2 #3 #4
{
\bool_set_false:N \l_pkgfirst_tmpa_bool
\seq_map_inline:Nn \l_pkgfirst_list_seq
{
\str_if_eq:nnT { #1 } { ##1 }
{ \prg_map_break:n { \bool_set_true:N \l_pkgfirst_tmpa_bool } }
\str_if_eq:nnT { #2 } { ##1 }
{ \prg_map_break:n { \bool_set_false:N \l_pkgfirst_tmpa_bool } }
}
\bool_if:NTF \l_pkgfirst_tmpa_bool {#3} {#4}
}

\NewDocumentCommand\test{m m}
{\ifpackagefirst{#1}{#2}{\msg_term:x {#1~before~#2}}{\msg_term:x {#1~after~#2}}}

\ExplSyntaxOff

\usepackage{graphicx}
\usepackage{imakeidx}
\usepackage{kantlipsum}

\test{graphicx.sty}{imakeidx.sty}

\test{imakeidx.sty}{kantlipsum.sty}

\test{kantlipsum.sty}{graphicx.sty}

\test{pippo.sty}{pluto.sty}

\stop


This is the output:

*************************************************
* graphicx.sty before imakeidx.sty
*************************************************
*************************************************
* imakeidx.sty before kantlipsum.sty
*************************************************
*************************************************
* kantlipsum.sty after graphicx.sty
*************************************************
*************************************************
* OOPS, packages not both loaded
*************************************************


Usage:

\ifpackagefirst{package1.sty}{package2.sty}
{code to be executed if 1 has been loaded before 2}
{code to be executed if 2 has been loaded before 1}


If the packages are not both loaded, no code will be executed.

-
+1 and thanks for moving! –  Stephen Feb 24 '12 at 17:38
It is good to have a completely different kind of solution for the problem. –  Stephen Feb 25 '12 at 13:48