at master 293 lines 11 kB view raw
1{ 2 lib, 3 stdenv, 4 fetchurl, 5 buildPackages, 6 updateAutotoolsGnuConfigScriptsHook, 7 ncurses, 8 pkg-config, 9 abiVersion ? "6", 10 enableStatic ? stdenv.hostPlatform.isStatic, 11 withCxx ? !stdenv.hostPlatform.useAndroidPrebuilt, 12 mouseSupport ? false, 13 gpm, 14 withTermlib ? false, 15 unicodeSupport ? true, 16 testers, 17 binlore, 18}: 19 20stdenv.mkDerivation (finalAttrs: { 21 version = "6.5"; 22 pname = "ncurses" + lib.optionalString (abiVersion == "5") "-abi5-compat"; 23 24 src = fetchurl { 25 url = "https://invisible-island.net/archives/ncurses/ncurses-${finalAttrs.version}.tar.gz"; 26 hash = "sha256-E22RvCaamleF5fnpgLx2q1dCj2BM4+WlqQzrx2eXHMY="; 27 }; 28 29 outputs = [ 30 "out" 31 "dev" 32 "man" 33 ]; 34 setOutputFlags = false; # some aren't supported 35 36 patches = [ 37 # linux-gnuabielfv{1,2} is not in ncurses' list of GNU-ish targets (or smth like that?). 38 # Causes some defines (_XOPEN_SOURCE=600, _DEFAULT_SOURCE) to not get set, so wcwidth is not exposed by system headers, which causes a FTBFS. 39 # Reported and fix submitted to upstream in https://lists.gnu.org/archive/html/bug-ncurses/2025-07/msg00040.html 40 # Backported to the 6.5 release (dropped some hunks for code that isn't in this release yet) 41 ./1001-ncurses-Support-gnuabielfv1-2.patch 42 ]; 43 44 postPatch = '' 45 sed -i '1i #include <stdbool.h>' include/curses.h.in 46 ''; 47 48 # see other isOpenBSD clause below 49 configurePlatforms = 50 if stdenv.hostPlatform.isOpenBSD then 51 [ "build" ] 52 else 53 [ 54 "build" 55 "host" 56 ]; 57 58 configureFlags = [ 59 (lib.withFeature (!enableStatic) "shared") 60 "--without-debug" 61 "--enable-pc-files" 62 "--enable-symlinks" 63 "--with-manpage-format=normal" 64 "--disable-stripping" 65 "--with-versioned-syms" 66 ] 67 ++ lib.optional unicodeSupport "--enable-widec" 68 ++ lib.optional (!withCxx) "--without-cxx" 69 ++ lib.optional (abiVersion == "5") "--with-abi-version=5" 70 ++ lib.optional stdenv.hostPlatform.isNetBSD "--enable-rpath" 71 ++ lib.optional withTermlib "--with-termlib" 72 ++ lib.optionals stdenv.hostPlatform.isWindows [ 73 "--enable-sp-funcs" 74 "--enable-term-driver" 75 ] 76 ++ lib.optionals (stdenv.hostPlatform.isUnix && enableStatic) [ 77 # For static binaries, the point is to have a standalone binary with 78 # minimum dependencies. So here we make sure that binaries using this 79 # package won't depend on a terminfo database located in the Nix store. 80 "--with-terminfo-dirs=${ 81 lib.concatStringsSep ":" [ 82 "/etc/terminfo" # Debian, Fedora, Gentoo 83 "/lib/terminfo" # Debian 84 "/usr/share/terminfo" # upstream default, probably all FHS-based distros 85 "/run/current-system/sw/share/terminfo" # NixOS 86 ] 87 }" 88 ] 89 ++ lib.optionals (stdenv.buildPlatform != stdenv.hostPlatform) [ 90 "--with-build-cc=${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}cc" 91 ] 92 ++ (lib.optionals (stdenv.cc.bintools.isLLVM && lib.versionAtLeast stdenv.cc.bintools.version "17") 93 [ 94 # lld17+ passes `--no-undefined-version` by default and makes this a hard 95 # error; ncurses' `resulting.map` version script references symbols that 96 # aren't present. 97 # 98 # See: https://lists.gnu.org/archive/html/bug-ncurses/2024-05/msg00086.html 99 # 100 # For now we allow this with `--undefined-version`: 101 "LDFLAGS=-Wl,--undefined-version" 102 ] 103 ) 104 ++ lib.optionals stdenv.hostPlatform.isOpenBSD [ 105 # If you don't specify the version number in the host specification, a branch gets taken in configure 106 # which assumes that your openbsd is from the 90s, leading to a truly awful compiler/linker configuration. 107 # No, autoreconfHook doesn't work. 108 "--host=${stdenv.hostPlatform.config}${stdenv.cc.libc.version}" 109 ] 110 # Without this override, the upstream configure system results in 111 # 112 # typedef unsigned char NCURSES_BOOL; 113 # #define bool NCURSES_BOOL; 114 # 115 # Which breaks C++ bindings: 116 # 117 # > /nix/store/[...]-gcc-15.1.0/include/c++/15.1.0/cstddef:81:21: error: redefinition of 'struct std::__byte_operand<unsigned char>' 118 # > 81 | template<> struct __byte_operand<unsigned char> { using __type = byte; }; 119 # > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 120 # > /nix/store/[...]-gcc-15.1.0/include/c++/15.1.0/cstddef:78:21: note: previous definition of 'struct std::__byte_operand<unsigned char>' 121 # > 78 | template<> struct __byte_operand<bool> { using __type = byte; }; 122 # 123 ++ [ 124 "cf_cv_type_of_bool=bool" 125 ]; 126 127 # Only the C compiler, and explicitly not C++ compiler needs this flag on solaris: 128 CFLAGS = lib.optionalString stdenv.hostPlatform.isSunOS "-D_XOPEN_SOURCE_EXTENDED"; 129 130 strictDeps = true; 131 132 nativeBuildInputs = [ 133 updateAutotoolsGnuConfigScriptsHook 134 pkg-config 135 ] 136 ++ lib.optionals (stdenv.buildPlatform != stdenv.hostPlatform) [ 137 # for `tic`, build already depends on for build `cc` so it's weird the build doesn't just build `tic`. 138 ncurses 139 ]; 140 141 buildInputs = lib.optional (mouseSupport && stdenv.hostPlatform.isLinux) gpm; 142 143 preConfigure = '' 144 export PKG_CONFIG_LIBDIR="$dev/lib/pkgconfig" 145 mkdir -p "$PKG_CONFIG_LIBDIR" 146 configureFlagsArray+=( 147 "--libdir=$out/lib" 148 "--includedir=$dev/include" 149 "--bindir=$dev/bin" 150 "--mandir=$man/share/man" 151 "--with-pkg-config-libdir=$PKG_CONFIG_LIBDIR" 152 ) 153 '' 154 + lib.optionalString stdenv.hostPlatform.isSunOS '' 155 sed -i -e '/-D__EXTENSIONS__/ s/-D_XOPEN_SOURCE=\$cf_XOPEN_SOURCE//' \ 156 -e '/CPPFLAGS="$CPPFLAGS/s/ -D_XOPEN_SOURCE_EXTENDED//' \ 157 configure 158 CFLAGS=-D_XOPEN_SOURCE_EXTENDED 159 ''; 160 161 enableParallelBuilding = true; 162 163 doCheck = false; 164 165 postFixup = 166 let 167 abiVersion-extension = 168 if stdenv.hostPlatform.isDarwin then "${abiVersion}.$dylibtype" else "$dylibtype.${abiVersion}"; 169 in 170 '' 171 # Determine what suffixes our libraries have 172 suffix="$(awk -F': ' 'f{print $3; f=0} /default library suffix/{f=1}' config.log)" 173 '' 174 # When building a wide-character (Unicode) build, create backward 175 # compatibility links from the the "normal" libraries to the 176 # wide-character libraries (e.g. libncurses.so to libncursesw.so). 177 + lib.optionalString unicodeSupport '' 178 libs="$(ls $dev/lib/pkgconfig | tr ' ' '\n' | sed "s,\(.*\)$suffix\.pc,\1,g")" 179 suffixes="$(echo "$suffix" | awk '{for (i=1; i < length($0); i++) {x=substr($0, i+1, length($0)-i); print x}}')" 180 181 # Get the path to the config util 182 cfg=$(basename $dev/bin/ncurses*-config) 183 184 # symlink the full suffixed include directory 185 ln -svf . $dev/include/ncurses$suffix 186 187 for newsuffix in $suffixes ""; do 188 # Create a non-abi versioned config util links 189 ln -svf $cfg $dev/bin/ncurses$newsuffix-config 190 191 # Allow for end users who #include <ncurses?w/*.h> 192 ln -svf . $dev/include/ncurses$newsuffix 193 194 for library in $libs; do 195 for dylibtype in so dll dylib; do 196 if [ -e "$out/lib/lib''${library}$suffix.$dylibtype" ]; then 197 ln -svf lib''${library}$suffix.$dylibtype $out/lib/lib$library$newsuffix.$dylibtype 198 ln -svf lib''${library}$suffix.${abiVersion-extension} $out/lib/lib$library$newsuffix.${abiVersion-extension} 199 if [ "ncurses" = "$library" ] 200 then 201 # make libtinfo symlinks 202 ln -svf lib''${library}$suffix.$dylibtype $out/lib/libtinfo$newsuffix.$dylibtype 203 ln -svf lib''${library}$suffix.${abiVersion-extension} $out/lib/libtinfo$newsuffix.${abiVersion-extension} 204 fi 205 fi 206 done 207 for statictype in a dll.a la; do 208 if [ -e "$out/lib/lib''${library}$suffix.$statictype" ]; then 209 ln -svf lib''${library}$suffix.$statictype $out/lib/lib$library$newsuffix.$statictype 210 if [ "ncurses" = "$library" ] 211 then 212 # make libtinfo symlinks 213 ln -svf lib''${library}$suffix.$statictype $out/lib/libtinfo$newsuffix.$statictype 214 fi 215 fi 216 done 217 ln -svf ''${library}$suffix.pc $dev/lib/pkgconfig/$library$newsuffix.pc 218 done 219 done 220 '' 221 # Unconditional patches. Leading newline is to avoid mass rebuilds. 222 + '' 223 224 # add pkg-config aliases for libraries that are built-in to libncurses(w) 225 for library in tinfo tic; do 226 for suffix in "" ${lib.optionalString unicodeSupport "w"}; do 227 ln -svf ncurses$suffix.pc $dev/lib/pkgconfig/$library$suffix.pc 228 done 229 done 230 231 # move some utilities to $bin 232 # these programs are used at runtime and don't really belong in $dev 233 moveToOutput "bin/clear" "$out" 234 moveToOutput "bin/reset" "$out" 235 moveToOutput "bin/tabs" "$out" 236 moveToOutput "bin/tic" "$out" 237 moveToOutput "bin/tput" "$out" 238 moveToOutput "bin/tset" "$out" 239 moveToOutput "bin/captoinfo" "$out" 240 moveToOutput "bin/infotocap" "$out" 241 moveToOutput "bin/infocmp" "$out" 242 ''; 243 244 preFixup = lib.optionalString (!stdenv.hostPlatform.isCygwin && !enableStatic) '' 245 rm "$out"/lib/*.a 246 ''; 247 248 # I'm not very familiar with ncurses, but it looks like most of the 249 # exec here will run hard-coded executables. There's one that is 250 # dynamic, but it looks like it only comes from executing a terminfo 251 # file, so I think it isn't going to be under user control via CLI? 252 # Happy to have someone help nail this down in either direction! 253 # The "capability" is 'iprog', and I could only find 1 real example: 254 # https://invisible-island.net/ncurses/terminfo.ti.html#tic-linux-s 255 passthru.binlore.out = binlore.synthesize ncurses '' 256 execer cannot bin/{reset,tput,tset} 257 ''; 258 259 meta = with lib; { 260 homepage = "https://www.gnu.org/software/ncurses/"; 261 description = "Free software emulation of curses in SVR4 and more"; 262 longDescription = '' 263 The Ncurses (new curses) library is a free software emulation of curses in 264 System V Release 4.0, and more. It uses Terminfo format, supports pads and 265 color and multiple highlights and forms characters and function-key 266 mapping, and has all the other SYSV-curses enhancements over BSD Curses. 267 268 The ncurses code was developed under GNU/Linux. It has been in use for 269 some time with OpenBSD as the system curses library, and on FreeBSD and 270 NetBSD as an external package. It should port easily to any 271 ANSI/POSIX-conforming UNIX. It has even been ported to OS/2 Warp! 272 ''; 273 license = licenses.mit; 274 pkgConfigModules = 275 let 276 base = [ 277 "form" 278 "menu" 279 "ncurses" 280 "panel" 281 ] 282 ++ lib.optional withCxx "ncurses++"; 283 in 284 base ++ lib.optionals unicodeSupport (map (p: p + "w") base); 285 platforms = platforms.all; 286 }; 287 288 passthru = { 289 ldflags = "-lncurses"; 290 inherit unicodeSupport abiVersion; 291 tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage; 292 }; 293})