Mix up ncurses and ncursesw and your Unicode box-drawing turns to garbage on a UTF-8 terminal. ncursesw6-config exists to hand you the correct wide-character flags instead, and this covers getting them, using them in a build, and checking which installation actually supplied them. Targets Ubuntu's libncurses-dev version 6.4+20240113-1ubuntu2.2, calling /usr/bin/ncursesw6-config directly throughout.
Allow ten minutes: a shell, the development package, a C compiler. This is read-only inspection plus a local build; nothing installs a package, touches linker configuration, or needs sudo.
Start with the absolute path. A bare ncursesw6-config can resolve to a completely different ncurses install sitting earlier in PATH, which is a common trap on a development workstation:
$ command -v ncursesw6-config
/home/example/.local/bin/ncursesw6-config
$ /usr/bin/ncursesw6-config --version
6.4.20240113
$ dpkg-query -W -f='${Package} ${Version}\n' libncurses-dev
libncurses-dev 6.4+20240113-1ubuntu2.2
That first path is only an example, but if it is anything other than /usr/bin/ncursesw6-config, use the absolute path for the rest of this diagnosis. The helper reports the ncurses release and patch date; the package manager reports the distribution's own version string. Related, but not interchangeable.
Checkpoint: Only continue once the helper version and the development package agree on the installation you actually intend to use.
Ask the helper for the full set of C compiler flags:
$ /usr/bin/ncursesw6-config --cflags
-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600
No -I appears here because the headers already sit in the compiler's standard search path on this installation. Do not add an include directory just because another machine prints one; this output is data for the compiler, not a command to run by itself.
Capture it in a shell variable when building. Leave the variable unquoted in this specific, controlled use, since quoting it as one word would pass both flags as a single argument:
$ CFLAGS=$(/usr/bin/ncursesw6-config --cflags)
$ printf '%s\n' "$CFLAGS"
-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600
Only use command substitution like this with a helper you trust. Never substitute output from an untrusted executable into a privileged build command.
Linking needs a separate library list:
$ /usr/bin/ncursesw6-config --libs
-lncursesw -ltinfo
$ /usr/bin/ncursesw6-config --libs-only-l
-lncursesw -ltinfo
No -L appears either, because this package needs no extra library search directory. The wide-character library is ncursesw, not ncurses; do not quietly swap it in when the source uses the wide-character interface, it will not link.
A practical one-shot build:
$ cc $CFLAGS -o hello-ncurses hello-ncurses.c \
$(/usr/bin/ncursesw6-config --libs)
$ test -x hello-ncurses && echo 'build succeeded'
build succeeded
Object and source files go before the libraries. Many Unix linkers resolve left to right, so putting -lncursesw ahead of the object file can produce unresolved-symbol errors that look like a missing library when the library is actually fine.
A safe smoke test: start ncurses, print one wide-character string, exit on a keypress.
#include <locale.h>
#include <ncursesw/curses.h>
int main(void)
{
setlocale(LC_ALL, "");
initscr();
addwstr(L"ncursesw build succeeded");
refresh();
getch();
endwin();
return 0;
}
Save that as hello-ncurses.c, then build it with the helper's own flags:
$ cc $(/usr/bin/ncursesw6-config --cflags) \
-o hello-ncurses hello-ncurses.c \
$(/usr/bin/ncursesw6-config --libs)
$ file hello-ncurses
hello-ncurses: ELF 64-bit LSB pie executable
Run it from a real terminal, not a non-interactive log stream:
$ ./hello-ncurses
ncursesw build succeeded
Press a key to leave. The executable writes terminal state while running, then endwin() restores it. If a test gets interrupted mid-run, stty sane in that same terminal recovers normal echo and line handling; that fixes the terminal session only, nothing else.
The helper also reports where this ncurses installation expects programs, data and terminal descriptions:
$ /usr/bin/ncursesw6-config --prefix
/usr
$ /usr/bin/ncursesw6-config --bindir
/usr/bin
$ /usr/bin/ncursesw6-config --mandir
/usr/share/man
$ /usr/bin/ncursesw6-config --terminfo
/etc/terminfo
$ /usr/bin/ncursesw6-config --terminfo-dirs
/etc/terminfo:/lib/terminfo:/usr/share/terminfo
Some fields come back blank. Here, --includedir, --libdir and --termpath are all empty because the package has nothing separate to report for them. Treat a blank result as a real answer, not permission to guess a path.
If the command is missing, check the package before reaching for elevated privileges:
$ dpkg-query -W -f='${Status}\n' libncurses-dev
install ok installed
$ test -x /usr/bin/ncursesw6-config && echo executable
executable
If the package is not installed, stop and use your normal package-management process; installing something changes system state and belongs outside this guide, reviewed on its own.
If the output shows a different release or prefix than you expected, compare command -v ncursesw6-config against the absolute path and check PATH. A command running successfully does not prove it matches the compiler, headers and libraries the rest of your build actually uses.
The manpage documents this as the ncurses 6.4 helper's portable option set: prefixes, compile and link flags, ABI and mouse-interface versions, installation directories, terminfo paths, --help and --version. This installed script may support fewer convenience options than another ncurses release, so check /usr/bin/ncursesw6-config --help on the target host rather than copying options from somewhere else.
--cflags for compiling, --libs for linking.PATH entry are not automatically a problem.