mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-22 11:47:04 +08:00
Support linking against reentrant-configured curses
NCurses headers contain this conditional "#define cur_term": print "#elif @cf_cv_enable_reentrant@" print "NCURSES_WRAPPED_VAR(TERMINAL *, cur_term);" print "#define cur_term NCURSES_PUBLIC_VAR(cur_term())" print "#else" OpenSUSE Tumbleweed uses this configuration option; For reentrancy, cur_term is a function. If the NCurses autoconf variable @NCURSES_WRAP_PREFIX@ is not changed from its default, the function is called _nc_cur_term. I'm not sure if we have a need to support non-default @NCURSES_WRAP_PREFIX@ but if we do there are various ways; - search for the symbol with the cur_term suffix - figure out the prefix based on the local curses installation, for example by looking at the header files. Fixes #10243
This commit is contained in:
parent
5dfcfa336b
commit
1234c77b15
27
build.rs
27
build.rs
|
@ -30,29 +30,42 @@ fn main() {
|
|||
|
||||
// Handle case where CMake has found curses for us and where we have to find it ourselves.
|
||||
rsconf::rebuild_if_env_changed("CURSES_LIBRARY_LIST");
|
||||
if let Ok(lib_path_list) = env::var("CURSES_LIBRARY_LIST") {
|
||||
let curses_libraries = if let Ok(lib_path_list) = env::var("CURSES_LIBRARY_LIST") {
|
||||
let lib_paths = lib_path_list.split(',').filter(|s| !s.is_empty());
|
||||
let curses_libnames: Vec<_> = lib_paths
|
||||
.map(|libpath| {
|
||||
let stem = Path::new(libpath).file_stem().unwrap().to_str().unwrap();
|
||||
// Ubuntu-32bit-fetched-pcre2's ncurses doesn't have the "lib" prefix.
|
||||
stem.strip_prefix("lib").unwrap_or(stem)
|
||||
stem.strip_prefix("lib").unwrap_or(stem).to_string()
|
||||
})
|
||||
.collect();
|
||||
// We don't need to test the libs because presumably CMake already did
|
||||
rsconf::link_libraries(&curses_libnames, LinkType::Default);
|
||||
curses_libnames
|
||||
} else {
|
||||
let mut curses_found = false;
|
||||
for lib in ["ncurses", "curses"] {
|
||||
let mut curses_libraries = vec![];
|
||||
let libs = ["ncurses", "curses"];
|
||||
for lib in libs {
|
||||
if target.has_library(lib) && target.has_symbol("setupterm", lib) {
|
||||
rsconf::link_library(lib, LinkType::Default);
|
||||
curses_found = true;
|
||||
curses_libraries.push(lib.to_string());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !curses_found {
|
||||
rsconf::warn!("Could not locate a compatible curses library!");
|
||||
if curses_libraries.is_empty() {
|
||||
panic!("Could not locate a compatible curses library (tried {libs:?})");
|
||||
}
|
||||
curses_libraries
|
||||
};
|
||||
|
||||
for lib in curses_libraries {
|
||||
if target.has_symbol("_nc_cur_term", &lib) {
|
||||
rsconf::enable_cfg("_nc_cur_term");
|
||||
if target.has_symbol("cur_term", &lib) {
|
||||
rsconf::warn!("curses provides both cur_term and _nc_cur_term");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
39
docker/opensuse-tumbleweed.docker
Normal file
39
docker/opensuse-tumbleweed.docker
Normal file
|
@ -0,0 +1,39 @@
|
|||
FROM opensuse/tumbleweed:latest
|
||||
LABEL org.opencontainers.image.source=https://github.com/fish-shell/fish-shell
|
||||
|
||||
ENV LANG C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
|
||||
RUN zypper --non-interactive install \
|
||||
bash \
|
||||
cmake \
|
||||
diffutils \
|
||||
gcc-c++ \
|
||||
git-core \
|
||||
ncurses-devel \
|
||||
ninja \
|
||||
pcre2-devel \
|
||||
python311 \
|
||||
python311-pip \
|
||||
python311-pexpect \
|
||||
openssl \
|
||||
procps \
|
||||
tmux \
|
||||
sudo \
|
||||
rust \
|
||||
cargo
|
||||
|
||||
RUN usermod -p $(openssl passwd -1 fish) root
|
||||
|
||||
RUN groupadd -g 1000 fishuser \
|
||||
&& useradd -p $(openssl passwd -1 fish) -d /home/fishuser -m -u 1000 -g 1000 fishuser \
|
||||
&& mkdir -p /home/fishuser/fish-build \
|
||||
&& mkdir /fish-source \
|
||||
&& chown -R fishuser:fishuser /home/fishuser /fish-source
|
||||
|
||||
USER fishuser
|
||||
WORKDIR /home/fishuser
|
||||
|
||||
COPY fish_run_tests.sh /
|
||||
|
||||
CMD /fish_run_tests.sh
|
|
@ -62,8 +62,10 @@ mod sys {
|
|||
pub type putc_t = extern "C" fn(tputs_arg) -> libc::c_int;
|
||||
|
||||
extern "C" {
|
||||
/// The ncurses `cur_term` TERMINAL pointer.
|
||||
#[cfg(not(have_nc_cur_term))]
|
||||
pub static mut cur_term: *const core::ffi::c_void;
|
||||
#[cfg(have_nc_cur_term)]
|
||||
pub fn have_nc_cur_term() -> *const core::ffi::c_void;
|
||||
|
||||
/// setupterm(3) is a low-level call to begin doing any sort of `term.h`/`curses.h` work.
|
||||
/// It's called internally by ncurses's `initscr()` and `newterm()`, but the C++ code called
|
||||
|
@ -77,6 +79,9 @@ mod sys {
|
|||
/// Frees the `cur_term` TERMINAL pointer.
|
||||
pub fn del_curterm(term: *const core::ffi::c_void) -> libc::c_int;
|
||||
|
||||
/// Sets the `cur_term` TERMINAL pointer.
|
||||
pub fn set_curterm(term: *const core::ffi::c_void) -> *const core::ffi::c_void;
|
||||
|
||||
/// Checks for the presence of a termcap flag identified by the first two characters of
|
||||
/// `id`.
|
||||
pub fn tgetflag(id: *const libc::c_char) -> libc::c_int;
|
||||
|
@ -95,6 +100,19 @@ mod sys {
|
|||
pub fn tputs(str: *const libc::c_char, affcnt: libc::c_int, putc: putc_t) -> libc::c_int;
|
||||
}
|
||||
}
|
||||
|
||||
/// The ncurses `cur_term` TERMINAL pointer.
|
||||
fn get_curterm() -> *const core::ffi::c_void {
|
||||
#[cfg(have_nc_cur_term)]
|
||||
unsafe {
|
||||
sys::have_nc_cur_term()
|
||||
}
|
||||
#[cfg(not(have_nc_cur_term))]
|
||||
unsafe {
|
||||
sys::cur_term
|
||||
}
|
||||
}
|
||||
|
||||
pub use sys::tputs_arg as TputsArg;
|
||||
|
||||
/// The safe wrapper around curses functionality, initialized by a successful call to [`setup()`]
|
||||
|
@ -434,7 +452,7 @@ where
|
|||
let result = unsafe {
|
||||
// If cur_term is already initialized for a different $TERM value, calling setupterm() again
|
||||
// will leak memory. Call del_curterm() first to free previously allocated resources.
|
||||
let _ = sys::del_curterm(cur_term);
|
||||
let _ = sys::del_curterm(get_curterm());
|
||||
|
||||
let mut err = 0;
|
||||
if let Some(term) = term {
|
||||
|
@ -469,8 +487,8 @@ pub fn reset() {
|
|||
unsafe {
|
||||
// Ignore the result of del_curterm() as the only documented error is that
|
||||
// `cur_term` was already null.
|
||||
let _ = sys::del_curterm(cur_term);
|
||||
sys::cur_term = core::ptr::null();
|
||||
let _ = sys::del_curterm(get_curterm());
|
||||
let _ = sys::set_curterm(core::ptr::null());
|
||||
}
|
||||
*term = None;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user