Build PostgreSQL extensions for every supported server version
You will set up the Debian packaging workflow that uses pg_buildext to build a PostgreSQL extension for the versions supported by both your package and the current system, then install each build into its matching Debian package staging directory. Allow 20 to 30 minutes for a small extension if the source and packaging skeleton already exist. The examples describe the postgresql-common 257build1.1 installed on this machine.
The route
Jump straight to the step you need, or tick off Done means at the end.
- 1. Check the effective PostgreSQL versions
- 2. Declare the package's supported versions
- 3. Generate control files from the template
- 4. Configure and build with VPATH directories
- 5. Install into versioned package staging directories
- 6. Clean and test in the right environment
- 7. Handle non-standard source layouts
- 8. Verify the package workflow
You need a Debian source package directory containing debian/, a working extension source tree, postgresql-common, the relevant PostgreSQL server development packages, and the usual Debian packaging tools. These commands build package files under debian/; they do not install an extension into the running PostgreSQL server.
1. Check the effective PostgreSQL versions
pg_buildext takes the intersection of two lists: the versions declared by debian/pgversions and the versions in /usr/share/postgresql-common/supported-versions. Start in the top level of the source package and ask for the result:
$ pg_buildext supported-versions
16
Your output may differ. This machine currently reports PostgreSQL 16, so the examples that loop over versions will run once here. The command requires debian/pgversions. A missing file is a packaging error, not a reason to guess a version.
Checkpoint: keep this output. It is the list that build, install and clean actions will use.
2. Declare the package's supported versions
Create debian/pgversions with one entry per line. all requests every system-supported version, while NN selects one major version and NN+ selects that version and newer ones. Lines beginning with # are comments.
all
# Keep these examples as comments until you have a reason to limit support.
# 15
# 15+
all is normally the least surprising declaration when the extension has no known incompatibility. It does not override the system list: a version not present in supported-versions will still be excluded. If you need a narrow compatibility range, use explicit version lines and rerun pg_buildext supported-versions before building.
3. Generate control files from the template
Put PGVERSION in package names in debian/control.in. Put PGVERSIONS in a dependency field when a space-separated list of versioned packages is needed. A package template can look like this:
Source: postgresql-foobar
Build-Depends: debhelper, postgresql-all <!nocheck>,
postgresql-server-dev-all (>= 217~)
Package: postgresql-PGVERSION-foobar
Architecture: any
Depends: ${misc:Depends}, ${postgresql:Depends}, ${shlibs:Depends}
Generate debian/control with:
$ pg_buildext updatecontrol
This expands package sections containing PGVERSION. A PGVERSION elsewhere in a section is replaced by the newest supported version, and PGVERSIONS expands to the supported version list. If debian/tests/control.in exists, the same package-name replacement is applied there.
Include this makefile fragment in debian/rules so a build can detect that generated control files are stale:
include /usr/share/postgresql-common/pgxs_debian_control.mk
For backports and PGDG suites, checkcontrol can update the control file as part of its suite-specific behaviour. On other builds, run updatecontrol yourself and review the resulting diff before packaging.
Checkpoint: inspect the generated package names and dependencies. Do not continue with a stale debian/control, because the binary package set follows that file.
4. Configure and build with VPATH directories
For an extension with an autoconf configure script, call the action from debian/rules with a separate directory for each PostgreSQL version. The %v marker is replaced by the version:
override_dh_auto_configure:
+pg_buildext configure build-%v "--libdir=/usr/lib/postgresql/%v/lib"
override_dh_auto_build:
+pg_buildext build build-%v
The leading + matters in a makefile. It lets the sub-make communicate with the parent make jobserver. Most PGXS extensions do not need a configure action, so omit that override when the source has no configure script.
The optional -m option passes additional make variables to these actions. For example, pg_buildext -m V=1 build build-%v enables the make variable requested by the extension's own makefile. Do not treat -m as a compiler flag; it is appended to the make invocation.
5. Install into versioned package staging directories
Install each VPATH build into the package named by the third argument:
override_dh_auto_install:
+pg_buildext install build-%v postgresql-%v-foobar
For each supported version, pg_buildext runs make install with a DESTDIR under debian/. The %v in the package pattern becomes the actual major version. It also writes the required server dependency to debian/<package>.substvars, using postgresql:Depends when the control file declares it, and retaining the older misc:Depends compatibility path when needed.
This is the point at which package contents change. Review the staged files and package names before running a full package build. Do not replace DESTDIR with a system path or run the makefile as root to install directly into /usr.
6. Clean and test in the right environment
Add a clean action matching the build directory:
override_dh_auto_clean:
+pg_buildext clean build-%v
The installcheck action is different from ordinary build tests. It uses pg_virtualenv and is intended for autopkgtest, after the extension package is installed into the test environment:
Depends: @, postgresql-server-dev-all
Tests: installcheck
Restrictions: allow-stderr
#!/bin/sh
pg_buildext installcheck
If tests need an explicit build directory, use pg_buildext installcheck build-%v. A package pattern can also make the temporary PostgreSQL instance find files below debian/<package>/. Do not put a service-disrupting test against a production cluster in this action: pg_virtualenv is for a temporary test instance.
For interactive SQL or a shell inside that temporary environment, the related actions are psql and virtualenv. They read their input from standard input. Use them only with commands whose state changes are acceptable inside the temporary cluster.
7. Handle non-standard source layouts
If the extension source is below the package root, pass its absolute path before the build directory:
override_dh_auto_build:
+pg_buildext build $(CURDIR)/postgresql-module build-%v
The source directory argument must be absolute. The build directory can contain %v; the source tree itself is shared through VPATH, so version-specific generated files remain separated.
8. Verify the package workflow
Run these checks from the package root:
$ pg_buildext supported-versions
16
$ test -f debian/control
$ grep -E '^Package: postgresql-[0-9]+-foobar$' debian/control
Package: postgresql-16-foobar
$ find debian -maxdepth 2 -type d -name 'postgresql-*-foobar' -print
The final command should show a staging directory after installation. Exact paths and output depend on the extension. If installed-versions reports that debian/control.in is missing, that action cannot infer installed package versions; it is for test environments whose control template contains PGVERSION. Treat a configure, make or test failure as a real failure, not as evidence that another PostgreSQL version should be invented.
If you need to undo a generated build, use pg_buildext clean build-%v and remove only the generated control files after preserving any deliberate packaging edits. Do not use a broad recursive deletion in the package root. Keep the original extension source and the reviewed templates until the package has been rebuilt successfully.
Done means
debian/pgversionsdeclares the intended support range andsupported-versionsconfirms the effective list.debian/controland any test control file were generated from reviewed templates.- Each build uses a versioned
build-%vdirectory, with a leading+indebian/rules. - Installation populates only the matching
debian/package staging directory and records PostgreSQL dependencies. - Regression tests run through
autopkgtestandpg_virtualenv, not against a production cluster. - The staged package names and files have been checked before any package publication or installation.