8 Installation
dxtr edited this page 2026-10-18 16:20:21 +02:00

Installation

Requirements

HarfBuzz the libharfbuzz shared library, 7.0 or newer, at load time
Lisp SBCL
Lisp libraries cl-ffi, uiop (plus cl-ft2 for cl-harfbuzz/ft2, parachute for the tests)
C toolchain none: struct layouts are written by hand with cl-ffi's C-sized types, so nothing is compiled

Linux

Install the runtime package. On Debian and Ubuntu:

apt install libharfbuzz0b

cl-harfbuzz loads libharfbuzz.so.0 (falling back to libharfbuzz.so). No -dev package is needed. For cl-harfbuzz/ft2, cl-ft2 also needs libfreetype6.

macOS

brew install harfbuzz. cl-harfbuzz looks for libharfbuzz.0.dylib, then libharfbuzz.dylib, on the dynamic linker's search path. Note that macOS is not tested in CI.

Windows

There is nothing to install. Windows ships no HarfBuzz, so cl-harfbuzz carries its own build in native/windows-x64/harfbuzz.dll (HarfBuzz 14.6.0, x86-64) and loads it by full path, so no other harfbuzz.dll on PATH gets in the way.

  • The DLL is HarfBuzz's single-file build with hb-ft (FreeType integration, used by cl-harfbuzz/ft2) and without glib, ICU, Graphite or the Uniscribe/DirectWrite shapers. (hb:shapers) lists "ot" and "fallback".
  • It delay-loads freetype.dll, so plain cl-harfbuzz loads without FreeType. FreeType's functions are resolved the first time hb-ft calls one, by which time cl-ft2 has loaded its own freetype.dll.
  • Delivered applications. An image saved without cl-harfbuzz's source tree cannot use the full path, so it loads harfbuzz.dll by name; Windows looks next to the executable first. Ship harfbuzz.dll beside your .exe, together with cl-ft2's freetype.dll if you use cl-harfbuzz/ft2. HarfBuzz's license is in native/windows-x64/HARFBUZZ-COPYING.
  • The DLL is reproducible: native/build-windows.sh rebuilds it from the pinned source and --check verifies the committed one. See Development.

If the library cannot be loaded, loading the system signals a harfbuzz-error that lists the files it tried and whose hint names what to install (on Windows, it tells you to restore the DLL from the repository). See Errors.

Loading

cl-harfbuzz is not in Quicklisp; its dependencies are pinned with stift. In a project of your own, stift get https://fakehacker.cc/dxtr/cl-harfbuzz.git requires cl-harfbuzz, and its stiftfile brings cl-ffi and cl-ft2 along. In a checkout of cl-harfbuzz, the repository's stiftfile pins them, and stift exec starts a Lisp that finds them:

stift exec sbcl

Then load the systems with ASDF:

(asdf:load-system :cl-harfbuzz)        ; shaping, outlines, paint, OpenType data
(asdf:load-system :cl-harfbuzz/ft2)    ; optional: HarfBuzz fonts on cl-ft2 faces

cl-harfbuzz/ft2 needs cl-ft2, which plain cl-harfbuzz does not load.

Checking it works

In a package that gives cl-harfbuzz the local nickname hb, as shown below the table of packages:

(hb:harfbuzz-version)   ; => 12, 3, 2   (major, minor, micro as three values)
(hb:shapers)            ; => ("graphite2" "ot" "fallback")   on Debian's build

The packages:

Package Use
cl-harfbuzz everything in this wiki unless stated otherwise
cl-harfbuzz/ffi the raw layer, on cl-ffi, see FFI layer
cl-harfbuzz/ft2 make-ft2-font, with-ft2-font, ft2-font, ft2-font-face

The packages have no global nicknames, so they take no names from the rest of your image. The examples in this wiki are written in a package that gives them local nicknames, hb for cl-harfbuzz and ft2 for cl-ft2:

(defpackage #:my-text
  (:use #:cl)
  (:local-nicknames (#:hb #:cl-harfbuzz)
                    (#:ft2 #:cl-ft2)))     ; only after loading cl-ft2
(in-package #:my-text)

Leave out cl-ft2 when you do not load it: a local nickname needs its package to exist.

With local nicknames nothing clashes. A package that :uses cl-harfbuzz together with another must shadow the names both export: glyph-index with cl-ft2, color with cl-svgread, script with sb-unicode, name-id, color and tag with cl-harfbuzz/ffi, whose struct slots have those names, and glyph-index, name-id and tag with cl-ft2/ffi, for the same reason.