……流石にそれはあり得ないだろうが、では texmf.cnf の検索対象のパスはどのように決まっているのだろう。チョット調べみた。
前提
調査対象は最新の TeX Live 2015(Windows)とする。現在の Kpathsearch では texmf.cnf は複数読込になっていて、実際に読み込まれた texmf.cnf のセットは次のコマンドで知ることができるはずである。
kpsewhich -all texmf.cnf
この調査では、この結果は正しいものと仮定する。
例えば、TeX Live 2015(Windows)の既定の状態では次のようになっている。
c:/texlive/2015/texmf.cnf c:/texlive/2015/texmf-dist/web2c/texmf.cnf
この前者のファイルはユーザのカスタム設定用のもので既定では(実質的に)空になっている。後者が TeX Live の既定の設定が書かれた“既定の texmf.cnf”である。
予備実験
TeX Live の既定の状態で以下のコマンドを実行して、変数 TEXMFCNF の値を調べてみる。
kpsewhich -var-value=TEXMFCNF
結果は以下のようになる。(実際には改行無しで一行で出力される。)
{ C:/texlive/2015/bin/win32, C:/texlive/2015/bin/win32/share/texmf-local/web2c, C:/texlive/2015/bin/win32/share/texmf-dist/web2c, C:/texlive/2015/bin/win32/share/texmf/web2c, C:/texlive/2015/bin/win32/texmf-local/web2c, C:/texlive/2015/bin/win32/texmf-dist/web2c, C:/texlive/2015/bin/win32/texmf/web2c, C:/texlive/2015/bin, C:/texlive/2015/bin/share/texmf-local/web2c, C:/texlive/2015/bin/share/texmf-dist/web2c, C:/texlive/2015/bin/share/texmf/web2c, C:/texlive/2015/bin/texmf-local/web2c, C:/texlive/2015/bin/texmf-dist/web2c, C:/texlive/2015/bin/texmf/web2c, C:/texlive/texmf-local/web2c, C:/texlive/2015, C:/texlive/2015/share/texmf-local/web2c, C:/texlive/2015/share/texmf-dist/web2c, C:/texlive/2015/share/texmf/web2c, C:/texlive/2015/texmf-local/web2c, C:/texlive/2015/texmf-dist/web2c, C:/texlive/2015/texmf/web2c }
“既定の texmf.cnf”(C:/texlive/2015/texmf-dist/web2c/texmf.cnf)を見ると、変数 TEXMFCNF の値が次のように書かれていて、これは上の結果と一致している。
TEXMFCNF = {\ $SELFAUTOLOC,\ $SELFAUTOLOC/share/texmf-local/web2c,\ $SELFAUTOLOC/share/texmf-dist/web2c,\ $SELFAUTOLOC/share/texmf/web2c,\ $SELFAUTOLOC/texmf-local/web2c,\ $SELFAUTOLOC/texmf-dist/web2c,\ $SELFAUTOLOC/texmf/web2c,\ \ $SELFAUTODIR,\ $SELFAUTODIR/share/texmf-local/web2c,\ $SELFAUTODIR/share/texmf-dist/web2c,\ $SELFAUTODIR/share/texmf/web2c,\ $SELFAUTODIR/texmf-local/web2c,\ $SELFAUTODIR/texmf-dist/web2c,\ $SELFAUTODIR/texmf/web2c,\ \ $SELFAUTOGRANDPARENT/texmf-local/web2c,\ $SELFAUTOPARENT,\ \ $SELFAUTOPARENT/share/texmf-local/web2c,\ $SELFAUTOPARENT/share/texmf-dist/web2c,\ $SELFAUTOPARENT/share/texmf/web2c,\ $SELFAUTOPARENT/texmf-local/web2c,\ $SELFAUTOPARENT/texmf-dist/web2c,\ $SELFAUTOPARENT/texmf/web2c\ }
ここで、$SELFAUTOLOC は実行ファイル(今の場合は kpsewhich.exe)があるディレクトリであり、$SELFAUTODIR・$SELFAUTOPARENT・$SELFAUTOGRANDPARENT は $SELFAUTOLOC の 1・2・3 階層上のディレクトリである。これらの変数の値は暗黙的に決められる。
さて、既に述べたように、この“既定の texmf.cnf”の TEXMFCNF の内容は実際には(少なくとも texmf.cnf を探索する目的では)参照されていないことが予想される。
一方で、環境変数の TEXMFCNF は実際に参照されている。例えば、以下の記事にある手順はその性質を利用している。
- 管理者権限(sudo)無しで extractbb の自動起動を有効化する (Qiita/zr-tex8r)
- 以下のパスに「
foo=1
」とだけ書いたファイルを置く。- C:/tmp/aa/texmf.cnf
- C:/tmp/bb/texmf.cnf
- C:/tmp/cc/texmf.cnf
- “既定の texmf.cnf”の TEXMFCNF のリストの先頭に
C:/tmp/aa
を追加する。TEXMFCNF = {\ C:/tmp/aa,\ $SELFAUTOLOC,\ ……(略)
- この状態で変数 TEXMFCNF の値を調べる。
kpsewhich -var-value=TEXMFCNF
結果は以下のようになり、C:/tmp/aa
がきちんと追加されている。{ C:/tmp/aa, C:/texlive/2015/bin/win32, ……(略)
- さらに、「実際に読まれる texmf.cnf」を調べてみる。
kpsewhich -all texmf.cnf
結果は次のようになる。c:/texlive/2015/texmf.cnf c:/texlive/2015/texmf-dist/web2c/texmf.cnf
- すなわち、“既定の texmf.cnf”の中の TEXMFCNF への変更は、変数 TEXMFCNF の値としては有効だが、実際の texmf.cnf の検索パスとしては無効であると推測される。
- 次に、環境変数 TEXMFCNF を以下のように設定する。
set TEXMFCNF=C:/tmp/bb;C:/tmp/cc
- この状態で TEXMFCNF の値を調べる(
-var-value
)と以下のようになる。C:/tmp/bb;C:/tmp/cc
さらに、「実際の texmf.cnf」(-all
)を調べる。c:/tmp/bb/texmf.cnf c:/tmp/cc/texmf.cnf
- つまり、環境変数での TEXMFCNF の変更は、texmf.cnf の探索パスとして有効であるようだ。
- 次に、環境変数 TEXMFCNF を以下のように設定する。
set TEXMFCNF=C:/tmp/bb;;C:/tmp/cc
なお、おの値の中の 2 つ連続する「;;」は、この間に「上位ファイルで指定された値」、つまり“既定の texmf.cnf”の TEXMFCNF の値が割り込むことを意味する。 - この状態で TEXMFCNF の値を調べる。
C:/tmp/bb;;C:/tmp/cc
どうやら、「上位割り込み」は(少なくとも kpsewhich で示される((-expand-var
を用いても同様の結果となる。)))TEXMFCNF の値としては反映されないようだ。
「実際の texmf.cnf」を調べる。c:/tmp/bb/texmf.cnf c:/texlive/2015/texmf.cnf c:/texlive/2015/texmf-dist/web2c/texmf.cnf c:/tmp/cc/texmf.cnf
- この場合でも、環境変数の TEXMFCNF は検索パスとして有効で、ファイルに書いた TEXMFCNF は無効であるようだ。
- 次のような内容のファイルを作る。
- C:/tmp/aa/texmf.cnf、内容は「
TEXMFCNF=C:/tmp/bb;
」 - C:/tmp/bb/texmf.cnf、内容は「
TEXMFCNF=C:/tmp/dd;
」 - C:/tmp/cc/texmf.cnf、内容は「
TEXMFCNF=C:/tmp/dd;
」 - C:/tmp/dd/texmf.cnf、内容は「
TEXMFCNF=C:/tmp/dd;
」
- C:/tmp/aa/texmf.cnf、内容は「
- “既定の texmf.cnf”の TEXMFCNF のリストの先頭に C:/tmp/cc を追加する。
TEXMFCNF = {\ C:/tmp/cc,\ $SELFAUTOLOC,\ ……(略)
- 環境変数 TEXMFCNF の内容を「
C:/tmp/aa;
」とする。 - この状態で、変数 TEXMFCNF の値を調べる。やはり割り込み部分は表示されない。
C/tmp/aa;
さらに、「実際の texmf.cnf」を調べる。結果は次の通り。c:/tmp/aa/texmf.cnf c:/texlive/2015/texmf.cnf c:/texlive/2015/texmf-dist/web2c/texmf.cnf
- 環境変数 TEXMFCNF を削除する。
- C:/texlive/2015/texmf.cnf に以下の行を書き加える。
TEXMFCNF=C:/tmp/bb;C:/tmp/cc
- 変数 TEXMFCNF の値を調べる。*1
C:/tmp/bb;C:/tmp/cc
「実際の texmf.cnf」を調べる。先の TEXMFCNF の値と全く食い違う結果になっている。c:/texlive/2015/texmf.cnf c:/texlive/2015/texmf-dist/web2c/texmf.cnf
- texmf.cnf ファイルに書いた TEXMFCNF は実際の texmf.cnf の検索パスとしては無効。
- 一方、環境変数の TEXMFCNF は実際の texmf.cnf の検索パスとして有効。
実験①
次の実験に移る前に、環境を復元しておく。
実験②
まとめ
以下のようであると推測される。
[2015-09-19 追記] おっと、一番大事なことを書いてなかった……
アレはどこから来た?
「実際の検索パスとしての TEXMFCNF」は texmf.cnf では指定できない、ということを述べたが、ではソレはどうやって決まっているのか? つまり、「実際に読まれる texmf.cnf」は既定では
c:/texlive/2015/texmf.cnf c:/texlive/2015/texmf-dist/web2c/texmf.cnf
となるのは何故か?
その答えはこの記事へのコメントで kakuto さんが答えて下さっている。要するに、
決め打ち
なのである。ただしその「決め打ちの値」は TeX 環境によって異なる。そして、TeX Live でのその値は何かというと、実は、先に示した「“既定の texmf.cnf”に書かれた TEXMFCNF の値」({$SELFAUTOLOC,……}
)と等しい。要するに、Kpathsearch は実際に「書かれた値」を参照しているのではないが、混乱が起こらないように、「正しい値を“既定の texmf.cnf”に書いておく」という“約束”になっていると考えられる。つまり、どこかの texmf.cnf において TEXMFCNF の値が変更・追加されることが無い限りには、kpsewhich が(-var-value
等で)示した TEXMFCNF の値は“正しい”のである。
改めてまとめ
「実際の検索パスとしての TEXMFCNF」は以下のように決まる。前にあるものほど優先される。
- 環境変数 TEXMFCNF の値。
- “決め打ち”した既定値。
比較のために示すと、一般の Kpathsearch 変数(HOGEHOGE とする)の値は以下のように決まる。「kpsewhich で表示される TEXMFCNF」もこの手順に従う。
基本的に、(あらゆる)texmf.cnf にある TEXMFCNF の値は既定(最初にインストールした状態)から変更してはいけない。これが遵守されている限りにおいて、「実際の検索パスとしての TEXMFCNF」と「kpsewhich で表示される TEXMFCNF」は一致する。つまり、「TEXMFCNF」は“例外扱い”ではなくなる。