Build a PCRE2 Program with pcre2-config
pcre2-config tells you exactly which compiler and linker flags a working PCRE2 build actually needs, so you stop guessing include paths. This guide uses it to compile a small C program and confirm the binary links the library correctly. Allow about fifteen minutes.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need a shell, a C compiler, and the PCRE2 development package. Examples use the installed Debian command at PCRE2 10.42 from libpcre2-dev version 10.42-4ubuntu2.1.
1. Check which command you're calling
pcre2-config describes an installed PCRE2 development setup. It doesn't install the library, change compiler settings, or touch a project. Start with read-only checks:
$ command -v pcre2-config
/usr/bin/pcre2-config
$ /usr/bin/pcre2-config --version
10.42
$ dpkg-query -W -f='${Package} ${Version}\n' libpcre2-dev:amd64
libpcre2-dev 10.42-4ubuntu2.1
The path matters more than it looks. More than one PCRE2 installation can exist on a machine, say a system package alongside a Homebrew or locally compiled copy, and the first executable in PATH is the one that answers every question below. If command -v points somewhere unexpected, inspect it before you compile anything:
$ PATH=/usr/bin:/bin type -a pcre2-config
pcre2-config is /usr/bin/pcre2-config
Checkpoint
Use the same path for every command in this guide. Examples here stick to /usr/bin/pcre2-config so the output stays tied to the Debian package rather than an accidental alternative.
2. Inspect the installation prefixes and flags
Ask for the values one at a time. Prefix options report where PCRE2 was installed; library options report link arguments; cflags options report include-directory or other compile arguments:
$ /usr/bin/pcre2-config --prefix
/usr
$ /usr/bin/pcre2-config --exec-prefix
/usr
$ /usr/bin/pcre2-config --cflags
$ /usr/bin/pcre2-config --libs8
-lpcre2-8
$ /usr/bin/pcre2-config --libs16
-lpcre2-16
$ /usr/bin/pcre2-config --libs32
-lpcre2-32
$ /usr/bin/pcre2-config --libs-posix
-lpcre2-posix -lpcre2-8
A blank --cflags line is entirely valid. It means this installation needs no extra compiler option for the header search path, because the header already sits somewhere standard. Don't turn a blank line into a literal argument, and don't bolt on an arbitrary include directory to compensate.
The suffix on a library flag actually matters: PCRE2 ships separate 8-bit, 16-bit and 32-bit library interfaces, and you link whichever width your source code uses. The POSIX wrapper is different again; this installation reports both -lpcre2-posix and -lpcre2-8 for it.
3. Create a small native API test
Make a temporary source file somewhere outside your project. The program asks PCRE2 for its version through the native API and prints it. The PCRE2_CODE_UNIT_WIDTH definition selects the 8-bit API, matching -lpcre2-8:
$ tmp_c=$(mktemp /tmp/pcre2-config-test.XXXXXX.c)
$ tmp_bin=${tmp_c%.c}
$ trap 'rm -f "$tmp_c" "$tmp_bin"' EXIT
$ cat > "$tmp_c" <<'EOF'
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
#include <stdio.h>
int main(void)
{
PCRE2_UCHAR version[64];
int length = pcre2_config(PCRE2_CONFIG_VERSION, version);
if (length < 0) {
return 1;
}
puts((char *)version);
return 0;
}
EOF
This only creates a temporary source file and arranges to remove it when the shell exits; it needs no elevated privileges. If your shell doesn't support trap, just delete the two temporary files by hand once you're done testing.
4. Compile and link with the reported values
Use command substitution so the installed helper supplies the flags for you. Put the library flags after the source file, which also plays nicely with linkers that resolve libraries strictly left to right:
$ cc -std=c11 -Wall -Wextra -o "$tmp_bin" "$tmp_c" \
$(/usr/bin/pcre2-config --cflags) \
$(/usr/bin/pcre2-config --libs8)
$ "$tmp_bin"
10.42 2022-12-11
The output opens with the PCRE2 library version the program loaded at runtime. This build also appends the library's release date, so don't expect it to match pcre2-config --version byte for byte. If the result surprises you, confirm the executable and its shared-library dependency directly:
$ file "$tmp_bin"
/tmp/pcre2-config-test.XXXXXX: ELF 64-bit LSB pie executable, ...
$ ldd "$tmp_bin" | grep pcre2
libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (...)
The exact temporary name, architecture wording and library path will vary machine to machine. What actually matters: a successful compiler exit status, a version line printed by the program, and a dependency on libpcre2-8.
5. Select a different library width deliberately
Never mix a source definition and a library flag from different widths. A program built with PCRE2_CODE_UNIT_WIDTH 16 needs the 16-bit declarations and --libs16, and the same rule holds for width 32:
$ /usr/bin/pcre2-config --libs16
-lpcre2-16
$ /usr/bin/pcre2-config --libs32
-lpcre2-32
The installed command reports all three libraries, so all three are available here. On another build, an unavailable width makes the command print its usage text instead of a valid linker line: treat that as a build configuration problem, not something to work around. Don't quietly fall back to -lpcre2-8; the declarations and data representation are not interchangeable between widths.
For code using the PCRE2 POSIX wrapper, reach for the wrapper flags instead of the native API ones:
$ cc -o posix-example posix-example.c \
$(/usr/bin/pcre2-config --cflags-posix) \
$(/usr/bin/pcre2-config --libs-posix)
That command assumes a real source file named posix-example.c; it's a pattern to follow, not something this guide creates for you. The POSIX wrapper and the native PCRE2 API are genuinely different interfaces, so pick whichever one matches the source you're actually compiling.
6. Diagnose the common failures
If compilation can't find pcre2.h, compare command -v, --prefix, and the package that owns the header. A mixed toolchain can report flags from one installation while the compiler or runtime loader uses another entirely; pick one consistent prefix rather than copying headers or libraries into system directories to paper over the mismatch.
If the linker reports an undefined PCRE2 symbol, check that the matching --libs8, --libs16, --libs32 or --libs-posix flag is present and comes after the object or source argument. If it says a library can't be found, look at the prefix and library search path rather than reaching for sudo: installation changes belong to your package manager and can affect other programs on the machine.
Shell expansion is another easy trap. A blank cflags result is harmless in the command substitution above. Quote the substitution only when you deliberately need one single argument; compiler flags often contain several, so the plain unquoted form shown here is intentional. Review the expanded command before it ends up in a build script that accepts untrusted environment values.
Done means
- Command confirmed.
pcre2-configresolves to the PCRE2 installation you actually meant to use. - Flags inspected.
--version, prefix, cflags and the library flags you need have all been checked. - Program compiled. A small C program built and linked using command substitution for the flags.
- Output verified. The test binary printed the expected PCRE2 version and links the matching library width.
- Cleanup done. Temporary source and binary files were removed, with no system files or project configuration touched.