Choosing the Right LaTeX Engine for OpenType Fonts and Unicode: pdfLaTeX vs XeLaTeX vs LuaLaTeX
Choose a LaTeX engine for OpenType fonts and Unicode input, with a minimal fontspec example and checks for glyph coverage, font embedding and portability.
16 Jun 2025, 06:14 UTC

Choose an engine from the document's requirements
If a LaTeX document needs to load an OpenType font by name or filename, start with XeLaTeX or LuaLaTeX and the fontspec package. Keep pdfLaTeX when an existing template requires it and its font and character support already meet the document's needs. LuaLaTeX is the appropriate choice when the document or a package specifically requires LuaTeX's embedded Lua facilities.
Unicode input, font coverage and language layout are separate concerns. A compiler can read a character without the selected font containing its glyph. Arabic shaping, right-to-left layout, mathematics and color emoji can need additional fonts, packages and engine-specific configuration. Switching the compiler alone does not provide all of these features.
Compare the capabilities that affect your project
| Engine | Text font workflow | Character support | When to choose it |
|---|---|---|---|
| pdfLaTeX | Uses traditional TeX font packages and encodings; it cannot use fontspec to load arbitrary system OpenType fonts. | Can read UTF-8 input, but the available characters depend on input mappings, font encodings and installed packages. | Your publisher or established template requires pdfLaTeX and its supported fonts cover your content. |
| XeLaTeX | Loads supported OpenType and TrueType fonts through fontspec. | Accepts Unicode input; the font must contain the required glyphs and the language setup must suit the text. | You need a straightforward Unicode and OpenType font workflow without LuaTeX-specific features. |
| LuaLaTeX | Loads supported fonts through fontspec, using luaotfload for font loading. | Accepts Unicode input with the same need to check glyph coverage and language configuration. | A package, font workflow or document customization requires LuaTeX's embedded Lua facilities. |
XeTeX does not provide LuaTeX's embedded Lua interpreter. Do not choose XeLaTeX expecting LuaTeX-specific commands to work. There is also no universal speed ranking for these engines: package choices, font caches, document size and the build machine affect compilation time. Measure the actual project if build duration is a constraint.
A minimal OpenType and UTF-8 document
Use a TeX distribution with XeLaTeX or LuaLaTeX, fontspec and the Latin Modern fonts installed. Save the following text as UTF-8 in main.tex. Latin Modern Roman avoids assuming that a proprietary system font such as Helvetica is present. A minimal TeX installation may still require you to install the font and package using its package manager.
\documentclass{article}
\usepackage{fontspec}
\setmainfont{Latin Modern Roman}
\begin{document}
Café, naïve, façade — a small UTF-8 example.
\end{document}
From a terminal in the directory containing main.tex, run one of these commands as your normal user. The second command is an alternative engine invocation; both are not needed to build the document.
xelatex -interaction=nonstopmode -halt-on-error main.tex
lualatex -interaction=nonstopmode -halt-on-error main.tex
The LuaLaTeX command is lualatex. These commands write main.pdf and auxiliary files in the current directory, so use a project directory where replacing those build outputs is acceptable. This example does not require shell escape or administrator privileges. Do not compile this fontspec example with pdfLaTeX; the package requires XeTeX or LuaTeX.
Check fonts, glyphs and portability
- Check the compiler exit status and read
main.log. Resolve missing-package, missing-font and missing-character diagnostics before relying on the PDF. - Open
main.pdfand inspect the accented characters, punctuation, line breaks and any other characters your real document uses. Successful compilation alone does not prove that every glyph rendered correctly. - If Poppler's
pdffontsutility is installed, runpdffonts main.pdfand inspect theembcolumn for embedded fonts. ACIDfont type is not by itself an embedding failure. Subset font names can contain a generated prefix. - Build on the target CI machine or another supported computer with the same engine, packages and fonts. Record those dependencies so a local system font does not become an accidental requirement.
If you replace Latin Modern Roman with another font, install that font and confirm that its license permits your intended distribution and embedding. Do not assume that a missing font will automatically fall back to an equivalent. For characters absent from the selected font, choose a font that covers them and configure it explicitly.
Extend the example only when the document needs it
The example deliberately uses Latin text with accents. It does not demonstrate Cyrillic, Arabic or emoji coverage. For multilingual documents, consult the documentation for your language package and the selected fonts. For Unicode and OpenType mathematics, unicode-math provides a separate XeLaTeX/LuaLaTeX workflow and requires a suitable mathematics font; changing the text font with fontspec does not change mathematics automatically.
Begin with the small document, confirm it works in the intended environment, and then add the actual template, languages and packages one at a time. That makes a failure easier to attribute to font availability, package compatibility or the document's own configuration.
Package references
- The LaTeX3 project's fontspec documentation and examples describe font selection with XeTeX and LuaTeX.
- The LaTeX3 project's unicode-math documentation describes OpenType mathematics and supported mathematics fonts.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.