Home / Alt manpages / pg_config(1)

  • pg_config(1)
  • User command
  • linux

Find PostgreSQL Headers and Build Flags with pg_config

pg_config tells you exactly which PostgreSQL headers, libraries and compiler flags a build should use, instead of you guessing a distribution path. Reach for it the moment a C extension, native client or build system says it cannot find PostgreSQL, or when you need to check which installation a build is actually using.

Allow about ten minutes. You need a shell and the libpq-dev package, or an equivalent PostgreSQL development package. The commands below only read installation metadata: no service starts, stops, reconfigures or needs elevated privileges.

1. Confirm which pg_config you are running

Start with the executable path, package version and PostgreSQL version. This catches the common mistake of asking one installation for metadata while compiling against another.

$ command -v pg_config
/usr/bin/pg_config
$ dpkg-query -W -f='${Package} ${Version}\n' libpq-dev
libpq-dev 16.15-0ubuntu0.24.04.1
$ pg_config --version
PostgreSQL 16.15 (Ubuntu 16.15-0ubuntu0.24.04.1)

The exact package revision will vary. What matters is that the command is the one you intended, and its reported PostgreSQL major version matches the headers and libraries you plan to use.

Checkpoint

If command -v reports an unexpected path, fix your PATH or use the absolute path to the intended pg_config before continuing. Do not solve an ambiguous path by copying headers between installations.

2. Read one value at a time

Each option prints one path or value. The most useful locations for ordinary client development and extension builds:

$ pg_config --bindir --includedir --includedir-server --libdir --pgxs
/usr/lib/postgresql/16/bin
/usr/include/postgresql
/usr/include/postgresql/16/server
/usr/lib/x86_64-linux-gnu
/usr/lib/postgresql/16/lib/pgxs/src/makefiles/pgxs.mk
  • Multiple options print in the order supplied, one item per line, with no labels. Keep the option list short or assign each result separately in a script.
  • --includedir is for client interface headers.
  • --includedir-server is for server programming, and is not automatically the right include path for a libpq client.
  • --bindir normally holds PostgreSQL user executables such as psql.
  • --libdir identifies object-code libraries.
  • --pgxs identifies the makefile used by the PostgreSQL extension build system.

3. Use the paths in a build without guessing

For a small C client, ask pg_config for the include and library directories instead of hard-coding a distribution-specific path. This compiles client.c into client:

cc \\
  -I"$(pg_config --includedir)" \\
  client.c \\
  -L"$(pg_config --libdir)" -lpq \\
  -o client

This assumes client.c is your source file and that the compiler can find the library's runtime dependencies. It does not create a database connection by itself. If the link step reports that -lpq cannot be found, inspect --libdir, confirm the development package is installed, and check the compiler is targeting the same architecture as the installed libraries.

For an extension built with PGXS, use the makefile path directly:

$ make -f "$(pg_config --pgxs)"

Run that from the extension source directory and follow its own build instructions. A successful build does not mean installation is complete.

Warning

Installing into a system PostgreSQL directory changes state and may need elevated privileges, so review the destination before running any make install target. Back up or record the previous version if you need a rollback.

4. Inspect all labelled values when the installation is unclear

With no option, pg_config prints every known item with a label, which is easier to audit than a long positional command:

$ pg_config
BINDIR = /usr/lib/postgresql/16/bin
DOCDIR = /usr/share/doc/postgresql-doc-16
HTMLDIR = /usr/share/doc/postgresql-doc-16
INCLUDEDIR = /usr/include/postgresql
PKGINCLUDEDIR = /usr/include/postgresql
INCLUDEDIR-SERVER = /usr/include/postgresql/16/server
LIBDIR = /usr/lib/x86_64-linux-gnu
PKGLIBDIR = /usr/lib/postgresql/16/lib
LOCALEDIR = /usr/share/locale
MANDIR = /usr/share/postgresql/16/man
SHAREDIR = /usr/share/postgresql/16
SYSCONFDIR = /etc/postgresql-common
PGXS = /usr/lib/postgresql/16/lib/pgxs/src/makefiles/pgxs.mk

The full output continues with build configuration and compiler variables. Paths are installation facts, not a promise that every file exists or that every binary on your PATH belongs to this installation. Check a specific path with test when a build depends on it:

includedir=$(pg_config --includedir)
libdir=$(pg_config --libdir)
test -d "$includedir" && test -d "$libdir" && printf '%s\n' 'PostgreSQL client paths exist'

5. Capture compiler and linker settings carefully

The build metadata options describe how this PostgreSQL package was built, which helps when comparing installations or diagnosing a native build:

$ pg_config --cc --cppflags --cflags --ldflags --libs
gcc
-Wdate-time -D_FORTIFY_SOURCE=3 -D_GNU_SOURCE -I/usr/include/libxml2
-Wall -Wmissing-prototypes ...
-Wl,-Bsymbolic-functions ...
-lpgcommon -lpgport ... -lpq ...

The long lines are shortened above because flags are host-specific. Do not paste these values blindly into a different compiler command: --cppflags, --cflags, --ldflags and --libs come from the PostgreSQL build, not a universal replacement for the flags your own project documents. The output can contain paths, optimisation choices and libraries appropriate to this package's build but not to your application.

Use --configure to inspect the options passed to PostgreSQL's configure step:

$ pg_config --configure
'--build=x86_64-linux-gnu' '--prefix=/usr' ... '--with-openssl' ...

Package builds can carry distribution patches or packaging choices, so this output is evidence about the build, not a recipe that guarantees an identical rebuild. It can also contain shell quoting: treat it as diagnostic data, not as an unreviewed command to execute.

6. Separate pg_config problems from compiler problems

If the command is missing, install the development package for your distribution. If it exists but a build fails, run the relevant option by itself and inspect the result:

$ pg_config --includedir
/usr/include/postgresql
$ test -f "$(pg_config --includedir)/libpq-fe.h" && printf '%s\n' 'libpq header found'
libpq header found
$ test -f "$(pg_config --pgxs)" && printf '%s\n' 'PGXS makefile found'
PGXS makefile found
  • A missing header usually points to an absent or mismatched development package.
  • A missing library can point to the library directory, architecture or linker configuration.
  • A failed database connection is a separate runtime problem: pg_config does not test server availability, credentials, sockets or network access.

Do not use sudo for these read-only checks. Reserve elevated privileges for a separately reviewed installation step, and know which PostgreSQL version and destination that step will modify.

Done means

  • Installation confirmed. command -v pg_config and pg_config --version identify the intended installation.
  • Paths obtained, not guessed. Client headers via --includedir, libraries via --libdir, PGXS via --pgxs.
  • Build uses discovered paths rather than a guessed distribution layout.
  • Output format understood: no-option output is labelled, multiple options are unlabelled and in order.
  • Compiler flags and --configure treated as diagnostic metadata, not blindly executable instructions.
  • Nothing changed. No service, database, persistent configuration or package state was touched.