Python Extension Technical Details

This document covers the technical details of FontForge’s Python extension module, including building wheels for PyPI distribution.

Modules

FontForge provides two Python modules:

  • fontforge - Main font manipulation API

  • psMat - PostScript matrix operations

Build Scenarios

Scenario

Detection

GUI

Install Location

Wheel (pip)

SKBUILD defined

OFF

Wheel root

System install

Manual cmake

ON/OFF

site-packages

Dependencies

Required (always linked):

libxml2, zlib, libiconv

Bundled in wheels:

FreeType, libpng, libjpeg, libtiff, libspiro, woff2

Not needed for wheels (GUI-only):

GLIB, Gettext/Intl, Readline

Versioning

The source uses PROJECT_VERSION = 20251009 (YYYYMMDD format). Wheels use CalVer format 2025.10.9.

fontforge.version() returns:

  • CalVer when imported as a module (from site-packages or wheel)

  • Numeric format when Python is embedded in the running FontForge application

CMake transformation:

string(SUBSTRING "${PROJECT_VERSION}" 0 4 _FF_YEAR)
string(SUBSTRING "${PROJECT_VERSION}" 4 2 _FF_MONTH)
string(SUBSTRING "${PROJECT_VERSION}" 6 2 _FF_DAY)
math(EXPR _FF_MONTH_INT "${_FF_MONTH}")
math(EXPR _FF_DAY_INT "${_FF_DAY}")
set(FONTFORGE_PYTHON_VERSION "${_FF_YEAR}.${_FF_MONTH_INT}.${_FF_DAY_INT}")

Windows MSVC Build

Windows wheels require MSVC because Python.org’s Windows Python is built with MSVC. The MinGW build continues for the GUI application.

MSVC compatibility patterns:

// UNUSED macro
#ifdef _MSC_VER
# define UNUSED(x) x
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#endif

DLL exports: MinGW uses --export-all-symbols. MSVC needs explicit __declspec(dllexport) or a DEF file.

vcpkg provides dependencies:

{
  "name": "fontforge",
  "dependencies": ["freetype", "libxml2", "glib", "gettext", "libiconv", "zlib"]
}

Build Configuration

Wheels are built using scikit-build-core. See pyproject.toml for the current configuration.

[build-system]
requires = ["scikit-build-core>=0.5"]
build-backend = "scikit_build_core.build"

[project]
name = "fontforge"
dynamic = ["version"]

[tool.scikit-build]
cmake.args = ["-DENABLE_GUI=OFF", "-DENABLE_PYTHON_EXTENSION=ON"]
wheel.install-dir = "."

Wheel Target Platforms

The project builds wheels for:

  • Linux: x86_64, aarch64 (manylinux_2_28)

  • macOS: x86_64, arm64 (separate wheels, macOS 11.0+)

  • Windows: x64 (MSVC)

Install Conflict Handling

App installs create fontforge-{version}.dist-info/ with INSTALLER = fontforge-app. This allows pip list to show the install and pip uninstall to work.

If a pip-installed version exists, app install skips and suggests pip uninstall fontforge.