Hello,

I have recently tried to build ncurses with MSVC-like tools (cl.exe and 
clang-cl.exe) and would like to share what I have encountered.

Configuration
-------------

I was using the following options with configure:

```
--without-debug
--without-profile
--without-progs
--without-tests
--without-ada
--with-cxx
--with-cxx-binding
--enable-exp-win32
--enable-term-driver
--enable-ext-funcs
--disable-ext-colors
--enable-sp-funcs
--enable-interop
--enable-opaque-curses
--enable-opaque-form
--enable-opaque-menu
--enable-opaque-panel
--enable-overwrite
--enable-widec
--disable-lib-suffixes
--disable-termcap
--enable-mixed-case
--disable-symlinks
--enable-pc-files
```

You may see me passing --without-progs and --without-tests. Windows' CRT does 
not have getopt.h and does not provide getopt functions. mingw-w64 provides 
them.

You also may see me passing --disable-ext-colors. The source file 
`ncurses/base/new_pair.c` unconditionally uses `tsearch`, `tfind` and `tdelete` 
functions. UCRT's `search.h` does not declare those functions and eventually 
link fails. This is not an issue with mingw-w64 since it provides its own 
versions of those functions.

Build system
------------

ncurses' build system is just autoconf without automake and libtool, but allows 
to use installed libtool script.

The are two ways to build ncurses.

First. Simply use Automake's `compile` and `ar-lib` wrappers for cl.exe and 
lib.exe. This way only static libraries can be built, but it may be just fine 
in some cases.

Automake-1.17's and earlier `compile` wrapper had a bug which causes ncurses++ 
build to fail[1]. It was fixed in automake-1.18.

Second. Configure and use libtool script for MSVC-like tools. This allows to 
build both shared and static libraries. It works, mostly.

There are a few configuration bugs in libtool which make it produce unusable 
.la files[2][3]. A workaround is to set FC=no and F77=no when configuring 
libtool.

Issues
------

I had to explicitly pass user32.lib to the linker. Otherwise, link will fail 
with undefined reference to MessageBeep function. This is not an issue with 
mingw-w64 since compiler passes -luser32 and some others to the linker by 
default.

When I tried to build using clang-cl.exe (a clang frontend which understands 
cl.exe's command line options) I got many

```
error: call to undeclared function 'FUNCNAME'
```

diagnostics. I summaries all of them in attached ncurses.txt.

All of them can be fixed by including <io.h> or <wchar.h> where appropriate. I 
think the reason why this issue was not yet discovered is that mingw-w64's 
header files could indirectly include those header files.

cl.exe does not report undeclared functions by default, `-W4` (which can be 
compared to -Wall -Wextra) must be passed in order to issue a diagnostic.

Misc
----

In configure's output I see the following:

```
checking if data-only library module links... mv: cannot stat 'conftest.o': No 
such file or directory
mv: cannot stat 'conftest.o': No such file or directory
no
```

I believe the issue here is hardcoded .o extension. $OBJEXT probably should be 
used instead.

When building and installing from Cygwin, it creates actual symbolic links in 
PREFIX/share/terminfo. Native Windows functions cannot read those symbolic 
links.

I am aware of a few cases when CRT's non-conformant behavior may cause issues 
with ncurses. Let me know if you would like to know about them.

I was using my own script to build ncurses alongside other packages like GNU 
libiconv and GNU libintl with MSVC-like tools. It simply invokes `configure` -> 
`make` -> `make check` -> `make install DESTDIR=...` in order and takes care of 
some important options like -MD. Let me know if you're interested in using this 
script to build ncurses with MSVC tools.

- Kirill Makurin

[1] https://lists.gnu.org/archive/html/bug-automake/2025-01/msg00003.html
[2] https://lists.gnu.org/archive/html/bug-libtool/2025-06/msg00000.html
[3] https://lists.gnu.org/archive/html/bug-libtool/2025-06/msg00015.html
H:\releases\ncurses-6.5\ncurses\base\lib_addch.c(229,22): error: call to 
undeclared function 'mbrtowc'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
  229 |     if ((len = (int) mbrtowc(&result,
      |                      ^
H:\releases\ncurses-6.5\ncurses\base\lib_addch.c(229,22): note: did you mean 
'mbtowc'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdlib.h(893,22): note: 'mbtowc' declared here
  893 | _ACRTIMP int __cdecl mbtowc(
      |                      ^
1 error generated.

H:\releases\ncurses-6.5\ncurses\base\lib_mouse.c(1111,14): error: call to 
undeclared function 'read'; ISO C99 and later do not support implicit function 
declarations [-Wimplicit-function-declaration]
 1111 |         res = (int) read(
      |                     ^
H:\releases\ncurses-6.5\ncurses\base\lib_mouse.c(1111,14): note: did you mean 
'fread'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdio.h(239,29): note: 'fread' declared here
  239 |     _ACRTIMP size_t __cdecl fread(
      |                             ^
H:\releases\ncurses-6.5\ncurses\base\lib_mouse.c(1237,14): error: call to 
undeclared function 'read'; ISO C99 and later do not support implicit function 
declarations [-Wimplicit-function-declaration]
 1237 |         res = (int) read(
      |                     ^
2 errors generated.

H:\releases\ncurses-6.5\ncurses\base\lib_addch.c(229,22): error: call to 
undeclared function 'mbrtowc'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
  229 |     if ((len = (int) mbrtowc(&result,
      |                      ^
H:\releases\ncurses-6.5\ncurses\base\lib_addch.c(229,22): note: did you mean 
'mbtowc'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdlib.h(893,22): note: 'mbtowc' declared here
  893 | _ACRTIMP int __cdecl mbtowc(
      |                      ^
1 error generated.

H:\releases\ncurses-6.5\ncurses\base\lib_newterm.c(205,5): error: call to 
undeclared function '_setmode'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
  205 |     _setmode(fileno(_ifp), _O_BINARY);
      |     ^
H:\releases\ncurses-6.5\ncurses\base\lib_newterm.c(205,5): note: did you mean 
'_set_fmode'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdlib.h(264,26): note: '_set_fmode' declared 
here
  264 | _ACRTIMP errno_t __cdecl _set_fmode  (_In_              int       _Mode 
);
      |                          ^

H:\releases\ncurses-6.5\ncurses\base\lib_set_term.c(433,5): error: call to 
undeclared function '_setmode'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
  433 |     _setmode(fileno(output), _O_BINARY);
      |     ^
H:\releases\ncurses-6.5\ncurses\base\lib_set_term.c(433,5): note: did you mean 
'_set_fmode'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdlib.h(264,26): note: '_set_fmode' declared 
here
  264 | _ACRTIMP errno_t __cdecl _set_fmode  (_In_              int       _Mode 
);
      |                          ^

H:\releases\ncurses-6.5\ncurses\base\lib_slkset.c(87,9): error: call to 
undeclared function 'mbrtowc'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
   87 |         need = mbrtowc(NULL, p, strlen(p), &state);
      |                ^
H:\releases\ncurses-6.5\ncurses\base\lib_slkset.c(87,9): note: did you mean 
'mbtowc'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdlib.h(893,22): note: 'mbtowc' declared here
  893 | _ACRTIMP int __cdecl mbtowc(
      |                      ^

H:\releases\ncurses-6.5\ncurses\widechar\charable.c(42,15): error: call to 
undeclared function 'wctob'; ISO C99 and later do not support implicit function 
declarations [-Wimplicit-function-declaration]
   42 |     result = (wctob((wint_t) ch) == (int) ch);
      |               ^
H:\releases\ncurses-6.5\ncurses\widechar\charable.c(42,15): note: did you mean 
'wctomb'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdlib.h(963,22): note: 'wctomb' declared here
  963 | _ACRTIMP int __cdecl wctomb(
      |                      ^
H:\releases\ncurses-6.5\ncurses\widechar\charable.c(53,14): error: call to 
undeclared function 'wctob'; ISO C99 and later do not support implicit function 
declarations [-Wimplicit-function-declaration]
   53 |     result = wctob(ch);
      |              ^
H:\releases\ncurses-6.5\ncurses\widechar\charable.c(71,14): error: call to 
undeclared function 'btowc'; ISO C99 and later do not support implicit function 
declarations [-Wimplicit-function-declaration]
   71 |     result = btowc(ch);
      |              ^
H:\releases\ncurses-6.5\ncurses\widechar\charable.c(71,14): note: did you mean 
'mbtowc'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdlib.h(893,22): note: 'mbtowc' declared here
  893 | _ACRTIMP int __cdecl mbtowc(
      |                      ^
3 errors generated.

H:\releases\ncurses-6.5\ncurses\tty\tty_update.c(357,5): error: call to 
undeclared function 'wcrtomb'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
  357 |     PUTC(CHDEREF(ch));
      |     ^
H:\releases\ncurses-6.5\ncurses\curses.priv.h(1470,20): note: expanded from 
macro 'PUTC'
 1470 |                                 PUTC_n = (int) wcrtomb(PUTC_buf,        
            \
      |                                                ^
H:\releases\ncurses-6.5\ncurses\tty\tty_update.c(357,5): note: did you mean 
'wctomb'?
H:\releases\ncurses-6.5\ncurses\curses.priv.h(1470,20): note: expanded from 
macro 'PUTC'
 1470 |                                 PUTC_n = (int) wcrtomb(PUTC_buf,        
            \
      |                                                ^
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdlib.h(963,22): note: 'wctomb' declared here
  963 | _ACRTIMP int __cdecl wctomb(
      |                      ^
1 error generated.

H:\releases\ncurses-6.5\ncurses\widechar\lib_slk_wset.c(61,16): error: call to 
undeclared function 'wcsrtombs'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
   61 |         if ((arglen = wcsrtombs(NULL, &str, (size_t) 0, &state)) != 
(size_t) -1) {
      |                       ^
H:\releases\ncurses-6.5\ncurses\widechar\lib_slk_wset.c(61,16): note: did you 
mean 'wcstombs'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdlib.h(1013,15): note: 'wcstombs' declared 
here
 1013 |     _ACRTIMP, wcstombs,
      |               ^
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\corecrt.h(891,65): note: expanded from macro 
'__DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_2_SIZE'
  891 |     __DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_2_SIZE_EX(_DeclSpec, 
_FuncName, _FuncName##_s, _DstType, _SalAttributeDst, _DstType, _Dst, _TType1, 
_TArg1, _TType2, _TArg2)
      |                                                                 ^
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\corecrt.h(1962,83): note: expanded from macro 
'__DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_2_SIZE_EX'
 1962 |                 _CRT_INSECURE_DEPRECATE(_SecureFuncName) _DeclSpec 
size_t __cdecl _FuncName(_SalAttributeDst _DstType *_Dst, _TType1 _TArg1, 
_TType2 _TArg2);
      |                                                                         
          ^
1 error generated.

H:\releases\ncurses-6.5\ncurses\widechar\lib_unget_wch.c(59,17): error: call to 
undeclared function 'wcsrtombs'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
   59 |         result = (int) wcsrtombs(NULL, &tempp, (size_t) 0, state);
      |                        ^
H:\releases\ncurses-6.5\ncurses\widechar\lib_unget_wch.c(59,17): note: did you 
mean 'wcstombs'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdlib.h(1013,15): note: 'wcstombs' declared 
here
 1013 |     _ACRTIMP, wcstombs,
      |               ^
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\corecrt.h(891,65): note: expanded from macro 
'__DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_2_SIZE'
  891 |     __DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_2_SIZE_EX(_DeclSpec, 
_FuncName, _FuncName##_s, _DstType, _SalAttributeDst, _DstType, _Dst, _TType1, 
_TArg1, _TType2, _TArg2)
      |                                                                 ^
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\corecrt.h(1962,83): note: expanded from macro 
'__DEFINE_CPP_OVERLOAD_STANDARD_NFUNC_0_2_SIZE_EX'
 1962 |                 _CRT_INSECURE_DEPRECATE(_SecureFuncName) _DeclSpec 
size_t __cdecl _FuncName(_SalAttributeDst _DstType *_Dst, _TType1 _TArg1, 
_TType2 _TArg2);
      |                                                                         
          ^
H:\releases\ncurses-6.5\ncurses\widechar\lib_unget_wch.c(61,17): error: call to 
undeclared function 'wcrtomb'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
   61 |         result = (int) wcrtomb(target, source, state);
      |                        ^
H:\releases\ncurses-6.5\ncurses\widechar\lib_unget_wch.c(61,17): note: did you 
mean 'wctomb'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdlib.h(963,22): note: 'wctomb' declared here
  963 | _ACRTIMP int __cdecl wctomb(
      |                      ^
H:\releases\ncurses-6.5\ncurses\widechar\lib_unget_wch.c(89,22): error: call to 
undeclared function 'wcrtomb'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
   89 |             IGNORE_RC((int) wcrtomb(string, wch, &state));
      |                             ^
3 errors generated.

H:\releases\ncurses-6.5\ncurses\tinfo\access.c(137,16): error: call to 
undeclared function 'access'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
  137 |     } else if (ACCESS(path, mode) < 0) {
      |                ^
H:\releases\ncurses-6.5\ncurses\tinfo\access.c(60,27): note: expanded from 
macro 'ACCESS'
   60 | # define ACCESS(FN, MODE) access((FN), (MODE)&(R_OK|W_OK))
      |                           ^
H:\releases\ncurses-6.5\ncurses\tinfo\access.c(137,16): note: did you mean 
'accept'?
H:\releases\ncurses-6.5\ncurses\tinfo\access.c(60,27): note: expanded from 
macro 'ACCESS'
   60 | # define ACCESS(FN, MODE) access((FN), (MODE)&(R_OK|W_OK))
      |                           ^
C:\Program Files (x86)\Windows 
Kits\10\\include\10.0.22000.0\\um\winsock2.h(1631,1): note: 'accept' declared 
here
 1631 | accept(
      | ^
1 error generated.

H:\releases\ncurses-6.5\ncurses\tinfo\lib_print.c(94,20): error: call to 
undeclared function 'write'; ISO C99 and later do not support implicit function 
declarations [-Wimplicit-function-declaration]
   94 |     result = (int) write(SP_PARM->_ofd, mybuf, need);
      |                    ^
H:\releases\ncurses-6.5\ncurses\tinfo\lib_print.c(94,20): note: did you mean 
'fwrite'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdio.h(297,29): note: 'fwrite' declared here
  297 |     _ACRTIMP size_t __cdecl fwrite(
      |                             ^
1 error generated.

H:\releases\ncurses-6.5\ncurses\tinfo\lib_setup.c(886,2): error: call to 
undeclared function '_setmode'; ISO C99 and later do not support implicit 
function declarations [-Wimplicit-function-declaration]
  886 |         _setmode(Filedes, _O_BINARY);
      |         ^
H:\releases\ncurses-6.5\ncurses\tinfo\lib_setup.c(886,2): note: did you mean 
'_set_fmode'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdlib.h(264,26): note: '_set_fmode' declared 
here
  264 | _ACRTIMP errno_t __cdecl _set_fmode  (_In_              int       _Mode 
);
      |                          ^

H:\releases\ncurses-6.5\ncurses\tinfo\lib_tputs.c(139,17): error: call to 
undeclared function 'write'; ISO C99 and later do not support implicit function 
declarations [-Wimplicit-function-declaration]
  139 |                 ssize_t res = write(SP_PARM->_ofd, buf, amount);
      |                               ^
H:\releases\ncurses-6.5\ncurses\tinfo\lib_tputs.c(139,17): note: did you mean 
'fwrite'?
C:\Program Files (x86)\Windows 
Kits\10\include\10.0.22000.0\ucrt\stdio.h(297,29): note: 'fwrite' declared here
  297 |     _ACRTIMP size_t __cdecl fwrite(
      |                             ^
H:\releases\ncurses-6.5\ncurses\tinfo\lib_tputs.c(194,10): error: call to 
undeclared function 'write'; ISO C99 and later do not support implicit function 
declarations [-Wimplicit-function-declaration]
  194 |             if (write(fileno(NC_OUTPUT(SP_PARM)), &tmp, (size_t) 1) == 
-1)
      |                 ^
H:\releases\ncurses-6.5\ncurses\tinfo\lib_tputs.c(199,6): error: call to 
undeclared function 'write'; ISO C99 and later do not support implicit function 
declarations [-Wimplicit-function-declaration]
  199 |         if (write(fileno(stdout), &tmp, (size_t) 1) == -1)
      |             ^

Reply via email to