Target a minimal terminfo library rather than necessarily a full curses

library for color support detection. This still will use a curses
library if that is all we have available on the system. This change
tries to use a smaller subset of the curses library, specifically the
subset that is on some systems split off into a separate library. For
example, if you install ncurses configured --with-tinfo, a 'libtinfo' is
install that provides just the terminfo querying functionality. That
library is now used instead of curses when it is available.

This happens to fix a build error on systems with that library because
when we tried to link ncurses into the binary, we didn't pull tinfo in
as well. =]

It should also provide an easy path for supporting the NetBSD
libterminfo library, but as I don't have access to a NetBSD system I'm
leaving adding that support to those folks.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188160 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chandler Carruth 2013-08-12 09:49:17 +00:00
parent 6a4e44f0de
commit 8d8bdff6d7
9 changed files with 100 additions and 80 deletions

View File

@ -123,7 +123,7 @@ set(FFI_INCLUDE_DIR "" CACHE PATH "Additional directory, where CMake should sear
set(LLVM_TARGET_ARCH "host" set(LLVM_TARGET_ARCH "host"
CACHE STRING "Set target to use for LLVM JIT or use \"host\" for automatic detection.") CACHE STRING "Set target to use for LLVM JIT or use \"host\" for automatic detection.")
option(LLVM_ENABLE_CURSES "Use curses to detect terminal info if available." ON) option(LLVM_ENABLE_TERMINFO "Use terminfo database if available." ON)
option(LLVM_ENABLE_THREADS "Use threads if available." ON) option(LLVM_ENABLE_THREADS "Use threads if available." ON)

View File

@ -1072,16 +1072,16 @@ AC_ARG_WITH(bug-report-url,
AC_DEFINE_UNQUOTED(BUG_REPORT_URL,"$withval", AC_DEFINE_UNQUOTED(BUG_REPORT_URL,"$withval",
[Bug report URL.]) [Bug report URL.])
dnl --enable-curses: check whether the user wants to control use of curses: dnl --enable-terminfo: check whether the user wants to control use of terminfo:
AC_ARG_ENABLE(curses,AS_HELP_STRING( AC_ARG_ENABLE(terminfo,AS_HELP_STRING(
[--enable-curses], [--enable-terminfo],
[Use curses for querying terminal infomation if available (default is YES)]), [Query the terminfo database if available (default is YES)]),
[case "$enableval" in [case "$enableval" in
yes) llvm_cv_enable_curses="yes" ;; yes) llvm_cv_enable_terminfo="yes" ;;
no) llvm_cv_enable_curses="no" ;; no) llvm_cv_enable_terminfo="no" ;;
*) AC_MSG_ERROR([Invalid setting for --enable-curses. Use "yes" or "no"]) ;; *) AC_MSG_ERROR([Invalid setting for --enable-terminfo. Use "yes" or "no"]) ;;
esac], esac],
llvm_cv_enable_curses="yes") llvm_cv_enable_terminfo="yes")
dnl --enable-libffi : check whether the user wants to turn off libffi: dnl --enable-libffi : check whether the user wants to turn off libffi:
AC_ARG_ENABLE(libffi,AS_HELP_STRING( AC_ARG_ENABLE(libffi,AS_HELP_STRING(
@ -1390,11 +1390,11 @@ dnl right libraries to link with.
AC_SEARCH_LIBS(clock_gettime,rt) AC_SEARCH_LIBS(clock_gettime,rt)
dnl The curses library is optional; used for querying terminal info dnl The curses library is optional; used for querying terminal info
if test "$llvm_cv_enable_curses" = "yes" ; then if test "$llvm_cv_enable_terminfo" = "yes" ; then
dnl We need the has_color functionality in curses for it to be useful. dnl We need the has_color functionality in curses for it to be useful.
AC_SEARCH_LIBS(has_colors,curses ncurses ncursesw, AC_SEARCH_LIBS(setupterm,tinfo curses ncurses ncursesw,
AC_DEFINE([HAVE_CURSES],[1], AC_DEFINE([HAVE_TERMINFO],[1],
[Define if curses provides the has_color() function on this platform.])) [Define if the setupterm() function is supported this platform.]))
fi fi
dnl libffi is optional; used to call external functions from the interpreter dnl libffi is optional; used to call external functions from the interpreter
@ -1574,8 +1574,8 @@ else
fi fi
dnl Try to find a suitable curses header. dnl Try to find a suitable curses header.
if test "$llvm_cv_enable_curses" = "yes" ; then if test "$llvm_cv_enable_terminfo" = "yes" ; then
AC_CHECK_HEADERS([curses.h ncurses.h ncursesw.h ncurses/curses.h ncursesw/curses.h]) AC_CHECK_HEADERS([term.h curses.h ncurses.h ncursesw.h ncurses/curses.h ncursesw/curses.h])
fi fi
dnl Try to find ffi.h. dnl Try to find ffi.h.

View File

@ -74,6 +74,7 @@ check_symbol_exists(FE_INEXACT "fenv.h" HAVE_DECL_FE_INEXACT)
check_include_file(mach/mach.h HAVE_MACH_MACH_H) check_include_file(mach/mach.h HAVE_MACH_MACH_H)
check_include_file(mach-o/dyld.h HAVE_MACH_O_DYLD_H) check_include_file(mach-o/dyld.h HAVE_MACH_O_DYLD_H)
check_include_file(term.h HAVE_TERM_H)
check_include_file(curses.h HAVE_CURSES_H) check_include_file(curses.h HAVE_CURSES_H)
check_include_file(ncurses.h HAVE_NCURSES_H) check_include_file(ncurses.h HAVE_NCURSES_H)
check_include_file(ncursesw.h HAVE_NCURSESW_H) check_include_file(ncursesw.h HAVE_NCURSESW_H)
@ -103,18 +104,21 @@ if( NOT PURE_WINDOWS )
else() else()
set(HAVE_LIBZ 0) set(HAVE_LIBZ 0)
endif() endif()
if(LLVM_ENABLE_CURSES) if(LLVM_ENABLE_TERMINFO AND
check_library_exists(curses has_colors "" HAVE_CURSES) (HAVE_TERM_H OR HAVE_CURSES_H OR HAVE_NCURSES_H OR HAVE_NCURSESW_H OR
if(NOT HAVE_CURSES) HAVE_NCURSES_CURSES_H OR HAVE_NCURSESW_CURSES_H))
check_library_exists(ncurses has_colors "" HAVE_NCURSES) set(HAVE_TERMINFO 0)
set(HAVE_CURSES ${HAVE_NCURSES}) foreach(library tinfo curses ncurses ncursesw)
if(NOT HAVE_CURSES) string(TOUPPER ${library} library_suffix)
check_library_exists(ncursesw has_colors "" HAVE_NCURSESW) check_library_exists(${library} setupterm "" HAVE_TERMINFO_${library_suffix})
set(HAVE_CURSES ${HAVE_NCURSESW}) if(HAVE_TERMINFO_${library_suffix})
set(HAVE_TERMINFO 1)
set(TERMINFO_LIBS "${library}")
break()
endif() endif()
endif() endforeach()
else() else()
set(HAVE_CURSES 0) set(HAVE_TERMINFO 0)
endif() endif()
endif() endif()

View File

@ -10,13 +10,9 @@ function(get_system_libs return_var)
if( HAVE_LIBDL ) if( HAVE_LIBDL )
set(system_libs ${system_libs} ${CMAKE_DL_LIBS}) set(system_libs ${system_libs} ${CMAKE_DL_LIBS})
endif() endif()
if(LLVM_ENABLE_CURSES) if(LLVM_ENABLE_TERMINFO)
if(HAVE_NCURSESW) if(HAVE_TERMINFO)
set(system_libs ${system_libs} ncursesw) set(system_libs ${system_libs} ${TERMINFO_LIBS})
elseif(HAVE_NCURSES)
set(system_libs ${system_libs} ncurses)
elseif(HAVE_CURSES)
set(system_libs ${system_libs} curses)
endif() endif()
endif() endif()
if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD )

View File

@ -20,7 +20,7 @@ set(TARGET_TRIPLE "@TARGET_TRIPLE@")
set(LLVM_TOOLS_BINARY_DIR @LLVM_TOOLS_BINARY_DIR@) set(LLVM_TOOLS_BINARY_DIR @LLVM_TOOLS_BINARY_DIR@)
set(LLVM_ENABLE_CURSES @LLVM_ENABLE_CURSES@) set(LLVM_ENABLE_TERMINFO @LLVM_ENABLE_TERMINFO@)
set(LLVM_ENABLE_THREADS @LLVM_ENABLE_THREADS@) set(LLVM_ENABLE_THREADS @LLVM_ENABLE_THREADS@)
@ -30,9 +30,8 @@ set(LLVM_NATIVE_ARCH @LLVM_NATIVE_ARCH@)
set(LLVM_ENABLE_PIC @LLVM_ENABLE_PIC@) set(LLVM_ENABLE_PIC @LLVM_ENABLE_PIC@)
set(HAVE_CURSES @HAVE_CURSES@) set(HAVE_TERMINFO @HAVE_TERMINFO@)
set(HAVE_NCURSES @HAVE_NCURSES@) set(TERMINFO_LIBS @TERMINFO_LIBS@)
set(HAVE_NCURSESW @HAVE_NCURSESW@)
set(HAVE_LIBDL @HAVE_LIBDL@) set(HAVE_LIBDL @HAVE_LIBDL@)
set(HAVE_LIBPTHREAD @HAVE_LIBPTHREAD@) set(HAVE_LIBPTHREAD @HAVE_LIBPTHREAD@)
set(HAVE_LIBZ @HAVE_LIBZ@) set(HAVE_LIBZ @HAVE_LIBZ@)

55
configure vendored
View File

@ -1453,8 +1453,8 @@ Optional Features:
target1,target2,... (default=disable) target1,target2,... (default=disable)
--enable-bindings Build specific language bindings: --enable-bindings Build specific language bindings:
all,auto,none,{binding-name} (default=auto) all,auto,none,{binding-name} (default=auto)
--enable-curses Use curses for querying terminal infomation if --enable-terminfo Query the terminfo database if available (default is
available (default is YES) YES)
--enable-libffi Check for the presence of libffi (default is NO) --enable-libffi Check for the presence of libffi (default is NO)
--enable-ltdl-install install libltdl --enable-ltdl-install install libltdl
@ -6006,17 +6006,17 @@ cat >>confdefs.h <<_ACEOF
_ACEOF _ACEOF
# Check whether --enable-curses was given. # Check whether --enable-terminfo was given.
if test "${enable_curses+set}" = set; then if test "${enable_terminfo+set}" = set; then
enableval=$enable_curses; case "$enableval" in enableval=$enable_terminfo; case "$enableval" in
yes) llvm_cv_enable_curses="yes" ;; yes) llvm_cv_enable_terminfo="yes" ;;
no) llvm_cv_enable_curses="no" ;; no) llvm_cv_enable_terminfo="no" ;;
*) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-curses. Use \"yes\" or \"no\"" >&5 *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-terminfo. Use \"yes\" or \"no\"" >&5
echo "$as_me: error: Invalid setting for --enable-curses. Use \"yes\" or \"no\"" >&2;} echo "$as_me: error: Invalid setting for --enable-terminfo. Use \"yes\" or \"no\"" >&2;}
{ (exit 1); exit 1; }; } ;; { (exit 1); exit 1; }; } ;;
esac esac
else else
llvm_cv_enable_curses="yes" llvm_cv_enable_terminfo="yes"
fi fi
@ -12268,10 +12268,10 @@ if test "$ac_res" != no; then
fi fi
if test "$llvm_cv_enable_curses" = "yes" ; then if test "$llvm_cv_enable_terminfo" = "yes" ; then
{ echo "$as_me:$LINENO: checking for library containing has_colors" >&5 { echo "$as_me:$LINENO: checking for library containing setupterm" >&5
echo $ECHO_N "checking for library containing has_colors... $ECHO_C" >&6; } echo $ECHO_N "checking for library containing setupterm... $ECHO_C" >&6; }
if test "${ac_cv_search_has_colors+set}" = set; then if test "${ac_cv_search_setupterm+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6 echo $ECHO_N "(cached) $ECHO_C" >&6
else else
ac_func_search_save_LIBS=$LIBS ac_func_search_save_LIBS=$LIBS
@ -12288,16 +12288,16 @@ cat >>conftest.$ac_ext <<_ACEOF
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
#endif #endif
char has_colors (); char setupterm ();
int int
main () main ()
{ {
return has_colors (); return setupterm ();
; ;
return 0; return 0;
} }
_ACEOF _ACEOF
for ac_lib in '' curses ncurses ncursesw; do for ac_lib in '' tinfo curses ncurses ncursesw; do
if test -z "$ac_lib"; then if test -z "$ac_lib"; then
ac_res="none required" ac_res="none required"
else else
@ -12338,7 +12338,7 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
ac_status=$? ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then (exit $ac_status); }; }; then
ac_cv_search_has_colors=$ac_res ac_cv_search_setupterm=$ac_res
else else
echo "$as_me: failed program was:" >&5 echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5 sed 's/^/| /' conftest.$ac_ext >&5
@ -12348,26 +12348,26 @@ fi
rm -f core conftest.err conftest.$ac_objext \ rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest$ac_exeext
if test "${ac_cv_search_has_colors+set}" = set; then if test "${ac_cv_search_setupterm+set}" = set; then
break break
fi fi
done done
if test "${ac_cv_search_has_colors+set}" = set; then if test "${ac_cv_search_setupterm+set}" = set; then
: :
else else
ac_cv_search_has_colors=no ac_cv_search_setupterm=no
fi fi
rm conftest.$ac_ext rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS LIBS=$ac_func_search_save_LIBS
fi fi
{ echo "$as_me:$LINENO: result: $ac_cv_search_has_colors" >&5 { echo "$as_me:$LINENO: result: $ac_cv_search_setupterm" >&5
echo "${ECHO_T}$ac_cv_search_has_colors" >&6; } echo "${ECHO_T}$ac_cv_search_setupterm" >&6; }
ac_res=$ac_cv_search_has_colors ac_res=$ac_cv_search_setupterm
if test "$ac_res" != no; then if test "$ac_res" != no; then
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
cat >>confdefs.h <<\_ACEOF cat >>confdefs.h <<\_ACEOF
#define HAVE_CURSES 1 #define HAVE_TERMINFO 1
_ACEOF _ACEOF
fi fi
@ -16543,13 +16543,14 @@ else
fi fi
if test "$llvm_cv_enable_curses" = "yes" ; then if test "$llvm_cv_enable_terminfo" = "yes" ; then
for ac_header in curses.h ncurses.h ncursesw.h ncurses/curses.h ncursesw/curses.h
for ac_header in term.h curses.h ncurses.h ncursesw.h ncurses/curses.h ncursesw/curses.h
do do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then

View File

@ -48,9 +48,6 @@
/* Define to 1 if you have the `closedir' function. */ /* Define to 1 if you have the `closedir' function. */
#cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR} #cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR}
/* Define if curses provides the has_color() function on this platform. */
#cmakedefine HAVE_CURSES
/* Define to 1 if you have the <curses.h> header file. */ /* Define to 1 if you have the <curses.h> header file. */
#cmakedefine HAVE_CURSES_H #cmakedefine HAVE_CURSES_H
@ -420,9 +417,15 @@
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ /* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
#cmakedefine HAVE_SYS_WAIT_H ${HAVE_SYS_WAIT_H} #cmakedefine HAVE_SYS_WAIT_H ${HAVE_SYS_WAIT_H}
/* Define if the setupterm() function is supported this platform. */
#cmakedefine HAVE_TERMINFO ${HAVE_TERMINFO}
/* Define to 1 if you have the <termios.h> header file. */ /* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} #cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H}
/* Define to 1 if you have the <term.h> header file. */
#cmakedefine HAVE_TERM_H
/* Define if the neat program is available */ /* Define if the neat program is available */
#cmakedefine HAVE_TWOPI ${HAVE_TWOPI} #cmakedefine HAVE_TWOPI ${HAVE_TWOPI}

View File

@ -69,9 +69,6 @@
/* can use __crashreporter_info__ */ /* can use __crashreporter_info__ */
#undef HAVE_CRASHREPORTER_INFO #undef HAVE_CRASHREPORTER_INFO
/* Define if curses provides the has_color() function on this platform. */
#undef HAVE_CURSES
/* Define to 1 if you have the <curses.h> header file. */ /* Define to 1 if you have the <curses.h> header file. */
#undef HAVE_CURSES_H #undef HAVE_CURSES_H
@ -455,9 +452,15 @@
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ /* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
#undef HAVE_SYS_WAIT_H #undef HAVE_SYS_WAIT_H
/* Define if the setupterm() function is supported this platform. */
#undef HAVE_TERMINFO
/* Define to 1 if you have the <termios.h> header file. */ /* Define to 1 if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H #undef HAVE_TERMIOS_H
/* Define to 1 if you have the <term.h> header file. */
#undef HAVE_TERM_H
/* Define if the neat program is available */ /* Define if the neat program is available */
#undef HAVE_TWOPI #undef HAVE_TWOPI

View File

@ -38,9 +38,12 @@
# include <termios.h> # include <termios.h>
#endif #endif
// See if we can use curses to detect information about a terminal when // Pull in the headers we found to go with the terminfo reading library (tinfo,
// connected to one. // curses, whatever it may be). We have to pull in the 'curses.h' header as the
#ifdef HAVE_CURSES // SysV spec only provides certain values and defines from that header even
// though we work hard to not link against all of the curses implementation
// when avoidable.
#ifdef HAVE_TERMINFO
# if defined(HAVE_CURSES_H) # if defined(HAVE_CURSES_H)
# include <curses.h> # include <curses.h>
# elif defined(HAVE_NCURSES_H) # elif defined(HAVE_NCURSES_H)
@ -51,10 +54,10 @@
# include <ncurses/curses.h> # include <ncurses/curses.h>
# elif defined(HAVE_NCURSESW_CURSES_H) # elif defined(HAVE_NCURSESW_CURSES_H)
# include <ncursesw/curses.h> # include <ncursesw/curses.h>
# else
# error Have a curses library but unable to find a curses header!
# endif # endif
# include <term.h> # if defined(HAVE_TERM_H)
# include <term.h>
# endif
#endif #endif
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -267,9 +270,8 @@ unsigned Process::StandardErrColumns() {
} }
static bool terminalHasColors(int fd) { static bool terminalHasColors(int fd) {
#ifdef HAVE_CURSES #ifdef HAVE_TERMINFO
// First, acquire a global lock because the curses C routines are thread // First, acquire a global lock because these C routines are thread hostile.
// hostile.
static sys::Mutex M; static sys::Mutex M;
MutexGuard G(M); MutexGuard G(M);
@ -279,8 +281,20 @@ static bool terminalHasColors(int fd) {
// colors. // colors.
return false; return false;
// Test whether the terminal as set up supports color output. // Test whether the terminal as set up supports color output. How to do this
if (has_colors() == TRUE) // isn't entirely obvious. We can use the curses routine 'has_colors' but it
// would be nice to avoid a dependency on curses proper when we can make do
// with a minimal terminfo parsing library. Also, we don't really care whether
// the terminal supports the curses-specific color changing routines, merely
// if it will interpret ANSI color escape codes in a reasonable way. Thus, the
// strategy here is just to query the baseline colors capability and if it
// supports colors at all to assume it will translate the escape codes into
// whatever range of colors it does support. We can add more detailed tests
// here if users report them as necessary.
//
// The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
// the terminfo says that no colors are supported.
if (tigetnum("colors") > 0)
return true; return true;
#endif #endif