From: Chandler Carruth Date: Mon, 12 Aug 2013 09:49:17 +0000 (+0000) Subject: Target a minimal terminfo library rather than necessarily a full curses X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=8d8bdff6d7eccb05bf16e18141263ee72ea8296b 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 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index a0a6c75fe72..3bd9e112a27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,7 +123,7 @@ set(FFI_INCLUDE_DIR "" CACHE PATH "Additional directory, where CMake should sear set(LLVM_TARGET_ARCH "host" 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) diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 30481ea9176..127eb6fd49f 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -1072,16 +1072,16 @@ AC_ARG_WITH(bug-report-url, AC_DEFINE_UNQUOTED(BUG_REPORT_URL,"$withval", [Bug report URL.]) -dnl --enable-curses: check whether the user wants to control use of curses: -AC_ARG_ENABLE(curses,AS_HELP_STRING( - [--enable-curses], - [Use curses for querying terminal infomation if available (default is YES)]), +dnl --enable-terminfo: check whether the user wants to control use of terminfo: +AC_ARG_ENABLE(terminfo,AS_HELP_STRING( + [--enable-terminfo], + [Query the terminfo database if available (default is YES)]), [case "$enableval" in - yes) llvm_cv_enable_curses="yes" ;; - no) llvm_cv_enable_curses="no" ;; - *) AC_MSG_ERROR([Invalid setting for --enable-curses. Use "yes" or "no"]) ;; + yes) llvm_cv_enable_terminfo="yes" ;; + no) llvm_cv_enable_terminfo="no" ;; + *) AC_MSG_ERROR([Invalid setting for --enable-terminfo. Use "yes" or "no"]) ;; esac], - llvm_cv_enable_curses="yes") + llvm_cv_enable_terminfo="yes") dnl --enable-libffi : check whether the user wants to turn off libffi: AC_ARG_ENABLE(libffi,AS_HELP_STRING( @@ -1390,11 +1390,11 @@ dnl right libraries to link with. AC_SEARCH_LIBS(clock_gettime,rt) 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. - AC_SEARCH_LIBS(has_colors,curses ncurses ncursesw, - AC_DEFINE([HAVE_CURSES],[1], - [Define if curses provides the has_color() function on this platform.])) + AC_SEARCH_LIBS(setupterm,tinfo curses ncurses ncursesw, + AC_DEFINE([HAVE_TERMINFO],[1], + [Define if the setupterm() function is supported this platform.])) fi dnl libffi is optional; used to call external functions from the interpreter @@ -1574,8 +1574,8 @@ else fi dnl Try to find a suitable curses header. -if test "$llvm_cv_enable_curses" = "yes" ; then - AC_CHECK_HEADERS([curses.h ncurses.h ncursesw.h ncurses/curses.h ncursesw/curses.h]) +if test "$llvm_cv_enable_terminfo" = "yes" ; then + AC_CHECK_HEADERS([term.h curses.h ncurses.h ncursesw.h ncurses/curses.h ncursesw/curses.h]) fi dnl Try to find ffi.h. diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake index 0567820b331..13bd40dce17 100755 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -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-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(ncurses.h HAVE_NCURSES_H) check_include_file(ncursesw.h HAVE_NCURSESW_H) @@ -103,18 +104,21 @@ if( NOT PURE_WINDOWS ) else() set(HAVE_LIBZ 0) endif() - if(LLVM_ENABLE_CURSES) - check_library_exists(curses has_colors "" HAVE_CURSES) - if(NOT HAVE_CURSES) - check_library_exists(ncurses has_colors "" HAVE_NCURSES) - set(HAVE_CURSES ${HAVE_NCURSES}) - if(NOT HAVE_CURSES) - check_library_exists(ncursesw has_colors "" HAVE_NCURSESW) - set(HAVE_CURSES ${HAVE_NCURSESW}) + if(LLVM_ENABLE_TERMINFO AND + (HAVE_TERM_H OR HAVE_CURSES_H OR HAVE_NCURSES_H OR HAVE_NCURSESW_H OR + HAVE_NCURSES_CURSES_H OR HAVE_NCURSESW_CURSES_H)) + set(HAVE_TERMINFO 0) + foreach(library tinfo curses ncurses ncursesw) + string(TOUPPER ${library} library_suffix) + check_library_exists(${library} setupterm "" HAVE_TERMINFO_${library_suffix}) + if(HAVE_TERMINFO_${library_suffix}) + set(HAVE_TERMINFO 1) + set(TERMINFO_LIBS "${library}") + break() endif() - endif() + endforeach() else() - set(HAVE_CURSES 0) + set(HAVE_TERMINFO 0) endif() endif() diff --git a/cmake/modules/LLVM-Config.cmake b/cmake/modules/LLVM-Config.cmake index 3e2447a0464..9fa45ce966a 100644 --- a/cmake/modules/LLVM-Config.cmake +++ b/cmake/modules/LLVM-Config.cmake @@ -10,13 +10,9 @@ function(get_system_libs return_var) if( HAVE_LIBDL ) set(system_libs ${system_libs} ${CMAKE_DL_LIBS}) endif() - if(LLVM_ENABLE_CURSES) - if(HAVE_NCURSESW) - set(system_libs ${system_libs} ncursesw) - elseif(HAVE_NCURSES) - set(system_libs ${system_libs} ncurses) - elseif(HAVE_CURSES) - set(system_libs ${system_libs} curses) + if(LLVM_ENABLE_TERMINFO) + if(HAVE_TERMINFO) + set(system_libs ${system_libs} ${TERMINFO_LIBS}) endif() endif() if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) diff --git a/cmake/modules/LLVMConfig.cmake.in b/cmake/modules/LLVMConfig.cmake.in index d87e2421146..68fe296924c 100644 --- a/cmake/modules/LLVMConfig.cmake.in +++ b/cmake/modules/LLVMConfig.cmake.in @@ -20,7 +20,7 @@ set(TARGET_TRIPLE "@TARGET_TRIPLE@") 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@) @@ -30,9 +30,8 @@ set(LLVM_NATIVE_ARCH @LLVM_NATIVE_ARCH@) set(LLVM_ENABLE_PIC @LLVM_ENABLE_PIC@) -set(HAVE_CURSES @HAVE_CURSES@) -set(HAVE_NCURSES @HAVE_NCURSES@) -set(HAVE_NCURSESW @HAVE_NCURSESW@) +set(HAVE_TERMINFO @HAVE_TERMINFO@) +set(TERMINFO_LIBS @TERMINFO_LIBS@) set(HAVE_LIBDL @HAVE_LIBDL@) set(HAVE_LIBPTHREAD @HAVE_LIBPTHREAD@) set(HAVE_LIBZ @HAVE_LIBZ@) diff --git a/configure b/configure index a14871169d1..2bf62483a38 100755 --- a/configure +++ b/configure @@ -1453,8 +1453,8 @@ Optional Features: target1,target2,... (default=disable) --enable-bindings Build specific language bindings: all,auto,none,{binding-name} (default=auto) - --enable-curses Use curses for querying terminal infomation if - available (default is YES) + --enable-terminfo Query the terminfo database if available (default is + YES) --enable-libffi Check for the presence of libffi (default is NO) --enable-ltdl-install install libltdl @@ -6006,17 +6006,17 @@ cat >>confdefs.h <<_ACEOF _ACEOF -# Check whether --enable-curses was given. -if test "${enable_curses+set}" = set; then - enableval=$enable_curses; case "$enableval" in - yes) llvm_cv_enable_curses="yes" ;; - no) llvm_cv_enable_curses="no" ;; - *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-curses. Use \"yes\" or \"no\"" >&5 -echo "$as_me: error: Invalid setting for --enable-curses. Use \"yes\" or \"no\"" >&2;} +# Check whether --enable-terminfo was given. +if test "${enable_terminfo+set}" = set; then + enableval=$enable_terminfo; case "$enableval" in + yes) llvm_cv_enable_terminfo="yes" ;; + no) llvm_cv_enable_terminfo="no" ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-terminfo. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-terminfo. Use \"yes\" or \"no\"" >&2;} { (exit 1); exit 1; }; } ;; esac else - llvm_cv_enable_curses="yes" + llvm_cv_enable_terminfo="yes" fi @@ -12268,10 +12268,10 @@ if test "$ac_res" != no; then fi -if test "$llvm_cv_enable_curses" = "yes" ; then - { echo "$as_me:$LINENO: checking for library containing has_colors" >&5 -echo $ECHO_N "checking for library containing has_colors... $ECHO_C" >&6; } -if test "${ac_cv_search_has_colors+set}" = set; then +if test "$llvm_cv_enable_terminfo" = "yes" ; then + { echo "$as_me:$LINENO: checking for library containing setupterm" >&5 +echo $ECHO_N "checking for library containing setupterm... $ECHO_C" >&6; } +if test "${ac_cv_search_setupterm+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS @@ -12288,16 +12288,16 @@ cat >>conftest.$ac_ext <<_ACEOF #ifdef __cplusplus extern "C" #endif -char has_colors (); +char setupterm (); int main () { -return has_colors (); +return setupterm (); ; return 0; } _ACEOF -for ac_lib in '' curses ncurses ncursesw; do +for ac_lib in '' tinfo curses ncurses ncursesw; do if test -z "$ac_lib"; then ac_res="none required" else @@ -12338,7 +12338,7 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_cv_search_has_colors=$ac_res + ac_cv_search_setupterm=$ac_res else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -12348,26 +12348,26 @@ fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext - if test "${ac_cv_search_has_colors+set}" = set; then + if test "${ac_cv_search_setupterm+set}" = set; then break fi done -if test "${ac_cv_search_has_colors+set}" = set; then +if test "${ac_cv_search_setupterm+set}" = set; then : else - ac_cv_search_has_colors=no + ac_cv_search_setupterm=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -{ echo "$as_me:$LINENO: result: $ac_cv_search_has_colors" >&5 -echo "${ECHO_T}$ac_cv_search_has_colors" >&6; } -ac_res=$ac_cv_search_has_colors +{ echo "$as_me:$LINENO: result: $ac_cv_search_setupterm" >&5 +echo "${ECHO_T}$ac_cv_search_setupterm" >&6; } +ac_res=$ac_cv_search_setupterm if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" cat >>confdefs.h <<\_ACEOF -#define HAVE_CURSES 1 +#define HAVE_TERMINFO 1 _ACEOF fi @@ -16543,13 +16543,14 @@ else 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 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 diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 4b0aa4bc31c..5090a65ff42 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -48,9 +48,6 @@ /* Define to 1 if you have the `closedir' function. */ #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 header file. */ #cmakedefine HAVE_CURSES_H @@ -420,9 +417,15 @@ /* Define to 1 if you have that is POSIX.1 compatible. */ #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 header file. */ #cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_TERM_H + /* Define if the neat program is available */ #cmakedefine HAVE_TWOPI ${HAVE_TWOPI} diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 7bb1caad41d..55c66cc0eb2 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -69,9 +69,6 @@ /* can use __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 header file. */ #undef HAVE_CURSES_H @@ -455,9 +452,15 @@ /* Define to 1 if you have that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H +/* Define if the setupterm() function is supported this platform. */ +#undef HAVE_TERMINFO + /* Define to 1 if you have the header file. */ #undef HAVE_TERMIOS_H +/* Define to 1 if you have the header file. */ +#undef HAVE_TERM_H + /* Define if the neat program is available */ #undef HAVE_TWOPI diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index 0a797f6979e..1bb3e2244c6 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -38,9 +38,12 @@ # include #endif -// See if we can use curses to detect information about a terminal when -// connected to one. -#ifdef HAVE_CURSES +// Pull in the headers we found to go with the terminfo reading library (tinfo, +// curses, whatever it may be). We have to pull in the 'curses.h' header as the +// 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) # include # elif defined(HAVE_NCURSES_H) @@ -51,10 +54,10 @@ # include # elif defined(HAVE_NCURSESW_CURSES_H) # include -# else -# error Have a curses library but unable to find a curses header! # endif -# include +# if defined(HAVE_TERM_H) +# include +# endif #endif //===----------------------------------------------------------------------===// @@ -267,9 +270,8 @@ unsigned Process::StandardErrColumns() { } static bool terminalHasColors(int fd) { -#ifdef HAVE_CURSES - // First, acquire a global lock because the curses C routines are thread - // hostile. +#ifdef HAVE_TERMINFO + // First, acquire a global lock because these C routines are thread hostile. static sys::Mutex M; MutexGuard G(M); @@ -279,8 +281,20 @@ static bool terminalHasColors(int fd) { // colors. return false; - // Test whether the terminal as set up supports color output. - if (has_colors() == TRUE) + // Test whether the terminal as set up supports color output. How to do this + // 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; #endif