33

How can I define a document command \FilesRequire that writes to the .log (or to the output console) a list of all packages internally required by the declared document class and by the packages that have been loaded by the user in a document?

For example, with this document

\documentclass{book}
\usepackage{graphicx}
\usepackage{amsmath}

\FilesRequire

\begin{document}

test

\end{document}

The output will be something like

Document class book: doesn't require additional packages.
Package graphicx requires: keyval, graphics.
Package amsmath requires: amstext[1995/01/25], amsbsy[1995/01/20],
amsopn[1995/01/20].

The command should have an optional argument for a comma separated list of the packages which will be inquired:

\documentclass{book}
\usepackage{graphicx}
\usepackage{amsmath}

\FilesRequire[amsmath]

\begin{document}

test

\end{document}

will produce just the information for the document class and for amsmath:

Document class book: doesn't require additional packages.
Package amsmath requires: amstext[1995/01/25], amsbsy[1995/01/20],
amsopn[1995/01/20].

Basically, the command must produce a list of the arguments for all \RequirePackage commands found inside the .cls and .sty files used in a document.

I am not interested in external scripts.

8
  • What you are asking for is doable by using one of the various package that keeps track of the current file, and hooking into \LoadClass and \RequirePackage (and \usepackage, if the hooking is done after \documentclass). But it is not completely straightforward to get everything right. Maybe if you described your goal it would be possible to find an alternate solution (within TeX). Jun 17, 2013 at 9:20
  • @BrunoLeFloch my goal is described in the question or, at least, I thought it was :-); I'd like to have the command with the mentioned specifications. Do you need me to clarify something else? Jun 17, 2013 at 19:54
  • My question is to know why you want such a list. For instance, do you in fact want to know for all existing packages what packages they depend on, to build a dependency tree? There may be easier approaches than what you are asking for. Jun 18, 2013 at 11:48
  • @BrunoLeFloch no, I am not interested in a dependency tree. I want this command to quickly show me which packages are being loaded behind the scenes without going to the .sty or .cls files directly. Jun 19, 2013 at 2:08
  • 1
    @BrunoLeFloch now that I re-read my previous answer to you in view of Frank's comment, perhaps I need to clarify: I don't want a full dependency tree (as I assumed you were suggesting with "all packages"), but I want the ability to know which/if some package(s) was(were) loaded internally by another one that I directly loaded in my document. I hope my intent is more clear now. Jun 20, 2013 at 2:19

2 Answers 2

23
+100

This prototype explores the idea to get the dependencies of the top level packages without recording the full package dependencies. The code observes LaTeX's package management and hooks into \@onefilewithoptions that is called for all required packages and classes, even if a package is already loaded (then LaTeX only checks the package options for clashes).

Remarks:

  • As requested, only the dependencies of the top level classes and packages are recorded.
  • Also packages are added to the dependencies, if they are required by dependent packages. However, the transitive closure is only complete, if the package and its dependent packages are not loaded earlier, see the example below.
  • Some packages also loads other packages via \AtBeginDocument, these cases are also caught, see the example.

Implementation notes:

  • An implementation should not use other packages. Otherwise it would interfere too much with the file, whose package dependencies are analyzed.
  • The package list is given via \AtEndDocument, the only hook vanilla LaTeX provides for code after the preamble. If an earlier time is wanted, then it could be checked in \AtBeginDocument, if pacakage etoolbox is available for using its hook \AfterEndPreamble. Or the package listings could be manually triggered in the document body.

Example file:

\makeatletter
\let\req@onefilewithoptions\@onefilewithoptions
\def\@onefilewithoptions#1[#2][#3]#4{%
  \req@push{#1.#4}%
  \req@onefilewithoptions{#1}[{#2}][{#3}]{#4}%
  \req@pop
}

\let\req@list\@empty
\let\req@item\relax
\let\req@top\relax
\newcounter{req@count}
\def\req@push#1{%
  % \typeout{*** [#1]}% debug
  \ifcase\value{req@count}%
    \@ifundefined{req@#1}{%the file, whose package dependencies 
      \global\expandafter
      \let\csname req@#1\endcsname\@empty
      \xdef\req@list{%
        \req@list
        \req@item{#1}%
      }%
    }{}%
    \xdef\req@top{#1}%
    \edef\req@tmp{%
      \noexpand\AtBeginDocument{%
        \noexpand\stepcounter{req@count}%
        \xdef\noexpand\req@top{#1}%
      }%
    }%
    \req@tmp
  \else
    \expandafter\ifx\csname req@\req@top\endcsname\@empty
      \expandafter\xdef\csname req@\req@top\endcsname{#1}%
    \else
      \edef\req@tmp{%
        \noexpand\in@{,#1,}{,\csname req@\req@top\endcsname,}%
      }%
      \req@tmp
      \ifin@
      \else
        \expandafter\xdef\csname req@\req@top\endcsname{%
          \csname req@\req@top\endcsname
          ,#1%
        }%
      \fi
    \fi
  \fi
  \stepcounter{req@count}%
}
\def\req@pop{%
  \addtocounter{req@count}{-1}%
  \ifcase\value{req@count}%
    \global\let\req@top\relax
    \AtBeginDocument{%
      \addtocounter{req@count}{-1}%
      \global\let\req@top\relax
    }%
  \fi
}

\def\req@process{%
  \typeout{Requirement list}%
  \typeout{================}%
  \let\req@item\req@process@item
  \req@list 
  \typeout{================}%
}
\def\req@process@item#1{%
  \typeout{* #1\req@info{#1}}%
  \expandafter\@for\expandafter\req@tmp
  \expandafter:\expandafter=\csname req@#1\endcsname\do{%
    \typeout{ \space> \req@tmp\req@info{\req@tmp}}%
  }%
}
\def\req@info#1{%
  \@ifundefined{ver@#1}{}{ [\@nameuse{ver@#1}]}%
}
\AtEndDocument{\req@process}%
\makeatother

\documentclass{article}
\usepackage{amsmath}
\usepackage[colorlinks]{hyperref}
\usepackage{bookmark}
\begin{document}
\end{document}

Result:

Requirement list
================
* article.cls [2007/10/19 v1.4h Standard LaTeX document class]
* amsmath.sty [2013/01/14 v2.14 AMS math features]
  > amstext.sty [2000/06/29 v2.01]
  > amsgen.sty [1999/11/30 v2.0]
  > amsbsy.sty [1999/11/29 v1.2d]
  > amsopn.sty [1999/12/14 v2.01 operator names]
* hyperref.sty [2012/11/06 v6.83m Hypertext links for LaTeX]
  > hobsub-hyperref.sty [2013/02/08 v1.16 Bundle oberdiek, subset hyperref (HO)
]
  > hobsub-generic.sty [2013/02/08 v1.16 Bundle oberdiek, subset generic (HO)]
  > ltxcmds.sty [2013/02/08 v1.23 LaTeX kernel commands for general use (HO)]
  > infwarerr.sty [2013/02/08 v1.4 Providing info/warning/error messages (HO)]
  > ifluatex.sty [2013/02/08 v1.5 Provides the ifluatex switch (HO)]
  > etexcmds.sty [2013/02/07 v1.6 Avoid name clashes with e-TeX commands (HO)]
  > protecteddef.sty [2013/02/08 v1.1 Define protected commands (HO)]
  > ifpdf.sty [2013/02/08 v2.5 Provides the ifpdf switch (HO)]
  > pdftexcmds.sty [2013/02/08 v0.22 Utility functions of pdfTeX for LuaTeX (HO
)]
  > intcalc.sty [2013/02/08 v1.2 Expandable calculations with integers (HO)]
  > bigintcalc.sty [2013/02/07 v1.4 Expandable calculations on big integers (HO
)]
  > hopatch.sty [2013/01/24 v1.4 Wrapper for package hooks (HO)]
  > xcolor-patch.sty [2013/02/08 xcolor patch]
  > keyval.sty [1999/03/16 v1.13 key=value parser (DPC)]
  > kvsetkeys.sty [2013/02/08 v1.18 Key value parser (HO)]
  > kvdefinekeys.sty [2013/02/08 v2.1 Define keys (HO)]
  > pdfescape.sty [2013/02/08 v1.16 Implements pdfTeX's escape features (HO)]
  > ifvtex.sty [2013/02/08 v1.6 Detect VTeX and its facilities (HO)]
  > ifxetex.sty [2010/09/12 v0.6 Provides ifxetex conditional]
  > hycolor.sty [2013/02/08 v1.8 Color options for hyperref/bookmark (HO)]
  > letltxmacro.sty [2013/02/08 v1.5 Let assignment for LaTeX macros (HO)]
  > auxhook.sty [2013/02/07 v1.4 Hooks for auxiliary files (HO)]
  > kvoptions.sty [2013/02/08 v3.13 Key value format for package options (HO)]
  > url.sty [2006/04/12  ver 3.3  Verb mode for urls, etc.]
  > bitset.sty [2013/02/07 v1.2 Handle bit-vector datatype (HO)]
  > atbegshi.sty [2013/02/08 v2.1 At begin shipout hook (HO)]
  > atveryend.sty [2013/02/08 v1.10 Hooks at the very end of document (HO)]
  > rerunfilecheck.sty [2013/02/08 v1.8 Rerun checks for auxiliary files (HO)]
  > uniquecounter.sty [2013/02/08 v1.4 Provide unlimited unique counter (HO)]
  > color.sty [2005/11/14 v1.0j Standard LaTeX Color (DPC)]
  > nameref.sty [2012/10/27 v2.43 Cross-referencing by name of section]
  > refcount.sty [2013/02/08 v3.6 Data extraction from label references (HO)]
  > gettitlestring.sty [2013/02/08 v1.6 Cleanup title references (HO)]
* bookmark.sty [2013/02/07 v1.25 PDF bookmarks (HO)]
  > pdfescape.sty [2013/02/08 v1.16 Implements pdfTeX's escape features (HO)]
  > ifpdf.sty [2013/02/08 v2.5 Provides the ifpdf switch (HO)]
  > ifxetex.sty [2010/09/12 v0.6 Provides ifxetex conditional]
  > ifvtex.sty [2013/02/08 v1.6 Detect VTeX and its facilities (HO)]
  > ifluatex.sty [2013/02/08 v1.5 Provides the ifluatex switch (HO)]
  > pdftexcmds.sty [2013/02/08 v0.22 Utility functions of pdfTeX for LuaTeX (HO
)]
  > hyperref.sty [2012/11/06 v6.83m Hypertext links for LaTeX]
  > auxhook.sty [2013/02/07 v1.4 Hooks for auxiliary files (HO)]
  > kvsetkeys.sty [2013/02/08 v1.18 Key value parser (HO)]
  > kvoptions.sty [2013/02/08 v3.13 Key value format for package options (HO)]
  > hycolor.sty [2013/02/08 v1.8 Color options for hyperref/bookmark (HO)]
  > bitset.sty [2013/02/07 v1.2 Handle bit-vector datatype (HO)]
  > ltxcmds.sty [2013/02/08 v1.23 LaTeX kernel commands for general use (HO)]
================

Discussion:

  • The example catches the packages nameref and color that are loaded by hyperref via \AtBeginDocument.
  • The example also shows the limitation. Package bookmark loads package hyperref. Since package hyperref is already loaded, the .sty file is not read by LaTeX and the \RequirePackage commands are not seen. Thus the list for package bookmark misses the dependencies of package hyperref. Therefore a refinement of this prototype would need to record the full package dependencies.
1
  • 1
    Now that's hooking!
    – Caio Lopes
    Jul 5, 2013 at 19:12
13

This is my dirt solution following Bruno Le Floch's suggestion.

The \RequirePackages have to be call before the packages you want to know about. It reports to the output console and to a file *.requiredpackages. It doesn't tell nothing about packages required by the document class. But could work as a starting point.

\documentclass{book}

\def\RequiredPackages{
   \newwrite\requiredpackagesfile
   \openout\requiredpackagesfile=\jobname.requiredpackages
   \newtoks\requiredpackages
   \newif\ifrequiredpackages

   \let\realusepackage=\usepackage
   \def\usepackage##1{%
      \requiredpackagesfalse
      \requiredpackages{}%
      \realusepackage{##1}%
      \ifrequiredpackages
         \edef\requiredpackagesreport{Package ##1 requires: \the\requiredpackages.}%
      \else
         \edef\requiredpackagesreport{Package ##1 doesn't require additional packages.}%
      \fi
      \expandafter\expandafter\expandafter\write\expandafter\requiredpackagesfile\expandafter{\requiredpackagesreport}%
      \message{\requiredpackagesreport}%
   }

   \let\realRequirePackage=\RequirePackage
   \def\RequirePackage##1{%
      \ifrequiredpackages
         \requiredpackages\expandafter{\the\requiredpackages, ##1}%
      \else
         \requiredpackagestrue
         \requiredpackages\expandafter{##1}%
      \fi
      \realRequirePackage{##1}%
   }
}
\RequiredPackages

\usepackage{graphicx}
\usepackage{amsmath}

\begin{document}

test

\end{document}

The commands \usepackage and \RequirePackage are hooked, but not \LoadClass, so its use is not reported.

As is, it produces this:

Package graphicx requires: keyval,graphics, trig.
Package amsmath requires: amstext, amsgen, amsbsy, amsgen, amsopn, amsgen.
2
  • 5
    nice, except for one thing ... it can't report on packages preloaded ("required") by a document class. so if you replace book by amsbook, it reports Package amsmath doesn't require additional packages. since amsmath is preloaded by amsbook, which short circuits the additional loading. in fact, it would be really nice if this could report packages required by a document class, so people would know that amsbook already preloads amsmath and amsfonts. (it has amsthm built into the code, so it would be impossible to detect that.) Jun 30, 2013 at 18:01
  • Thank you, Caio. This is definitely a big step towards the solution! Jul 2, 2013 at 15:01

You must log in to answer this question.

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