読者です 読者をやめる 読者になる 読者になる

Acetaminophen’s diary

化学に関すること,TeXに関すること,ゆきだるまに関すること。

TeX Live 2016 の新しい LuaTeX あれこれ

【最終更新 2016/06/11 16:28】luatex85 パッケージの注意点として挙げていた件について “失敗する実例” の情報をいただいたので追記、冒頭の LuaTeX に対する意見を追加。

【記事公開 2016/04/23 14:19】W32TeX の LuaTeX が新しいものに置き換わったようなので、ひとまず公開します。まだ対処法は流動的ですが、現時点で有効そうなものを書いてあります。

久々の更新。今回は、既にあちこちで噂されているように相当新しくなった LuaTeX について説明します。まず LuaTeX の変更点を概説してから(ここまでは“カジュアルな LaTeX ユーザ”は難しければ読み飛ばしてもよいです)、次に LuaLaTeX を使ううえでつまずきそうな点の対処法をいくつか紹介します。

説明に入る前に:LuaTeX はいいぞ?

巷では「LuaTeX はいいぞ」という言及をよくみかけます。しかし、本当にそうなのでしょうか? たしかに LuaTeX は強いと私は思いますが、自分の目的に合っていないと思うときには (u)pLaTeX + dvipdfmx などの方法を使っています。

あなたにとって LuaTeX (LuaLaTeX, LuaTeX-ja) とはなんですか?

これに対する明確な答えがあるなら、ぜひとも LuaTeX を使いましょう。もし「ただなんとなく」「新しそうだから」「人が LuaTeX はいいぞと言っているから」という消極的な理由なら、いま一度「LuaTeX 使用によって起きるトラブルに自分で立ち向かう覚悟はあるか」と天秤にかけてみるとよいかもしれません*1LuaTeX はついに 2016 年中に Ver. 1.0 をリリースする予定であることが公表されていて、ここでようやくベータ版を脱却して “まともに使える正式版” となることが期待されます。LuaTeX のメリットを正当に評価してうまく活用したいものです。

【誤解を防ぐために】上の主張は「○○というツールは〜に使うべきだ」を意図したものではありませんし、開発者の意見を代弁するものでもありません。ツールをどのように使うかは、使う人の完全な自由です。開発者が想定していない使いかたであっても、それが使う人にとって望むものだったなら、誰にも止める権利はありません。ただ、使うのであればその長所も短所も素直に受け入れることが、使う人にとっても作った人にとっても幸せだと私は思います。特にそのツールを無料で使わせてもらっている場合にはなおさら、作者への感謝(可能ならば改善案などのフィードバック)を忘れてはいけません。

【さらに注意】上記は「自分で好きなエンジンを選択して文章を書いてよい」という場合の話です。ソースを複数人でやりとりする場合にはもうひとつの観点が必要です。

本記事にあるとおり、LuaTeX や周辺パッケージはどんどん仕様が変わっています。したがって、手元ではコンパイルできても相手方ではコンパイルできない(あるいはレイアウトが変わる)ということが往々にしてあります。また、論文投稿規定自体に「pLaTeX で書いてください」「LuaTeX はダメです」のようにエンジンがはっきり指定されていることはまずないでしょう。しかし、特に日本語の場合には「配布されているクラスファイルがそもそも pLaTeX しか想定していない → 事実上 pLaTeX 以外ダメ」というケースがほとんどです。このような場合には、事前に関係者と相談して環境を統一しておくとトラブルを未然に防げることもあります。くれぐれも締切間近になって初めて問題点に気づくということのないように注意しましょう。

 

目次(タイトルだけでも参考になるかもしれません)

 

TeX Live 2016 の LuaTeX の新しいところ

とにかく、いろいろ変わりました。とはいっても、当面の間はカジュアルな LaTeX ユーザが喜びそうなのは「OS X を El Capitan にアップグレードしてヒラギノフォントが LuaTeX で使えなくなってしまった」という人くらいでしょうか…

1. LuaTeX が OpenType Collection (OTC) フォントに対応した

一応簡単に説明しておくと、OpenType Collection とは「OpenType (.otf) フォントを束ねたもの」で、ちょうど「TrueType (.ttf) フォントを束ねたもの=TrueType Collection (.ttc) フォント」と同様の関係です。ただし、OTC も拡張子は .ttc を流用してあるので気づきにくいという状態にあり*2OS X 10.11 El Capitan 以上では日本語フォントの多くも標準でこの OTC 形式でバンドルされるようになりました。私が知る範囲では、フリーフォントでは Adobe の SourceHanSans(源ノ角ゴシック)系だけです。

この OTC フォントが新しすぎる形式なのでpTeX 系と一緒に用いる dvipdfmx はどうにか対応を完了していました(万歳!)が、TeX Live 2015 時点で LuaTeX は未対応でした。このため、TeX Live 2015 の状態 (LuaTeX beta-0.80.0) では「LuaTeX-ja で El Capitan のヒラギノなどが使えない」という状況になってしまいました。LuaTeX beta-0.81.0 で OTC 対応コードが入りましたので、結果的に TeX Live 2016 では「LuaTeX-ja で El Capitan のヒラギノが使える!」となりそうです。

2. プリミティブ名がすごーくたくさん変わった

以降は LuaTeX の開発思想や方針に絡むので、ここで(僕の理解を)説明しておきます。

LuaTeX はいままで「本家 TeX のさまざまな拡張の集大成」のような状態でした。この時点では「LuaTeX = おもに“欧米ではスタンダード”な pdfTeX をベースにほかの拡張版 TeX(Ωとか)のプリミティブを追加したもの」と考えても差し支えなかったわけです。このため、いままでは「pdfTeX 用に書かれたパッケージやコードが LuaTeX でもそのまま動く」という流用が可能でした。ところが、LuaTeX の開発方針はそことは違うところにあり、「本家 TeX やその他エンジンの不合理な点や変態な挙動は正す」という変更が積極的に行われました。LuaTeX はまだベータ版なので、互換性はそれほど重視しなくてよいということでしょう。

プリミティブ名の変更として、LuaTeX はたとえば pdfTeX 由来の \pdfナントカ というプリミティブ*3の接頭辞を取り払うように変更しました。というのも、pdfTeX の多くの拡張機能は「PDF 出力そのもの」にかかわるとは限らず、それらに PDF という名前を付けているのは LuaTeX 的に良くないということだと思います。そうして、分かりにくいプリミティブ名(と判断されたもの;たとえば画像とりこみ機能のプリミティブ)は積極的に新しい名称を与えられることとなりました。

3. 「\write18 で外部コマンド実行」(や「\write16 でコンソール出力」)が廃止

新しい LuaTeX では \newwrite で使えるレジスタの数が従来の16個まで(0 ... 15)だから128個(0 ... 127)に拡張されました。これにともない、いままでは \write18{...} と書けば TeX から外部コマンドを呼び出して実行できたという仕組みも削除されました。そもそも LuaTeX には別途 \directlua という「Lua コードを直接動かす仕組み」がありますので、これを経由して外部コマンドを実行できたわけです。それに、一般的な感覚からすれば18番を外部コマンド実行として特別扱いするのは“変態”といわれても無理はないと思います*4

18番だけでなく16番も同様です。コンソールにメッセージを出力するために \write16{...} と書いていた人もいるようです*5が、これももはや安全とはいえなくなりました。

4. PDF 出力モードでの \mag サポート廃止

pLaTeX や upLaTeX で jsarticle などの「新ドキュメントクラス」を使っている人の中には聞いたことがあるかもしれない \mag という版面拡大機能が、LuaTeX beta-0.87.0 以降の PDF 出力モードでは廃止されました。機能そのものが廃止されたため、もし \mag を使うコードを書いていた場合はおかしな出力になってしまい、直接的な代替措置もないという状況です。この \mag は時に問題を引き起こすことが知られていますし、そもそも文書クラスが \mag を使って版面拡大することは筋が悪いという意見もときどき見かけます。おそらく LuaTeX も都合の悪い機能は排除したかったのでしょう。

 

LuaLaTeX ユーザのトラブルシューティング・マニュアル

さて、いよいよ「対策」を紹介することにしましょう。これだけ LuaTeX には多くの変更が加わりましたので、従来のソースが新しい LuaTeX ではタイプセットが通らないという事象に必ず遭遇するといっても過言ではないと私は思います。こうしたトラブルにどう対処するか、今の段階でわかっていることを列挙しておくことで、LuaLaTeX や LuaTeX-ja 愛用者の「LuaTeX beta-0.95.0 で困った!」に少しでも手助けできれば幸いです。先に「本記事の更新時点でユーザが対処する必要のあるもの」を優先して並べ、そのあとに「既に対策済みのパッケージ」も参考までに紹介します。LuaTeX 本体や周辺のパッケージの開発者の方々への敬意を表します。

対処法へ入る前に:そのパッケージは最新ですか?

新しい LuaTeX で エラーが出た場合は、とりあえずそのパッケージを最新版に更新できないか試してみましょう。「たまたまインストールされているのが新 LuaTeX に未対応で、最新版は対応済み」という場合も十分考えられるからです。ちなみに

パッケージ開発者が問題を把握 → 修正版を開発 → CTAN へアップロード → TeX Live 収録

という流れになっていることも、この際覚えておくと便利です。

対策 (1) :\pdfナントカ が未定義と怒られる → luatex85 パッケージ!

新しい LuaTeX でソースを処理していて最も多く出くわすと思われるエラーが

! Undefined control sequence.
(略) ->\pdfナントカ 
                  ...
l.10 \hoge
?

というものです。このように \pdfナントカ という命令が Undefined だと言われた場合は、pdfTeX のプリミティブが名称変更されたことが原因だと疑って、luatex85 パッケージを一度試してみましょう。luatex85 パッケージは LaTeX3 チームの作で、「新しい LuaTeX を pdfTeX にみせかける」という機能を提供します。使いかたは

\RequirePackage{luatex85}
\documentclass{article}

のように、文書クラスより前に \RequirePackage{luatex85} と書き込むのがベストです。いくつかの実例をみていくことにしましょう。

実例 (1-1):standalone を使いたい → luatex85 パッケージ

用紙サイズを出力にあわせてクロップしたいときに用いる standalone クラスは

\documentclass{standalone}
\begin{document}
Hello, \LaTeX!
\end{document}
! Undefined control sequence.
\sa@placebox ->\newpage \global \pdfpagewidth 
                                              =\wd \sa@box \global \pdfpageh...
l.4 \end{document}
                
? x

のようにエラーが出ます。このエラーは luatex85 パッケージを使えば一発で解消します。

実例 (1-2):geometry を使いたい → luatex85 パッケージ

一見エラーなく終了しますが、いざ出てきた PDF をみると用紙サイズが A4 のまま変更されていないという例です。こちらも LuaTeX の新しいバージョンを geometry が知らないために起こるようです。

\documentclass{article}
\usepackage[b6paper]{geometry}
\begin{document}
Hello world.
\end{document}

geometry が依存している ifpdf パッケージが新しめ (2016/04/04 v3.0) ならこのコードは PDF 出力モードで動く…はずなのですが、geometry が LuaTeX に未対応なせいで、pdftex という誤ったドライバが指定されてしまいます。これもやはり luatex85 パッケージで一発解消します。

ほかにも、「\pdfナントカ が未定義」という文言以外のエラーにも luatex85 パッケージが有用なこともあります。KOMA-Script の scrartcl クラスの例です:

\documentclass{scrartcl}
\begin{document}
Hello
\end{document}
./test.tex:2:Missing number, treated as zero.
<to be read again>
p
l.2 \begin{document}

? 

これも実は KOMA-Script が新しい LuaTeX に未対応であることが原因で、luatex85 パッケージが解決してくれるようです。

【注意点】このように結構有用な luatex85 パッケージですが、あくまで応急処置だとお考えください。luatex85 パッケージは「新しい LuaTeX のプリミティブを pdfTeX のプリミティブ名にコピーする」というものですが、一部の命令は実装上の差異のため「途中の展開過程が異なることによるエラー」が発生するかもしれません。

(追記:2016-06-10)実際に luatex85 パッケージで対処できない例の情報をいただきましたので、紹介します。この場合の対処法としては、新 LuaTeX に対応した datetime2 パッケージへ更新することです。

対策 (2) :外部コマンドが実行されない → shellesc パッケージ!

\write18 という仕組みで外部コマンドを実行するようなコードがあった場合、もはや LuaTeX beta-0.95.0 では何も起こりません。もし仮に自分の書いているコードや使っているパッケージが「外部コマンドを実行する」というものだった場合、プリアンブルに

\usepackage{shellesc}

と書いてみましょう(もちろん文書クラスより前に \RequirePackage{shellesc} と書いても OK です)。shellesc パッケージは LaTeX チームが「ほかの TeX エンジンと同様に、やっぱり LuaTeX でも \write18 が動かないと困る」という場合の対処法として作成したもので、LaTeX 2016/02/01 以降に付属しています。

実例 (2-1):TikZ の external ライブラリを使いたい → shellesc パッケージ

TikZ の external ライブラリは -shell-escape オプションによって外部コマンドを実行し、図を作成します。しかし、現在は \write18 という書式を使っているため失敗し、エラーが出ます。

\RequirePackage{luatex85}
\documentclass{article}
\usepackage{pgfplots}
\usepgfplotslibrary{external}
\tikzexternalize
\begin{document}
\begin{tikzpicture}
\end{tikzpicture}
test
\end{document}
! Package tikz Error: Sorry, the system call 'lualatex -shell-escape (中略)' did NOT result
in a usable output file 'test-figure0' (expected one of .pdf:.jpg:.jpeg:.png:).
Please verify that you have enabled system calls.
For pdflatex, this is 'pdflatex -shell-escape'.
Sometimes it is also named 'write 18' or something like that.
Or maybe the command simply failed?
Error messages can be found in 'ad-figure0.log'. If you continue now,
I'll try to typeset the picture.

この問題も shellesc パッケージで見かけ上解消します(上の例ではソース最小かのためそもそも図を使っていないので微妙ですが、きっと役に立つはず!)。

【余談】私が開発している chemobabel パッケージ (GitHub) も外部コマンド実行の仕組みを使っています。これは shellesc パッケージに頼らずに「LuaTeX の場合は特別に \directlua で外部コマンドを実行する」という場合分けを導入してあります。このように LuaTeX なら \write18 を使わない書き方を心がけるほうが better だと思いますので、今後 \directlua の活用が増えることを願います。

 

新しい LuaTeX に既に(なんらかの)対策済みのパッケージたち

LuaTeX-ja を使いたい → 対処済み(LuaTeX-ja 20160505.0 + luaotfload v2.7)

LuaTeX beta-0.95.0 に対応するために LuaTeX-ja にも多くの改訂が施され、見た目には今までどおり使えるようになりました。ただし、luaotfload という「LuaTeX でフォントを読み込むパッケージ」の仕様も LuaTeX beta-0.95.0 に向けて変更されていますので、これまでとはフォント読み込みの仕組みが微妙に異なることに注意してください(luaotfload v2.6 までは LuaTeX 組み込みの fontloader を使っていましたが、今度の v2.7 からは独自実装の Lua モジュールでフォント読み込みを行うという点が最も大きな変更です)。

もう少し詳しく:実はこの LuaTeX-ja は、相当 LuaTeX まわりの仕様変更の影響を受けたパッケージの一つだと思います。

  1. LuaTeX-ja 20160404.0 で、ltjsarticle などの「新ドキュメントクラス互換 LuaTeX-ja 用クラスファイル」が従来の jsarticle と異なり \mag を使わずに実装された(具体的には「BXJS クラス」の magstyle=xreal 相当)。これで PDF 出力モードでの \mag 廃止に対応。
  2. LuaTeX-ja 20160421.0 で glue node の仕様変更に対応(これで初めて luaotfload v2.6 との組み合わせで正常に動くようになった)。
  3. luaotfload v2.7 が偶然同日 (2016/04/21) にリリースされ、これと LuaTeX-ja が齟齬を来してしまった。LuaTeX-ja 20160505.0 で一通り対応(Ticket #36276)。

graphicx や (x)color を使いたい → 対処済み(luatex.def の新設)

よく知られているとおり graphicx や color の機能は TeX 本来の機能ではなく、実際に機能を提供するのは PDF 出力を担当するドライバです。これらの「ドライバ依存パッケージ」は LuaTeX の仕様変更(プリミティブ名変更)の影響をモロに受けました。ただし、graphicx や color は LuaTeX beta-0.95.0 以降でも正常に動作するように「LuaTeX ドライバ向けの定義ファイル」が新設されています。つまり、この LuaTeX 向け定義ファイル luatex.def がインストールされていれば、graphicx や (x)color は LuaTeX beta-0.95.0 以降に対処済みといえます。

もう少し詳しく:従来 LuaTeX は pdfTeX とプリミティブが互換だったため、graphicx や color は「pdfTeX ならドライバは pdftex と自動判定」という仕組みに LuaTeX も便乗していました。実際、自動判定どおり pdftex ドライバファイル (pdftex.def) が機能していたので、それで問題なかったわけです。しかし、LuaTeX beta-0.85.0 以降のプリミティブ名変更で「pdftex.def に使われているプリミティブの多くが LuaTeX に存在しない」という事態に陥りました。これが「LuaTeX のプリミティブに対応した luatex.def の新設」と「LuaTeX ならドライバを luatex と自動判定する仕組みの導入」で解消しました。つまり今後、もしドライバ省略せずに明示したい場合は \usepackage[luatex]{graphicx,xcolor} のように書けばよいことになります。

hyperref を使いたい → 応急処置済み(LaTeX3 Team パッチ版または v6.83n 以降)

hyperref もやはりドライバ依存パッケージで、LuaTeX のプリミティブ名変更の影響を受けています。この変更に対応するため、LaTeX3 チームが hyperref に 2016/04/19 付でパッチを加えて“新しい LuaTeX でも一応動く hyperref パッケージ”として発表しました。これは既に TeX Live 2016 pretest や W32TeX [2016/04/21] に取り込まれています。

もう少し詳しく:hyperref のメンテナである Oberdiek さんは忙しすぎるようで、LuaTeX のプリミティブ名変更に対応した「新しい LuaTeX 向けドライバ定義ファイル」を発表していません。LaTeX3 チームによるパッチは先述の luatex85 パッケージを hyperref に読ませるという安易なものですが、見かけ上 hyperref のドライバ依存コードが動くという算段になっています。最近はさらに進んで、hyperref v6.83n 以降は徐々にではあるが「luatex85 に頼らない hyperref」を目指しているようです。Oberdiek さんに代わってその作品をメンテナンスする Oberdiek Package Support Group という組織がつくられ、GitHub にリポジトリを移して hyperref の更新が続いています。是非積極的に Pull request しましょう!

TikZ (PGF) を使いたい → 対処済み(pgfsys-luatex.def などの新設)

TikZ もやはり LuaTeX のプリミティブ名変更の影響を受けています。そこで、Norbert Preining さんが「LuaTeX 用の新しいドライバファイル*6」を作成し、TikZ (PGF) の開発者である Till Tantau 氏の許可を得て TeX Live に追加してくださいました (TeX Live r40966, W32TeX 2016/05/09) 。

もう少し詳しく:蛇足ですが、2016/05/08 時点の TeX Live 2016 pretest では以下のようなエラーが出ていました。

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
  \fill (-1,2) circle [radius=0.5];% まる
  \draw (-1,-1)--(-0.5,0)--(0,-1)--cycle;% さんかく
  \draw (1,0.5) rectangle (2,1.5);% しかく
\end{tikzpicture}
\end{document}
! Package pgf Error: Driver file ``pgfsys-luatex.def'' not found..

See the pgf package documentation for explanation.
Type  H   for immediate help.
 ...                                              
                                                  
l.988 ...{Driver file ``\pgfsysdriver'' not found.}}
                                                  
? 

これは、せっかく graphicx や color が自動判定で [luatex] ドライバ (luatex.def) を使ったにもかかわらず、PGF 用の LuaTeX 向けドライバ pgfsys-luatex.def が存在しないためでした。これもやはり応急処置としては luatex85 パッケージを使った

\RequirePackage{luatex85}
\def\pgfsysdriver{pgfsys-pdftex.def}
\documentclass{article}
\usepackage{tikz}
\begin{document}
(略)
\end{document}

が有効ではあるのですが、やっぱり綺麗な解決法は def ファイルの新設です。というわけで、Norbert さんに感謝!

Beamer を使いたい → 対処済み(pgfsys-luatex.def の新設)

Beamer は内部で PGF のパッケージを読み込んでいますので、上の TikZ (PGF) の解説に準じます。

 

最後に

TeX Live 2016 が正式リリースされても、全てのパッケージが「新しい LuaTeX」に対応完了するとは期待できません。しばらくの間は、ユーザの皆さんで LuaTeX でのエラー対策を行う必要が生じると思います。そのようなときに、この記事を参考に試行錯誤してどうにか乗り越えていただければ幸いです。

また、パッケージが新しい LuaTeX に未対応だと発見した場合は、積極的に開発者にメールなりリクエストしてみましょう。そもそも開発者が問題に気付いていないことも考えられますし、パッチを作って Pull request できるとなおよいでしょう。皆さんの力で LuaTeX の試練を乗り切っていきましょう。

*1:参考までに、私が「LuaTeX は強い」と思う理由を挙げておきます:

  • Unicode 対応
    • upLaTeX も Unicode 化されているけれど LuaLaTeX のほうが完全(数式フォントなども Unicode 化できるので文字情報が正しくなる)。
  • 好きなフォント(欧文・和文、等幅・プロポーショナル問わず)を使える
    • Lua モジュールで OpenType / TrueType フォントを毎回その場で読み込む能力があるので、pTeX のように面倒な TFM (TeX Font Metric) をいちいち準備しなくて済む。
    • ただし、その裏替えしとして LuaTeX は処理は遅い。変則的なメトリクスのフォントでなければ pLaTeX の pxchfon パッケージで十分通用する。
  • デフォルトで使える数式フォントの種類が多い
    • 最近の (u)pLaTeX は e-(u)pTeX で動いていて、FAM256 拡張されているので、頑張れば数式フォントの種類を増やせる。
    • ただし、LuaTeX に対しては LaTeX がデフォルトで数式フォントを多数使えるようにサポートしているので、難しいコードが不要。
  • PDF 直接出力、組み込み MetaPost サポートが充実
    • TikZ はほとんどの機能が dvipdfmx でも使えるが、若干 pdfTeX/LuaTeX のほうが多い(個人的にはそんなに気にならない程度)。
    • ただし本記事で述べているとおり LuaTeX が仕様変更したことで、pdfTeX 向け TikZ モジュールが若干 LuaTeX で動きづらくなった。
  • Lua コードをゴリゴリ書いて計算・多機能化できる
    • パッケージが Lua で書かれている例も最近は増えてきた。

これらのことから、現在私が LuaTeX を使うのは事実上「プロポーショナルフォントを使いたいとき」「Lua コードでゴリゴリ書かれたパッケージを使いたいとき」に限られています。

*2:おそらく他のソフトウェアのサポート状況を考慮したものだと思います。

*3:pdfTeX は自分が独自に拡張実装したプリミティブについて“識別用符号”のような接頭辞として pdf... を付けている。

*4:もともとこのような特別扱いが必要だったのは、制限の多かった古い時代の遺物です。

*5:レジスタ16番は絶対に使われないから、今までは「あくまで慣習的に」コンソール出力として使われてきた、というのが実情のようです。

*6:具体的には pgfsys-luatex.def と pgflibrarypgfplots.surfshading.pgfsys-luatex.def がそれにあたります。