Skip to content

kriptolix/pfmg

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pfmg — Python Flatpak Module Generator

Warning

For the sake of honesty, it's important to say that most of the code in this package was written by Claude. Although I reviewed the code in general, I didn't review every single line in detail. Please use it accordingly and report any issues you find.

A modern, probe-first replacement for flatpak-pip-generator.

Instead of resolving dependencies statically on the host, pfmg installs the package inside a real Flatpak build sandbox, runs ldd on every compiled extension, checks pkg-config, and tests the import. The result is a Flatpak module JSON that you can drop directly into your manifest — with native dependency errors caught before you ever run flatpak-builder.


Requirements

  • Python 3.11+
  • flatpak installed on the host (for generate and inspect)
  • pip3 or uv available on the host (for source collection)

Installation

pip install pfmg

How it works

pfmg generate numpy
         │
         ├─ 1. Install package inside org.freedesktop.Sdk sandbox
         ├─ 2. Run ldd on every .so file → detect missing native libs
         ├─ 3. Run pkg-config on declared deps → detect missing headers / pc files
         ├─ 4. Test the Python import
         ├─ 5. Build-test the generated module (flatpak-builder dry run)
         │      └─ if a build dep is missing and resolvable on PyPI → probe it
         │         and retry automatically (up to 5 times)
         └─ 6. Write module JSON

Errors are matched against a local dataset of SDK profiles, extension profiles, and ready-to-use recipes, so you get actionable suggestions ("add org.freedesktop.Sdk.Extension.rust-stable") instead of raw linker output.


The local dataset

pfmg ships with — and continuously grows — a dataset of:

Directory Contents
data/sdk-profiles/ Profiles of base SDKs (libraries, pkgconfig, executables)
data/ext-profiles/ Profiles of SDK extensions
data/nat-recipes/ Ready-to-use Flatpak module JSON for native libraries (zlib, openssl, …)
data/pip-recipes/ Ready-to-use module JSON for Python packages with known native deps

When pfmg generate encounters an error it queries this dataset and suggests concrete actions: which SDK extension to add, which recipe to prepend to the manifest, or which --build-dep flag to pass.

Use pfmg import, pfmg inspect, and pfmg inspect-all to grow the dataset for your own extensions or SDK versions.

Commands

pfmg generate

Probe one or more Python packages and generate Flatpak module JSON files.

pfmg generate <package> [<package> ...] [OPTIONS]
Option Default Description
--sdk, -s org.freedesktop.Sdk Base SDK to use
--runtime org.freedesktop.Platform Runtime ID
--sdk-version, -V 24.08 SDK branch
--extension, -e SDK extension to activate (repeatable)
--build-dep, -b Explicit build-time PyPI dep (repeatable)
--output-dir, -o Directory to write module JSON files
--format, -f json Output format: json or yaml
--uv / --pip --uv Package installer to use inside the sandbox
--keep off Keep the sandbox work directory after probing
--raw-output, -r off Print raw sandbox stdout/stderr
--verbose, -v off Enable debug logging

Examples:

# Simplest case — latest numpy
pfmg generate numpy

# Pin a version, save the result
pfmg generate numpy==1.26.4 --output-dir ./modules

# Package that needs the Rust toolchain
pfmg generate cryptography \
  --extension org.freedesktop.Sdk.Extension.rust-stable \
  --output-dir ./modules

# Several packages at once on SDK 24.08
pfmg generate pillow lxml --sdk-version 24.08 --output-dir ./modules

# Manually hint a build-time dep (pfmg tries to auto-resolve these,
# but you can be explicit)
pfmg generate some-package --build-dep meson-python --build-dep ninja

When --output-dir is omitted the module JSON is printed to stdout. If pfmg detects errors it prints a resolution table with suggestions from the local dataset.


pfmg search

Search the local dataset for a library, package name, or executable.

pfmg search <query> [OPTIONS]
Option Default Description
--kind, -k all Filter: nat, pip, sdk, ext
--module, -m off Print the full module JSON for matching recipes
pfmg search openssl
pfmg search numpy --kind pip
pfmg search libz  --kind nat
pfmg search clang --kind ext --module

Searches SDK profiles, extension profiles, nat-recipes, and pip-recipes using the same fuzzy matching as the error resolver.


pfmg list

List all entries in the local dataset.

pfmg list [OPTIONS]
Option Default Description
--kind, -k all Filter: nat, pip, sdk, ext
--limit, -n 50 Maximum rows per table
pfmg list
pfmg list --kind nat
pfmg list --kind pip --limit 100

pfmg show

Show the full content of a recipe by its exact ID.

pfmg show <recipe-id> [OPTIONS]
Option Default Description
--kind, -k both Restrict to nat or pip
pfmg show zlib
pfmg show numpy --kind pip

pfmg summarize

Print counts of recipes and profiles in the local dataset.

pfmg summarize

pfmg inspect

Introspect a Flatpak SDK or extension and write a static profile JSON to the local dataset. Profiles are used by the resolver to match errors against known providers.

pfmg inspect <sdk-or-extension-id> [OPTIONS]
Option Default Description
--sdk-branch, -B 25.08 Branch of the base SDK
--ext-branch, -X Branch of the extension when it differs from --sdk-branch
--output-dir, -o Override the default profile output directory
--nocleanup off Don't uninstall the extension after probing
--override off Re-probe and overwrite an existing profile

pfmg auto-detects whether the target is a base SDK or an extension by looking for .Extension. in the ID.

Examples:

# Base SDK
pfmg inspect org.freedesktop.Sdk --sdk-branch 24.08

# Extension on the same branch as the SDK
pfmg inspect org.freedesktop.Sdk.Extension.node24 --sdk-branch 25.08

# Extension with its own branch
pfmg inspect org.freedesktop.Sdk.Extension.gcc8 --sdk-branch 24.08 --ext-branch 1.6

Profiles are written to:

data/sdk-profiles/<shortname>.<branch>.json   # base SDKs
data/ext-profiles/<shortname>.<branch>.json   # extensions

pfmg inspect-all

Discover every extension available on a Flatpak remote for the given SDK branches and probe them all.

pfmg inspect-all [OPTIONS]
Option Default Description
--sdk-branch, -B 24.08, 25.08 Branches to probe (repeatable)
--remote, -r flathub Flatpak remote to query
--output-dir, -o Override profile output directory
--nocleanup off Don't uninstall extensions after probing
--override off Re-probe profiles that already exist

Intended to be run once a year when a new SDK generation ships:

# Update profiles for the two current branches
pfmg inspect-all

# When 26.08 ships
pfmg inspect-all -B 25.08 -B 26.08

Extensions whose profile already exists are skipped unless --override is given.


pfmg import

Import native library and Python recipes from a shared-modules directory (e.g. a checkout of flathub/shared-modules).

pfmg import <modules-dir> [OPTIONS]
Option Default Description
--repo-root, -r . Root of the pfmg repository
--verbose, -v off Enable debug logging
pfmg import ~/src/shared-modules


About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors