Home / Alt manpages / pg_buildext(1)

  • pg_buildext(1)
  • User command
  • linux

Build PostgreSQL Extensions for Every Supported Server Version

pg_buildext builds a PostgreSQL extension against every server version your package supports. Allow 20 to 30 minutes for a small extension if the source and packaging skeleton already exist, then stage each build in its own Debian package directory. The examples describe postgresql-common 257build1.1 installed on this machine.

  • 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.
  • It will not touch: a running PostgreSQL server. These commands build package files under debian/ only.

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 at 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 run once here. The command requires debian/pgversions to exist; 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.
  • NN selects one major version.
  • NN+ selects that version and newer ones.
  • Lines starting 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 choice when the extension has no known incompatibility. It does not override the system list: a version missing from supported-versions is still excluded. For 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, and PGVERSIONS in a dependency field where 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 every package section 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 replacement runs there too.

Add this line to debian/rules so a build can detect that generated control files have gone 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 diff before packaging.

Checkpoint

Inspect the generated package names and dependencies. Do not continue with a stale debian/control: 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: it lets the sub-make talk to the parent make jobserver. Most PGXS extensions do not need a configure action at all, so leave that override out when the source has no configure script.

The optional -m option passes extra make variables to these actions. For example, pg_buildext -m V=1 build build-%v turns on a make variable the extension's own makefile expects. Do not treat -m as a compiler flag: it is appended to the make invocation, nothing more.

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 falling back to the older misc:Depends path when needed.

Warning

This is the point where package contents actually change. Review the staged files and package names before a full package build. Do not replace DESTDIR with a system path, and do not run the makefile as root to install straight 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 not an ordinary build test. It uses pg_virtualenv and is meant for autopkgtest, run 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 point the temporary PostgreSQL instance at files below debian/<package>/.

Warning

Never point a service-disrupting test at a production cluster from this action. pg_virtualenv exists precisely so you don't have to.

For interactive SQL or a shell inside that temporary environment, use the related psql and virtualenv actions. They read their input from standard input, so only feed them commands whose state changes are fine inside a throwaway cluster.

7. Handle non-standard source layouts

If the extension source sits 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 still contain %v; the source tree itself is shared through VPATH, so version-specific generated files stay 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 once installation has run. Exact paths and output depend on the extension. If installed-versions reports that debian/control.in is missing, that just means the action cannot infer installed package versions here; it is meant 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.

Recovery

To undo a generated build, run pg_buildext clean build-%v and remove only the generated control files, preserving any deliberate packaging edits. Do not use a broad recursive delete in the package root. Keep the original extension source and reviewed templates until the package has rebuilt successfully.

Done means

  • Versions declared and confirmed. debian/pgversions states the intended support range and supported-versions confirms the effective list.
  • Control files regenerated. debian/control and any test control file came from reviewed templates.
  • Builds are versioned. Each build uses a build-%v directory, with a leading + in debian/rules.
  • Installs stay scoped. Installation populates only the matching debian/ package staging directory and records PostgreSQL dependencies.
  • Tests run in a throwaway cluster. Regression tests go through autopkgtest and pg_virtualenv, never a production cluster.
  • Staged output reviewed. Package names and files were checked before any publication or install.