bug-ncurses
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Building ncurses 6.5 on MS-Windows with MinGW


From: Thomas Dickey
Subject: Re: Building ncurses 6.5 on MS-Windows with MinGW
Date: Sun, 14 Jul 2024 13:09:40 -0400

On Sun, Jul 14, 2024 at 01:19:27PM +0300, Eli Zaretskii wrote:
> Hi,
> 
> First, thank you very much for developing ncurses.
> 
> I've build ncurses 6.5 on MS-Windows using MinGW tools, and needed to

which patch-date?

> solve several problems as I went about it.  I describe these problems
> and their solutions below, in the hope that this will be useful.
> 
> FYI, here's the configure command I used:
> 
>    ./configure --prefix=d:/usr \
>       --without-ada \
>       --with-cxx \
>       --enable-warnings \
>       --enable-assertions\
>       --disable-home-terminfo \
>       --enable-database \
>       --enable-sp-funcs \
>       --enable-term-driver \
>       --enable-interop \
>       --disable-termcap \
>       --without-libtool \
>       --enable-pc-files \
>       --with-shared \
>       --with-normal \
>       --disable-overwrite \
>       --disable-widec

hmm - the README was Juergen's, and I should review that periodically.

I've been building ncurses with more than one toolchain: MinGW32,
MSYS2 with 32-bit and 64-bit environments, and cross-compiling with
Debian or Fedora -- I seem to recall some success with FreeBSD as
while back).

The original MinGW32 is the least capable.  I have "all" of its development
tools installed, iirc.  I tried ada (gnat) a while back, but found a few
problems with that.

I've been building ncurses with widec enabled (last built May 4):
--------------------------------------------------------------------------------
#!/bin/sh
. my-terminfo
cfg-normal \
        --enable-reentrant \
        --without-debug \
        --with-trace \
        --enable-term-driver \
        --enable-sp-funcs \
        --enable-widec \
        --without-ada \
        $MY_TERMINFO "$@"
--------------------------------------------------------------------------------
#!/bin/sh
# source this script when configuring for building terminal database

DATABASE=/tmp/TD
rm -rf $DATABASE
mkdir  $DATABASE

if infocmp ms-terminal >/dev/null 2>/dev/null
then
        FALLBACK="--with-infocmp-path=$(which infocmp)"
elif infocmp6 ms-terminal >/dev/null 2>/dev/null
then
        FALLBACK="--with-infocmp-path=$(which infocmp6)"
fi
test -n "$FALLBACK" && FALLBACK="$FALLBACK 
--with-fallbacks=unknown,xterm-256color,ms-terminal"

MY_TERMINFO="--disable-home-terminfo --with-default-terminfo-dir=$DATABASE 
$FALLBACK"
--------------------------------------------------------------------------------
#!/bin/sh
rm -f config.cache config.status config.log *.out
run-out ./configure \
        --verbose \
        --enable-warnings \
        --with-warnings \
        --disable-echo \
        $*
--------------------------------------------------------------------------------

> The configure options were basically taken from your recommendations
> in README.MinGW.  The only exception is --disable-widec.
> 
> Problem #1: the configure script failed as follows:
> 
>      checking if you want to use pkg-config... yes

I may have changed something in this area since my May 4 build,
but my log says I didn't ask for pkg-config.

>      checking for pkg-config... /d/usr/bin/pkg-config
>      checking for /d/usr/bin/pkg-config library directory... auto
>      checking for search-list... d \usr\lib\pkgconfig;d \usr\share\pkgconfig
>      checking for first directory... none
>      checking for workaround... d
>      checking if we should install .pc files for /d/usr/bin/pkg-config... yes
>      configure: error: expected a pathname, not "d"
> 
> This happens because my pkg-config is a native MinGW port, so the
> command to find search path, viz.:

I see...

Is that somewhere that I could get a copy (to better match the environment)?

>    $ pkg-config pkg-config --variable=pc_path
> 
> produces a Windows-style directory list:
> 
>    D:\usr\lib\pkgconfig;D:\usr\share\pkgconfig
> 
> and then the 'tr' command incorrectly thinks that the first directory
> is 'd'.  My solution was to manually hack the configure script to fix
> this like below:

I see...
 
>    cf_search_path=`"$PKG_CONFIG" --variable=pc_path "$cf_pkg_program" 
> 2>/dev/null | tr ';' ' ' | tr '\' '/'`
> 
> which also takes care of converting backslashes to forward slashes.
> This got me past the configure step.
> 
> Problem #2: several source files cause the compiler to emit warnings
> like this one:
> 
>      ./tinfo/make_hash.c: In function 'main':
>      ./tinfo/make_hash.c:439:7: warning: cast discards 'const' qualifier from 
> pointer target type [-Wcast-qual]
>        439 |  free((void *) name_table[n].ute_name);
>          |       ^
> 
> I ignored these warnings.

I do too - there's a half-dozen that I can't fix without really radical change.

Cross-compiling for MinGW there also are a few places such as mkdir where the
prototype differs (signed/unsigned/etc) which are a nuisance.
 
> Problem #3: several places in the code don't support file names with
> backslashes, and also use X_OK, which is not supported on MS-Windows
> (and usually causes invalid parameter errors).  The patches to fix
> these are attached at the end of this message.

thanks
 
> Problem #4: several test programs, including ncurses.exe, hit an
> assertion in win_driver.c:
> 
>      Assertion failed: term != 0, file ../ncurses/./win32con/win_driver.c, 
> line 2067
> 
> In ncurses.exe this happens when I press ESC to return to the main
> menu.  I traced this to _nc_mingw_tcflush, which insists to find the
> input file descriptor in the list of known TERMINAL structures
> recorded in _nc_screen_chain.  But in the cases this assertion
> triggers, the only TERMINAL structure has its Filedes set to 1,
> whereas lib_kernel.c:flushinp first calls _nc_mingw_tcflush with the
> file descriptor of zero, and that triggers the assertion.
> 
> My conclusion, after looking at the code, and also after comparing the
> code with win32_driver does to implement tcflush, was that it is not
> necessary to insist on finding the descriptor in the _nc_screen_chain
> terminals.  That's because the code anyway calls
> FlushConsoleInputBuffer _only_ for STD_INPUT_HANDLE, basically
> disregarding the input descriptor.  So I used this change to fix this
> problem:
> 
> --- ./ncurses/win32con/win_driver.c~0 2023-09-16 19:27:44.000000000 +0300
> +++ ./ncurses/win32con/win_driver.c   2024-07-10 16:02:45.735385000 +0300
> @@ -612,7 +612,7 @@ wcon_doupdate(TERMINAL_CONTROL_BLOCK * T
>      returnCode(result);
>  }
>  
> -#ifdef __MING32__
> +#ifdef __MINGW32__

ouch - that typo was from a year ago.

fwiw, I recall running the program to validate the patch,
but likely didn't visit all menus.

>  #define SysISATTY(fd) _isatty(fd)
>  #else
>  #define SysISATTY(fd) isatty(fd)
> @@ -2064,14 +2064,24 @@ _nc_mingw_tcgetattr(int fd, struct termi
>  int
>  _nc_mingw_tcflush(int fd, int queue)
>  {
> +#if 0
> +    /* This is not needed: we flush stdin anyway, regardless of what
> +       FD is connected to, as long as it is a console device.  Some
> +       programs (e.g., 'ncurses' from the test suite) have only fd = 1
> +       in terminals recorded by _nc_screen_chain, so they abort
> +       unnecessarily here when flushinp calls us with fd = 0.  */
>      TC_PROLOGUE(fd);
>      (void) term;
> +#else
> +    int code = ERR;
> +#endif
>  
>      if (_nc_mingw_isconsole(fd)) {
>       if (queue == TCIFLUSH) {
>           BOOL b = FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
>           if (!b)
>               return (int) GetLastError();
> +         return 0;

or 
        code = 0;

>       }
>      }
>      return code;
> 
> (This also fixes a typo in "__MING32__", and makes the function return
> zero if it succeeds, as mandated by Posix.)

:-)
 
> Problem #5: misc/Makefile.in is not prepared to deal with
> $PKG_CONFIG_LIBDIR that begins with a Windows drive letters, with the
> result that *.pc files are not installed:
> 
>      /bin/install -c ncurses-config 
> /d/usr/test-ncurses-6.5/bin/ncurses6-config
>      ...skip actual install: no destination was given
> 
> I fixed this like below:
> 
> --- ./misc/Makefile~  2024-07-11 08:47:35.466830100 +0300
> +++ ./misc/Makefile   2024-07-11 11:17:31.781491900 +0300
> @@ -148,7 +148,7 @@
>  install \
>  install.libs :: pc-files
>       @$(SHELL) -c 'case "x$(PKG_CONFIG_LIBDIR)" in \
> -             x/*) \
> +             x/* | x[a-zA-Z]:/*) \
>                       mkdir -p $(DESTDIR)$(PKG_CONFIG_LIBDIR:$(prefix)%=%); \
>                       for name in $(PC_FILES); do \
>                               test -f $$name || continue; \
> 
> Problem #6: this caused me the most of headache.  The problem is that
> ncurses cannot be installed in a staging directory because saying
> "make install prefix=FOO" rebuilds the library with FOO hard-coded in
> a few files.  This is explicitly advised against in INSTALL.  Instead,
> INSTALL says to use "make install DESTDIR=FOO".  But this cannot be
> used as-is on Windows, because the Makefile's simply prepend
> $(DESTDIR) to the directories derives from $(prefix), and that creates
> file names which are invalid on Windows, like d:/foo/bard:/usr/share
> (when prefix = d:/usr and DESTDIR = d:/foo/bar).  (To try to avoid
> this, I originally attempted to use prefix = /d/usr, which MSYS
> converts to d:/usr when it invokes MinGW problems, but this caused
> other troubles: the literal "/d/usr" string is hardcoded in the
> programs, and causes failures because native Windows code doesn't
> support such file names.)

yes... for MinGW, I've been using the relative- and forward-slash
pathnames throughout for scripting.  Mapping the result (to find the
terminal database) is a nuisance.

I see what your problem is - needing to access multiple drives.
When I used OS/2 EMX, that was on F: (a nuisance).
 
> (If you want to know why I install in a staging directory, then it's
> because that makes it much easier to produce binary archives with only
> the build artifacts of the package, which I can then both install
> locally under $(prefix) and upload to the ezwinports site where others
> can download the prebuilt binaries and use them.)
> 
> Eventually, I needed to manually hack all the Makefile's to perform
> the replacements such as the one below:
> 
>      $(DESTDIR)$(bindir)/... => $(DESTDIR)$(bindir:$(prefix)%=%)/...

I suppose that I could help this by adding a new configure option
(probably most of the occurrences come from awk scripts).
 
> That is, I told Make to remove $(prefix) from the beginning of each
> directory, like $(bindir), thus effectively using DESTDIR as
> $(prefix), but without touching $(prefix) itself.  This worked, but it
> also required me to edit run_tic.in, because it also concatenated
> DESTDIR with the various installation directories.
> 
> Problem #7: there's no "install-strip" target in the Makefiles.  I
> solved this with manually stripping the programs and the libraries
> after "make install".

stripping is currently done as a configure option

    --disable-stripping
        Do not strip installed executables.

    --with-strip-program=XXX
        When stripping executables during install, use the specified program
        rather than "strip".
 
> This ends my "building ncurses 6.5 with MinGW" saga.  Once again,
> thanks for developing and maintaining ncurses.
> 
> Here are the diffs for the minor issues I mentioned in Problem #3
> above:
> 
> --- ./include/nc_mingw.h~0    2023-02-25 21:59:24.000000000 +0200
> +++ ./include/nc_mingw.h      2024-07-09 15:37:36.866527000 +0300
> @@ -79,6 +79,12 @@ NCURSES_EXPORT(int) _nc_gettimeofday(str
>  #define wcwidth(ucs) _nc_wcwidth((wchar_t)(ucs))
>  NCURSES_EXPORT(int) _nc_wcwidth(wchar_t);
>  
> +/* Newer versions of MSVCRT barf with invalid parameter error when

huh - that's nice of them, I suppose :-)

> +   passed X_OK of 1, the value defined on MinGW headers.  So we
> +   disable it here.  */
> +#undef X_OK
> +#define X_OK 0
> +
>  #ifdef __cplusplus
>  }
>  #endif
> --- ./ncurses/tinfo/access.c~0        2023-06-25 00:55:09.000000000 +0300
> +++ ./ncurses/tinfo/access.c  2024-07-09 15:34:02.017708600 +0300
> @@ -93,7 +93,7 @@ _nc_rootname(char *path)
>  NCURSES_EXPORT(bool)
>  _nc_is_abs_path(const char *path)
>  {
> -#if defined(__EMX__) || defined(__DJGPP__)
> +#if defined(__EMX__) || defined(__DJGPP__) || defined(__MINGW32__)
>  #define is_pathname(s) ((((s) != 0) && ((s)[0] == '/')) \
>                 || (((s)[0] != 0) && ((s)[1] == ':')))
>  #else
> @@ -109,7 +109,7 @@ NCURSES_EXPORT(unsigned)
>  _nc_pathlast(const char *path)
>  {
>      const char *test = strrchr(path, '/');
> -#ifdef __EMX__
> +#if defined __EMX__ || defined __MINGW32__
>      if (test == 0)
>       test = strrchr(path, '\\');
>  #endif
> 

-- 
Thomas E. Dickey <dickey@invisible-island.net>
https://invisible-island.net

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]