Use pg_config to Find PostgreSQL Headers, Libraries and Build Flags
You will use pg_config to discover the PostgreSQL headers, libraries, extension makefiles and compiler settings installed on a Linux machine. That is useful when a C extension, native client or build system cannot find PostgreSQL, or when you need to check which installation a build is using.
The route
Jump straight to the step you need, or tick off Done means at the end.
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. They do not start, stop or reconfigure a database service, and they do not need 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. The useful check is that the command is the one you intended and that 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 are:
$ 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 are printed in the order supplied, one item per line. The output has no labels, so 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 contains 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 example compiles client.c into client:
cc \\
-I"$(pg_config --includedir)" \\
client.c \\
-L"$(pg_config --libdir)" -lpq \\
-o client
The command assumes that 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 that the development package is installed, and check that the compiler command is using 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 the extension's own build instructions. A successful build does not mean installation is complete. Installing into a system PostgreSQL directory changes state and may require 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. This 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 promises 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. They are useful 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 are variables from the PostgreSQL build, not a universal replacement for the flags documented by your project. In particular, the output can contain paths, optimisation choices and libraries that are 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 contain 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 appropriate to 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. Use elevated privileges only for a separately reviewed installation step, and make sure you know which PostgreSQL version and destination that step will modify.
Done means
command -v pg_configandpg_config --versionidentify the intended installation.- You can obtain client headers with
--includedir, libraries with--libdir, and PGXS with--pgxs. - Your build uses discovered paths rather than guessed distribution paths.
- You know that no-option output is labelled, while multiple options produce unlabelled values in order.
- Compiler flags and
--configureoutput are treated as diagnostic metadata, not blindly executable instructions. - No service, database, persistent configuration or package state was changed.