7

I create a package: one common file that includes others. In common package file (russian_post.sty) I define options:

\DeclareOption{times}{\@seriffalse}
\DeclareOption{landscape}{\@lscapetrue}
\DeclareOption{portrait}{\@lscapefalse}
\DeclareOption{smalltab}{\PassOptionsToPackage{smalltab}{form_110}}
\DeclareOption{tinytab}{\PassOptionsToPackage{tinytab}{form_110}}
\DeclareOption*{\PackageWarning{russian_post}{Unknown option `\CurrentOption'}}
\ProcessOptions\relax

after that I include packages, the interesting is

\RequirePackage{form_110}

In file form_110.sty I define them again:

\DeclareOption{smalltab}{\@smallt@btrue}
\DeclareOption{tinytab}{\@tinyt@btrue}
\ProcessOptions\relax

And in my file.tex I try to use my package with this options:

\usepackage[times,tinytab]{russian_post}

This cause latex errors:

! LaTeX Error: Unknown option `times' for package `russian_post'.
! LaTeX Error: Unknown option `tinytab' for package `russian_post'.

in spite of that I've already defined default action for unknown options (just show warning).

The weird things come later: after ignoring these errors I get a right pdf-file.

If I move all \RequirePackage before options declaration block, latex works without errors but options don't pass to package. I know, that I can use global variables from russian_post.sty in other packages, but what if I would like to use that package alone?

How can this be so? And how can I omit such errors?

UPD:*

Thanks to @Werner. I add minimal example:

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{russian_post.sty}
\DeclareOption{smalltab}{\PassOptionsToPackage{smalltab}{form_110}}
\DeclareOption{tinytab}{\PassOptionsToPackage{tinytab}{form_110}}
\DeclareOption*{\PackageWarning{russian_post}{Unknown option `\CurrentOption'}}
\ProcessOptions\relax

\RequirePackage{form_110}
\end{filecontents*}

\begin{filecontents*}{form_110.sty}
\newif\if@smallt@b\newif\if@tinyt@b
\@smallt@bfalse\@tinyt@bfalse
\DeclareOption{smalltab}{\@smallt@btrue}
\DeclareOption{tinytab}{\@tinyt@btrue}
\ProcessOptions\relax

\RequirePackage{russian_post}

\def\testsmall{\if@smallt@b TRUE\else FALSE\fi}
\def\testtiny{\if@tinyt@b TRUE\else FALSE\fi}
\end{filecontents*}

\usepackage[smalltab]{russian_post}

\begin{document}
small: \testsmall

tiny: \testtiny
\end{document}

It seems that the problem is in multiple inclusion of russian_post.sty. But latex should prevent such things when you're using \RequirePackage or \usepackage. I don't understand anything!!!

UPD2: it's more and more weird!

If I move this options to \documentclass, all works fine! What is it?

4
  • Do you load the package form_110? In the LaTeX companion book, page 880, there is a footnote saying "It is the responsibility of the package writer to actually load such packages. LaTEX does not check that packages receiving options via \PassOptionsToPackage are actually loaded later on."
    – Guido
    May 4, 2014 at 5:59
  • @Guido, this package is loaded via \RequirePackage in russian_post.
    – Eddy_Em
    May 4, 2014 at 6:02
  • This minimal example produces as output "test opt passed", as expected. It would be great if you could widdle down your current setup to something minimal and self-contained that you can post here.
    – Werner
    May 4, 2014 at 6:14
  • @Werner, thanks! I found it: that was because of \RequirePackage{russian_post} in form_110.sty. It is become now more weird: latex should omit such multiple inclusion...
    – Eddy_Em
    May 4, 2014 at 6:37

1 Answer 1

9

General part

This comment indicates, that a more general answer might be useful.

If LaTeX loads a package foo, then it defines macro \[email protected] (containing version date and information). At the next loading request (\RequirePackage{foo}, \usepackage{foo}) it sees that \[email protected] is defined and does not load the package again. That would be quite fatal, if the package uses \newcommand (which a good package should do ...).

But it checks the options. LaTeX's understanding of an option is that an option adds/enables an additional feature. Therefore, if subsequent \RequirePackage and \usepackage calls of the same package do not contain new options, LaTeX is happy and continues. Otherwise, if LaTeX sees a new option, it cannot load the package again to enable the new option. And LaTeX complains. Example:

\usepackage[ngerman]{babel}
\usepackage[english]{babel}

LaTeX stops with an error:

! LaTeX Error: Option clash for package babel.

Pressing h at the prompt reveals:

The package babel has already been loaded with options:
  [ngerman]
There has now been an attempt to load it with options
  [english]
Adding the global options:
  ngerman,english
to your \documentclass declaration may fix this.

Or without global options:

\usepackage[ngerman,english]{babel}

or if the first package loading is hidden in a class or package:

\PassOptionsToPackage{ngerman,english}{babel}
\documentclass{...}

Now, we reached \PassOptionsToPackage. It is useful before the package is loaded the first time, otherwise LaTeX options code does not see the subsequent option additions. And it should be noted:

  • \PassOptionsToPackage does not check, if the package will be loaded at all.
  • Also it does not check, whether the package is already loaded. (Perhaps a warning could be given in this case. A package could later check for new options, but \@ifpackagewith is limited to the preamble.)

Specific problem

You have the following package loading order:

* \usepackage[smalltab]{russian_post}
  * \RequirePackage{form_110}
    * \RequirePackage{russian_post}

The problem is that russian_post is again requested for loading before the first loading is completed. The package file is not loaded, but LaTeX has still to deal with the options.

Workaround: Delay the loading of package form_110 with \AtEndOfPackage, then the nested loading of russain_post is late enough to get LaTeX's option stuff of the first loading finished:

Package russian_post contains then:

\AtEndOfPackage{RequirePackage{form_110}}

The loading order/nesting of the test file is then:

* \usepackage[smalltab]{russian_post}
* \RequirePackage{form_110}
   * \usepackage{russian_post}

Thus the second \usepackage{russian_post} is not longer inside the scope of its first loading.

1
  • Thanks! \AtEndOfPackage fully solve my problem.
    – Eddy_Em
    May 4, 2014 at 8:10

You must log in to answer this question.

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