[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
signature.asc
Description: PGP signature