[Tex/LaTex] ‘Unknown option’ for the own package

errorspackage-optionspackage-writing

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?

Best Answer

General part

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

If LaTeX loads a package foo, then it defines macro \ver@foo.sty (containing version date and information). At the next loading request (\RequirePackage{foo}, \usepackage{foo}) it sees that \ver@foo.sty 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.