Files
klammertext/doc/install/macos_source_install.md
Andy Kopra a2baaaa639 Document the mdpdf command in the source-install guides
The distribution shipped sks/tns/ and the mdpdf command in the previous
snapshot without either install guide mentioning them, so the only way to
discover the command was to read env/runtime.env.  Both source-install
guides now describe it: what it is for (Markdown that is not Klammertext,
rendered through a headless browser), that runtime.env defines it -- so a
shell started before the installation does not have it -- the two things the
distribution does not install (the renderer's virtual environment, created
by "md_to_pdf.py --setup", and a Chromium-based browser), the MDPDF_*
variables that change its defaults, and where the stylesheet is.

 (from dev d8ea0e973914)
2026-08-09 16:14:26 +02:00

8.8 KiB

Klammertext source installation on macOS (Apple Silicon)

Companion to linux_source_install.md. Verified on an Apple-Silicon Mac (arm64, macOS 26 "Tahoe"). Klammertext's core (engine, SKS, HTML/LaTeX, @image) builds and runs natively with Apple Clang; the cross-platform build environment (env/makefile.env) auto-detects the OS via uname.

1. Toolchain prerequisites

xcode-select --install            # Command Line Tools (clang, headers) — if not already present

Then install Python with a linkable libpython and python3-config, using whichever package manager you have — Homebrew or MacPorts. Both work; only the install prefix differs, and the build auto-detects it.

# Homebrew (https://brew.sh):
brew install python
brew install gcc                  # OPTIONAL: a second compiler for a standards check

# MacPorts (https://www.macports.org) — provisional, pending testing on a
# MacPorts system:
sudo port install python312
sudo port select --set python3 python312   # so python3 / python3-config resolve
sudo port install gcc14           # OPTIONAL: a second compiler for a standards check

Notes:

  • The build embeds Python, which needs python3-config and a linkable libpython. Apple's /usr/bin/python3 does not ship a usable python3-config and Apple discourages linking it — so a package-manager Python (Homebrew or MacPorts) is required. It coexists with Apple's; python3-config resolves to it when the manager's bin is early on PATH (/opt/homebrew/bin for Homebrew, /opt/local/bin for MacPorts — both set up by their installers). For MacPorts, port select --set python3 python312 makes python3 and python3-config resolve.
  • makefile.env gets all Python include/link flags from python3-config and auto-detects the package-manager prefix (/opt/homebrew or /opt/local, via MACOS_PREFIX), so either manager works without edits. Override with make MACOS_PREFIX=... if yours is installed elsewhere.

2. Image support (the @image klammer): OpenImageIO

# Homebrew:
/opt/homebrew/bin/pip3.<N> install --break-system-packages OpenImageIO
# e.g. pip3.14 — match your Python's version

# MacPorts (matches the python312 installed above):
sudo port install py312-openimageio

This provides the OpenImageIO Python bindings the embedded interpreter uses. With pip, the self-contained PyPI wheel goes into that Python's site-packages; --break-system-packages is needed because the Python is PEP-668 "externally managed". (Homebrew alternative: brew install openimageio, heavier — it pulls ffmpeg/openexr/etc.)

3. Clone and configure the environment

git clone https://git.andykopra.com/ack/klammertext.git ~/projects/klammertext
# Set up the runtime environment (KLAMMERTEXT_HOME, PATH); add to ~/.zprofile:
echo 'source "$HOME/projects/klammertext/env/runtime.env"' >> ~/.zprofile

The single self-configuring runtime.env self-locates KLAMMERTEXT_HOME from its own path. On macOS it sets no LD_LIBRARY_PATH/DYLD_LIBRARY_PATH (libklammertext.so is found via the binaries' @loader_path rpath, and document.so is dlopen'd by absolute path under $KLAMMERTEXT_HOME) and no LSAN_OPTIONS (LeakSanitizer is unsupported on macOS).

4. Build (Apple Clang)

Clang is the compiler you run on macOS, and it is the default here (makefile.env selects clang on Darwin), so no COMPILER= flag is needed. A single make -C com builds its prerequisites in mac/ and sks/ first, then the commands:

cd "$KLAMMERTEXT_HOME"
make -C com -j               # optimized (-O3) by default; libklammertext.so + sks/*.so + bin/{ktext,kdesc,kdiag}
ktext -s '@eval 1 + 1 @' -d  # smoke test — prints 2

(For a debug build with AddressSanitizer, intended for development, prefix DEBUG=1: DEBUG=1 make -C com -j.)

For a document smoke test, create a small file and render it to HTML:

cat > hello.kt <<'EOF'
@document
:structure article
:title Hello
:text
@s1 Hello, Klammertext @

This document was built from source.
@
EOF
ktext hello.kt -t html       # writes hello/index.html

(A PDF render needs TeX Live — see section 5.)

5. PDF target: TeX Live

Build a complete Klammertext TeX Live tree with the bundled script, into ~/external/texlive/<year> — the location runtime.env auto-detects (bin/universal-darwin). macOS already has curl, perl, and tar, and install-tl self-provides xz, so nothing extra is needed:

bash "$KLAMMERTEXT_HOME/doc/install/texlive_additional_packages.sh" ~/external/texlive/2026

This installs scheme-small plus the SKS's additional packages and rebuilds all formats, fetching the universal-darwin binaries, and writes a KLAMMERTEXT_BUILD_INFO.txt provenance file into the tree. This is the same command used on Linux, so the TeX Live layout is identical across your machines. runtime.env then finds the tree automatically — open a new shell (or re-source it) and xelatex is on PATH; no manual KLAMMERTEXT_TEXLIVE_BIN is needed.

If you already run BasicTeX/MacTeX and prefer to reuse it, point runtime.env at its bin directory from the gitignored escape hatch instead (and install the SKS's extra packages into it yourself — the list is in the script). Set the variable and prepend it to PATH, since runtime.env.local is sourced after the main PATH is built:

cat >> "$KLAMMERTEXT_HOME/env/runtime.env.local" <<'EOF'
export KLAMMERTEXT_TEXLIVE_BIN=/usr/local/texlive/2025basic/bin/universal-darwin
export PATH="$KLAMMERTEXT_TEXLIVE_BIN:$PATH"
EOF

Verify and test (reusing hello.kt from section 4):

xelatex --version
ktext hello.kt -t pdf         # writes hello.pdf

6. Optional: the mdpdf command (Markdown to PDF)

Klammertext ships a second, independent route in sks/tns/: mdpdf renders a Markdown file to PDF through a headless browser, bypassing Klammertext entirely. It is for a document that is not written in Klammertext — one you have not converted yet, or one whose Markdown is not worth converting.

The command is a shell function that env/runtime.env defines, so if you source that file (section 3) you already have it — in shells started after the installation. In a shell that was already running, source it again:

source "$KLAMMERTEXT_HOME/env/runtime.env"
type mdpdf                    # mdpdf is a shell function

Two things it needs that the distribution does not install:

# 1. The Markdown renderer, in a virtual environment of its own.  PEP 668
#    forbids installing it into the system Python, so this is not optional
#    and not a system package.
python3 "$KLAMMERTEXT_HOME/sks/tns/md_to_pdf.py" --setup

# 2. A Chromium-based browser -- Brave, Chrome or Chromium -- which is the
#    renderer.  Any one of them will do, and an .app in /Applications is
#    found without being told where it is.
brew install --cask chromium

Then:

mdpdf notes.md                # writes notes.pdf beside it
mdpdf notes                   # the .md may be left off

It supplies the fonts, the size matching and the code wrapping, and completes on *.md at the TAB key. Each default is a variable you may set in ~/.zprofileMDPDF_SERIF, MDPDF_SANS, MDPDF_MONO, MDPDF_MATCH, MDPDF_WRAP, and MDPDF_BROWSER for a browser installed somewhere the command does not look. Any option of the underlying md_to_pdf.py may also be given on the command line, where it overrides the default:

mdpdf notes.md --paper letter --margin 0.75

The stylesheet it applies is sks/tns/markdown.css; copy it, edit the copy, and pass --css yourcopy.css to render to your own taste.

7. Updating

To update an existing source installation to the latest version:

cd "$KLAMMERTEXT_HOME"
git pull
make -C com -j               # rebuild library, SKS components, and commands (optimized)

Rebuild the TeX Live tree only if the SKS's package requirements changed (rare); re-run the script from section 5.

Compiler notes (macOS)

  • Clang is the compiler you run, and the default here. Apple Clang builds run correctly; makefile.env selects clang on Darwin automatically.
  • Do not run gcc-built binaries on macOS. GCC (Homebrew g++-NN or MacPorts g++-mp-NN) is useful only as an optional compile-time standards check (make -C com COMPILER=gcc); the resulting binaries crash at runtime on macOS because of a gcc/macOS codegen issue (for example std::source_location returning a bad pointer, so Machine::Machine() walks into strlen and SIGSEGVs). Always run the clang-built binary. (gcc-built binaries run fine on Linux.)
  • Switching compilers requires a full cleang++ and clang++ objects must not be mixed (ABI). make -C com redo does a full clean rebuild across mac, sks, and com; a partial make -C mac clean does not.