Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix "stdscr" configure failure & ncursest support #1558

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

Explorer09
Copy link
Contributor

@Explorer09 Explorer09 commented Oct 19, 2024

This fixes the issue of #1548, while adding minor improvements to the ncurses detecttion code since #1512.

@BenBE BenBE added enhancement Extension or improvement to existing feature build system 🔧 Affects the build system rather then the user experience Linux 🐧 Linux related issues labels Oct 19, 2024
Copy link
Member

@BenBE BenBE left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Document the #if defined(HAVE_CONFIG_H) to be used for reference inside configure.ac.

Also, if not done, have the ncursest specific changes re macros and the ProvideCurses changes live inside separate commits (though that already seems to be the case AFAICS).

@Explorer09 Explorer09 force-pushed the ncursest-support branch 2 times, most recently from 5f0d8f1 to 8eac24b Compare October 25, 2024 10:14
Comment on lines +75 to +83
#ifndef _XOPEN_SOURCE_EXTENDED
#undef _XOPEN_SOURCE_EXTENDED
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you got the check inverted by accident …

Suggested change
#ifndef _XOPEN_SOURCE_EXTENDED
#undef _XOPEN_SOURCE_EXTENDED
#endif
#ifdef _XOPEN_SOURCE_EXTENDED
#undef _XOPEN_SOURCE_EXTENDED
#endif

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. It is not an error. It's the peculiarity of the config.h.in format. The #undef is technically the placeholder that would be replaced by #define during configure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL. Please add a small note about this to document this somewhat. TIA.

configure.ac Outdated Show resolved Hide resolved
@Explorer09 Explorer09 force-pushed the ncursest-support branch 2 times, most recently from 845bc0c to 6a4b665 Compare October 26, 2024 07:57
configure.ac Outdated Show resolved Hide resolved
@Explorer09 Explorer09 force-pushed the ncursest-support branch 2 times, most recently from d5320f9 to e3f2bb2 Compare October 26, 2024 10:04
@Explorer09
Copy link
Contributor Author

@BenBE

I have a idea when trying to improve configure in detecting ncurses header, but am not sure whether such a change is acceptable:

--- a/ProvideCurses.h
+++ b/ProvideCurses.h
@@ -16,16 +16,13 @@ in the source distribution for its full text.
 
 // IWYU pragma: begin_exports
 
-#if defined(HAVE_NCURSESW_CURSES_H)
-#include <ncursesw/curses.h>
-#elif defined(HAVE_NCURSES_NCURSES_H)
-#include <ncurses/ncurses.h>
-#elif defined(HAVE_NCURSES_CURSES_H)
-#include <ncurses/curses.h>
-#elif defined(HAVE_NCURSES_H)
-#include <ncurses.h>
-#elif defined(HAVE_CURSES_H)
-#include <curses.h>
+// The CURSES_HEADER_NAME macro may be defined by configure script to any of these:
+// <ncursesw/curses.h>
+// <ncurses/curses.h>
+// <ncurses.h>
+// <curses.h>
+#if defined(CURSES_HEADER_NAME)
+#include CURSES_HEADER_NAME
 #endif
 
 #ifdef HAVE_LIBNCURSESW

Instead of having a lot of boolean HAVE_*CURSES_H macro tokens, I think it would be better to have one token for curses/ncurses header name. This form of include directive is supposed to work with any C89-compliant compiler, but programmers might be unfamiliar with this form of include.

@BenBE
Copy link
Member

BenBE commented Oct 27, 2024

I considered it briefly when that header was created, but decided against it, as we hate the ProvideCurses.h anyway to deal with all the other aspects of curses that come bundled with terminal control stuff. And since you get those booleans for free™ from autoconf there's no real reason not using them in favour of some little-used feature of the pre-processor. So keep it as-is.

@Explorer09
Copy link
Contributor Author

I considered it briefly when that header was created, but decided against it, as we hate the ProvideCurses.h anyway to deal with all the other aspects of curses that come bundled with terminal control stuff. And since you get those booleans for free™ from autoconf there's no real reason not using them in favour of some little-used feature of the pre-processor. So keep it as-is.

The problem is, the list of possible header names for ncurses is non-exhaustive. We only check header names that are common in distributions (<ncursesw/curses.h>, <ncurses.h>, etc.), but I've experimented with ncurses' configure (upstream), and it technically allows builders to specify any suffix for the library and header directory. So the header could be ncurseswfoo/curses.h (if ncurses is configured with --with-extra-suffix=foo), ncurseswbar/curses.h (if --with-extra-suffix=bar) and so on.

I know these are custom builds and niche use cases, but as I introduced --with-curses=XXX in htop's configure, I think I should allow builders to specify custom header for ncurses (to free them from needing to hack the ProvideCurses.h). It won't be a configure option, but a CPPFLAGS='-DCURSES_HEADER_NAME=<ncurseswfoo/curses.h>' override.

@BenBE
Copy link
Member

BenBE commented Oct 28, 2024

People who mess around with the header names may also just mess around with the code at that point. I doubt most programs using (n)curses at that point would even compile properly with these custom header names. That's some additional complexity added that doesn't provide reasonable benefit for the average case or is common enough to warrant going that extra kilometer.

People messing with their header names can feel lucky, that it's basically just one place they have to mess with in our code …

It makes no sense to error out if the builder runs "./configure
--with-curses" and no option argument. "--with-curses" without an option
argument now keeps using the default name list for detecting ncurses
library.

Signed-off-by: Kang-Che Sung <[email protected]>
When "configure" suggests user to install pkg-config, output the
'*curses*.pc' file detected in the config.log. This aids diagnosing
the configure script.

Signed-off-by: Kang-Che Sung <[email protected]>
@Explorer09 Explorer09 force-pushed the ncursest-support branch 2 times, most recently from 2c4e92e to eb2ee64 Compare October 28, 2024 11:29
It is slightly more robust to grep for the 'pkg_m4_included' token when
running "make dist". Also, shorten the "make dist" warning message, and
tell users if they need to regenerate configure when we recommend them
to install pkg-config.

Signed-off-by: Kang-Che Sung <[email protected]>
When ncurses is compiled with reentrant support, the "stdscr" may be
only available as a macro and not a symbol for direct linking. We can
check for "stdscr" only after the curses headers are included. For now
we can remove the "stdscr" test when checking for keypad() function.

Signed-off-by: Kang-Che Sung <[email protected]>
According to ncurses man page, mvadd_wchnstr() may be implemented as a
macro.

Signed-off-by: Kang-Che Sung <[email protected]>
This allows configure tests to utilize the macro.
Also explain the reasons that we define _XOPEN_SOURCE_EXTENDED and not
_XOPEN_SOURCE.

Signed-off-by: Kang-Che Sung <[email protected]>
The main thing I intended to test is "stdscr", but it is also useful to
test ncurses functions that might be implemented as macros, such as
refresh() and mvadd_wchnstr().

Signed-off-by: Kang-Che Sung <[email protected]>
curses.h may define its own "bool" type, because the X/Open Curses
standard defines "bool" that predates C99 "bool". If curses.h "bool" is
not compatible with ISO C, fail at configure time.

(The C23 standard now makes "bool" a keyword so that a
"typedef /*whatever*/ bool;" is no longer portable. This is a bug that
curses implementations should fix.)

Solaris 11 is known to ship with a broken curses.h header (the default
curses, not ncurses).

Signed-off-by: Kang-Che Sung <[email protected]>
Now it can guess the terminfo library name based on the ncurses
library file name. E.g. "-ltinfow" for the corresponding"-lncursesw".
If the guessed library name doesn't link, try the "-ltinfo" name then.

Signed-off-by: Kang-Che Sung <[email protected]>
"ncursest" and "ncursestw" are multi-threaded variants of the ncurses
library. The "t" library names are only used in operating systems that
do not support weak symbols (so you won't see such names in Linux), but
the names are documented in ncurses anyway. Adding them to the list of
names to check won't hurt.

* See the curs_threads(3X) man page, and the INSTALL file from ncurses
  package. Notably the "--enable-reentrant", "--with-pthread" and
  "--enable-weak-symbols" options in ncurses.

Signed-off-by: Kang-Che Sung <[email protected]>
@Explorer09 Explorer09 marked this pull request as ready for review November 2, 2024 10:00
@Explorer09
Copy link
Contributor Author

I think I would defer the header detection changes to another PR. The rest of the changes are ready.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
build system 🔧 Affects the build system rather then the user experience enhancement Extension or improvement to existing feature Linux 🐧 Linux related issues
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants