Hatena::ブログ(Diary)

アセトアミノフェンの気ままな日常

2015-07-09

W32TeX の 64bit 版と repstopdf

いままで誰も気づいていないのかなあと思いつつ:
W32TeX には 32bit 版バイナリの他に 64bit 版バイナリがある。あべのりさんの TeX インストーラ 3 はこの両方をダウンロードして展開するが、Path を通すのは C:\w32tex\bin の方だけらしい。これは Ghostscript についても 32bit 版しかインストールしないことと整合性が取れているように思える。W32TeX の 64bit 版は気にかけたことすらなかったし、今まで問題も起きなかったので知らなかったが、今回の現象はどうも 64bit 版が干渉することによって起きるらしい。

長くなりそうなので本記事の核心は

[1] bin64 ディレクトリが存在するとき、repstopdf (32bit) を起動するとたとえパスが通っていなくても rungs (64bit) が動き出すのはなぜか
[2] そもそも「bin64 ディレクトリが存在するかどうかで repstopdf の挙動が変わる」というややこしい現象は意図したものなのか、またそれに伴って TeX インストーラのデフォルトでは不都合が生じるのは既知なのか

ということである。以下で、この現象に気づいた経緯を説明する。

はじめに僕の環境を説明しておこう。

  • Windows 7 64bit
  • W32TeX [2015/07/04]
  • Ghostscript (32bit) 9.10, 9.15 ← 2通りのバージョンで試した
  • Strawberry Perl (32bit) 5.20.2

である。W32TeX と Ghostscript は TeX インストーラ 3 がインストールしたままの状態*1で、これらが 32bit なので Perl も 32bit 版をインストールして統一している次第である(じゃあ W32TeX 64bit バイナリもそもそもダウンロードするな、というのはナシ)。

試しに上記の環境で epstopdf コマンドを使用すると、epstopdf.exe (32bit) と rungs.exe (32bit) が起動して正常に実行できる(hoge.pdf を出力)。

 $ epstopdf hoge.eps

また、C:\w32tex\bin64 へのパスを(もちろん C:\w32tex\bin より前に)追加してから同様に実行すると、epstopdf.exe (64bit) と rungs (64bit) が起動するので次のエラーが出る。

epstopdf ($Id: epstopdf.pl 36129 2015-01-24 00:30:11Z karl $) 2.23
!!! Error: Writing to rungs failed, error code 255

まあこれは Ghostscript 64bit がインストールされていないからだと納得してよいだろう。実際、Ghostscript 64bit をインストールするとエラーは消える。

以上は想定内である。さて問題は、repstopdf コマンドである。repstopdf.exe (32bit) を起動したはずなのに

 $ repstopdf hoge.eps

を実行すると次のエラーが発生する。

epstopdf ($Id: epstopdf.pl 36129 2015-01-24 00:30:11Z karl $) 2.23
!!! Error: Writing to c:/w32tex/share/texmf-dist/scripts/epstopdf/../../../../bi
n64/rungs failed, error code 255

どうやら、実行したのが 32bit バイナリであるにもかかわらず、bin64 以下の rungs (64bit) を呼び出しに行っているらしい。というわけでいろいろ試してみたところ…

  1. Ghostscript 64bit をインストールしてみるとエラーは消える。
  2. bin64 フォルダを適当にリネーム(例えば xxx とか)するとエラーは消える。

という挙動が見られた。

この結果だけを見ると「EPS → PDF 変換は常に epstopdf を使えば、干渉の心配をせず済むではないか」と思われるかもしれない。しかし、repstopdf の存在意義を考えてみよう。texmf.cnf で shell_escape_commands に含まれているのは epstopdf ではなく repstopdf である*2

実際に LaTeX タイプセットで repstopdf が使われる例を見てみよう。たとえば、以下のソースを pdflatex でタイプセットすることを考える。

\documentclass{article}
\usepackage{graphicx}
\usepackage{epstopdf}
\begin{document}
\includegraphics[width=0.5\textwidth]{abcdef.eps}
\end{document}

前提として、pdflatex 用の graphicx のドライバ pdftex.def は標準で .eps という拡張子に対応していない。このため、代替策として epstopdf パッケージを読み込むことで PDF に変換して取り込むことになっている。epstopdf パッケージはもちろん epstopdf を呼ぶわけだが、結果的に

  • -shell-escape なら epstopdf を実行
  • restricted \write18 enabled. なら repstopdf を実行

ということになる*3

さて、Path に C:\w32tex\bin だけが追加された状態で例のソースをタイプセットしてみる (restricted \write18 enabled) と、コンソールにエラーが出力される。

[Loading MPS to PDF converter (version 2006.09.02).]
)epstopdf ($Id: epstopdf.pl 36129 2015-01-24 00:30:11Z karl $) 2.23
!!! Error: Writing to c:/w32tex/share/texmf-dist/scripts/epstopdf/../../../../bi
n64/rungs failed, error code 255


! Package pdftex.def Error: File `abcdef-eps-converted-to.pdf' not found.

See the pdftex.def package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.5 ...degraphics[width=0.5\textwidth]{abcdef.eps}
                                                  
? 

ログファイルのほうにはもう少し別の内容が書かれていて

…
[Loading MPS to PDF converter (version 2006.09.02).]
…
Package epstopdf Info: Source file: <abcdef.eps>
(epstopdf)                    date: 2015-07-09 23:38:49
(epstopdf)                    size: 314244 bytes
(epstopdf)             Output file: <abcdef-eps-converted-to.pdf>
(epstopdf)             Command: <repstopdf --outfile=abcdef-eps-converted-to.pd
f abcdef.eps>
(epstopdf)             \includegraphics on input line 5.
runsystem(repstopdf --outfile=abcdef-eps-converted-to.pdf abcdef.eps)...execute
d safely (allowed).

Package epstopdf Info: Result file: <abcdef-eps-converted-to.pdf>.


! Package pdftex.def Error: File `abcdef-eps-converted-to.pdf' not found.

See the pdftex.def package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.5 ...degraphics[width=0.5\textwidth]{abcdef.eps}
                                                  
? 

明らかに repstopdf が呼ばれて変換に失敗したことがわかる。先ほど示した2つの対処法をそれぞれ講じてみると

  1. Ghostscript 64bit のインストール:成功
  2. bin64 フォルダを適当にリネーム:成功

となる。この場合のログは以下のとおり。

…
[Loading MPS to PDF converter (version 2006.09.02).]
…
Package epstopdf Info: Source file: <abcdef.eps>
(epstopdf)                    date: 2015-07-09 23:38:49
(epstopdf)                    size: 314244 bytes
(epstopdf)             Output file: <abcdef-eps-converted-to.pdf>
(epstopdf)                    date: 2015-07-10 00:40:40
(epstopdf)                    size: 275788 bytes
(epstopdf)             Command: <repstopdf --outfile=abcdef-eps-converted-to.pd
f abcdef.eps>
(epstopdf)             \includegraphics on input line 5.
Package epstopdf Info: Output file is already uptodate.
 <abcdef-eps-converted-to.pdf, id=1, 825.0825pt x 590.205pt>
File: abcdef-eps-converted-to.pdf Graphic file (type pdf)

<use abcdef-eps-converted-to.pdf>
Package pdftex.def Info: abcdef-eps-converted-to.pdf used on input line 5.
(pdftex.def)             Requested size: 172.5pt x 123.38834pt.
…

なんだか不思議なので、epstopdf.pl や repstopdf.pl を見に行ってみると、角藤さんによる修正部分がある。スクリプト中に bin64 が登場するのは、restricted の場合の処理を定義したここだけであった。

  ##
  ## changed for W32TeX (2013/09/30 --ak)
  ##
  $kpsewhich = "$mydirname/../../../../bin64/kpsewhich.exe";
  if (-f $kpsewhich) {
    $kpsewhich = "$mydirname/../../../../bin64/kpsewhich";
    $GS = "$mydirname/../../../../bin64/$GS";
  } else {
    $kpsewhich = "$mydirname/../../../../bin/kpsewhich";
    $GS = "$mydirname/../../../../bin/$GS";
  }

おそらく、結果論からはどうやら「bin64 というフォルダが存在すれば 64bit 版を呼び、そうでなければ 32bit 版を呼ぶ」という働きをしているらしいのだが、果たしてこれで良いのだろうか?

いろいろな組み合わせで行った実験結果をまとめると

【Ghostscript 32bit がインストールされているとき】

  • W32TeX 32bit (with /bin64) --> epstopdf: OK, repstopdf: NG
  • W32TeX 32bit (without /bin64) --> epstopdf: OK, repstopdf: OK
  • W32TeX 64bit+32bit (with /bin64) --> epstopdf: NG, repstopdf: NG

【Ghostscript 64bit がインストールされているとき】

  • W32TeX 32bit (with /bin64) --> epstopdf: NG, repstopdf: OK
  • W32TeX 32bit (without /bin64) --> epstopdf: NG, repstopdf: NG
  • W32TeX: 64bit+32bit (with /bin64) --> epstopdf: OK, repstopdf: OK

問題なのは rungs と gswin**c が 32bit と 64bit で食い違う場合であることがわかった。Perl の 32bit/64bit の別は関係ないようだった。

一つの解決策は「32bit バイナリしか使わないならばそもそも 64bit バイナリをダウンロードしない」であり、もう一つの解決策は「64bit バイナリをダウンロードしたのであれば Ghostscript(と Perl)の 64bit 版をインストールする」であろう。しかし、32bit バイナリでタイプセット実行中に 64bit バイナリが呼ばれるのは意図された仕様なのだろうか? さあ、どこにどうやって問い合わせればよいのやら…

続く

*1:すなわち W32TeX について「C:\w32tex\bin と C:\w32tex\bin64 の両方が存在するが、Path は C:\w32tex\bin だけに通っている」という状態で、Ghostscript は 32bit 版インストーラを使用して C:\gs\gs9.10\bin と C:\gs\gs9.10\lib に Path が通った状態である。

*2:ちなみに両者のスクリプト epstopdf.pl と repstopdf.pl は中身が同一で、実行ファイル名によって動作を切り替えるというよくある仕組みである;例えば extractbb が dvipdfmx のシンボリックリンクであることと似ている。

*3:例えば abcdef.eps は abcdef-eps-converted-to.pdf という名称の PDF ファイルに変換される。もし既に abcdef-eps-converted-to.pdf というファイルがあれば、変換作業はスキップして直接この PDF を読み込む。もし存在しなければ epstopdf/repstopdf で変換を行う。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証