为我的文档中使用的包创建依赖树(\RequirePackage)

为我的文档中使用的包创建依赖树(\RequirePackage)

有没有办法\RequirePackage为文档中使用的软件包创建相互依赖的依赖关系树,最好使用各自所需的选项和版本号?是否有用于此目的的工具或软件包?这对于调试包选项冲突非常重要(参见“包选项和 \RequirePackage:命令顺序和选项冲突吗?“; 也可以看看 ”软件包作者处理软件包冲突的最佳实践是什么?“)。

例如,我不需要graphicx明确加载,因为dtklogos(我正在使用的)已经需要/加载它。事实上,graphicx也需要/加载graphicskeyval,而这也恰好是需要/加载的microtype。等等。我想给出一个涉及包选项冲突的例子,但由于相关的依赖关系很难弄清楚和调试,所以我现在想不出任何例子(我遇到过几个,但由于它们没有编译,我放弃了它们并忘记了它们);这个问题实际上可以帮助解决这一问题。

答案1

我同意约瑟夫的观点,你应该总是明确地需要你需要的任何包,不管其他包是否已经加载了它,但要回答你关于记录依赖关系树的问题,可以\@onefilewithoptions像这样挂钩(这比仅仅挂钩更好,\RequirePackage因为它还挂钩类等):

\errorcontextlines=\maxdimen

% begin code to log calls to \@onefilewithoptions (http://tex.stackexchange.com/questions/99723/creating-a-dependency-tree-requirepackage-for-packages-used-in-my-document)
\makeatletter
\def\@log@onefilewithoptions@{}% this will store the file tree
\def\@log@onefilewithoptions@delim{^^J}%
\def\@log@onefilewithoptions#1[#2][#3]#4{% our hook
    \ifx\@currnamestack\@empty
        \def\@log@onefilewithoptions@tmp{.}%
    \else
        \edef\@log@onefilewithoptions@tmp{\expandafter\@parse@curnamestack\@currnamestack\@nil}%
    \fi
    \expandafter\g@addto@macro\expandafter\@log@onefilewithoptions@\expandafter{\@log@onefilewithoptions@tmp}%
    \edef\@log@onefilewithoptions@tmp{#4[#2]{#1}[#3]\@log@onefilewithoptions@delim}%
    \expandafter\g@addto@macro\expandafter\@log@onefilewithoptions@\expandafter{\@log@onefilewithoptions@tmp}%
}
\def\@parse@curnamestack#1#2#3#4\@nil{%
    |%
    \@log@onefilewithoptions@ifblank{#4}{%
        +%
    }{%
        \@parse@curnamestack#4\@nil
    }%
}
\newcommand{\typeoutonefilewithoptionstree}{\typeout{@onefilewithoptions tree follows:\@log@onefilewithoptions@delim\@log@onefilewithoptions@ end @onefilewithoptions tree.}}
% display the tree at end document (for demonstration purposes)
\AtEndDocument{\typeoutonefilewithoptionstree}%
% patch the original to invoke our hook first, and to show the tree if there's an option clash
\def\@onefilewithoptions#1[#2][#3]#4{%
  %added by cyberSingularity
  \@log@onefilewithoptions{#1}[#2][#3]{#4}%
  %end addition
  \@pushfilename
  \xdef\@currname{#1}%
  \global\let\@currext#4%
  \expandafter\let\csname\@currname.\@currext-h@@k\endcsname\@empty
  \let\CurrentOption\@empty
  \@reset@ptions
  \makeatletter
  \def\reserved@a{%
    \@ifl@aded\@currext{#1}%
      {\@if@ptions\@currext{#1}{#2}{}%
        {%added by cyberSingularity
        \typeout{Option clash for \@cls@pkg\space #1. To help,}%
        \typeoutonefilewithoptionstree
        %end addition
        \@latex@error
            {Option clash for \@cls@pkg\space #1}%
            {The package #1 has already been loaded
             with options:\MessageBreak
             \space\space[\@ptionlist{#1.\@currext}]\MessageBreak
             There has now been an attempt to load it
              with options\MessageBreak
             \space\space[#2]\MessageBreak
             Adding the global options:\MessageBreak
             \space\space
                  \@ptionlist{#1.\@currext},#2\MessageBreak
             to your \noexpand\documentclass declaration may fix this.%
             \MessageBreak
             Try typing \space <return> \space to proceed.}}}%
      {\@pass@ptions\@currext{#2}{#1}%
       \global\expandafter
       \let\csname ver@\@currname.\@currext\endcsname\@empty
       \InputIfFileExists
         {\@currname.\@currext}%
         {}%
         {\@missingfileerror\@currname\@currext}%
    \let\@unprocessedoptions\@@unprocessedoptions
    \csname\@currname.\@currext-h@@k\endcsname
    \expandafter\let\csname\@currname.\@currext-h@@k\endcsname
              \@undefined
    \@unprocessedoptions}
    \@ifl@ter\@currext{#1}{#3}{}%
      {\@latex@warning@no@line
         {You have requested,\on@line,
          version\MessageBreak
            `#3' of \@cls@pkg\space #1,\MessageBreak
          but only version\MessageBreak
           `\csname ver@#1.\@currext\endcsname'\MessageBreak
          is available}}%
    \ifx\@currext\@clsextension\let\LoadClass\@twoloadclasserror\fi
    \@popfilename
    \@reset@ptions}%
  \reserved@a}
% borrowed from etoolbox (don't really want to load it just for this)
\newcommand{\@log@onefilewithoptions@ifblank}[1]{%
  \etb@ifblank@i#1&&\@secondoftwo\@firstoftwo:}
\long\def\etb@ifblank@i#1#2&#3#4#5:{#4}
\makeatother
% end code to log calls to \@onefilewithoptions



% real document begins
\documentclass[a4paper]{article}
\usepackage{graphicx}
\usepackage{keyval}
%\usepackage{tikz}% uncomment this to get an option clash on the next line
\usepackage[svgnames]{xcolor}

\begin{document}
    See console output or log file.
\end{document}

现在,当您遇到选项冲突时,您应该在错误发生之前获得依赖关系树的转储。

此外,依赖关系树始终会显示\AtEndDocument

请注意,在这两种情况下,都需要检查控制台或日志输出,其中将包含如下内容:

@onefilewithoptions tree follows:
.cls[a4paper]{article}[]
.sty[]{graphicx}[]
|+sty[]{keyval}[]
|+sty[]{graphics}[]
||+sty[]{trig}[]
||+sty[]{infwarerr}[2007/09/09]
||+sty[]{ltxcmds}[2010/12/07]
.sty[]{keyval}[]
.sty[svgnames]{xcolor}[]
end @onefilewithoptions tree.

希望这篇文章足够容易阅读。

答案2

虽然如评论中所述,我建议直接要求那些你使用的包,但包依赖关系“树”的概念已在 LaTeX2e 中得到解决pkgloader包装:见自动管理包装选项和加载顺序) 了解更多信息。如软件包文档中所述,其理念是,您可以按任意顺序给出要使用的软件包列表,然后它会“整理”出依赖关系树。

相关内容