Files
nixpkgs/pkgs/shells/bash/5.nix
2025-10-10 18:22:13 +00:00

291 lines
9.5 KiB
Nix

{
lib,
stdenv,
buildPackages,
fetchurl,
updateAutotoolsGnuConfigScriptsHook,
bison,
util-linux,
coreutils,
libredirect,
glibcLocales,
gnused,
interactive ? true,
readline,
withDocs ? null,
forFHSEnv ? false,
pkgsStatic,
}:
let
upstreamPatches = import ./bash-5.3-patches.nix (
nr: sha256:
fetchurl {
url = "mirror://gnu/bash/bash-5.3-patches/bash53-${nr}";
inherit sha256;
}
);
in
lib.warnIf (withDocs != null)
''
bash: `.override { withDocs = true; }` is deprecated, the docs are always included.
''
stdenv.mkDerivation
(fa: {
pname = "bash${lib.optionalString interactive "-interactive"}";
version = "5.3${fa.patch_suffix}";
patch_suffix = "p${toString (builtins.length upstreamPatches)}";
src = fetchurl {
url = "mirror://gnu/bash/bash-${lib.removeSuffix fa.patch_suffix fa.version}.tar.gz";
hash = "sha256-DVzYaWX4aaJs9k9Lcb57lvkKO6iz104n6OnZ1VUPMbo=";
};
hardeningDisable = [
"format"
]
# bionic libc is super weird and has issues with fortify outside of its own libc, check this comment:
# https://github.com/NixOS/nixpkgs/pull/192630#discussion_r978985593
# or you can check libc/include/sys/cdefs.h in bionic source code
++ lib.optional (stdenv.hostPlatform.libc == "bionic") "fortify";
outputs = [
"out"
"dev"
"man"
"doc"
"info"
];
separateDebugInfo = true;
env.NIX_CFLAGS_COMPILE = ''
-DSYS_BASHRC="/etc/bashrc"
-DSYS_BASH_LOGOUT="/etc/bash_logout"
''
+ lib.optionalString (!forFHSEnv) ''
-DDEFAULT_PATH_VALUE="/no-such-path"
-DSTANDARD_UTILS_PATH="/no-such-path"
-DDEFAULT_LOADABLE_BUILTINS_PATH="${placeholder "out"}/lib/bash:."
''
+ ''
-DNON_INTERACTIVE_LOGIN_SHELLS
-DSSH_SOURCE_BASHRC
'';
patchFlags = [ "-p0" ];
patches = upstreamPatches ++ [
# Enable PGRP_PIPE independently of the kernel of the build machine.
# This doesn't seem to be upstreamed despite such a mention of in https://github.com/NixOS/nixpkgs/pull/77196,
# which originally introduced the patch
# Some related discussion can be found in
# https://lists.gnu.org/archive/html/bug-bash/2015-05/msg00071.html
./pgrp-pipe-5.patch
];
configureFlags = [
# At least on Linux bash memory allocator has pathological performance
# in scenarios involving use of larger memory:
# https://lists.gnu.org/archive/html/bug-bash/2023-08/msg00052.html
# Various distributions default to system allocator. Let's nixpkgs
# do the same.
"--without-bash-malloc"
(if interactive then "--with-installed-readline" else "--disable-readline")
]
++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
"bash_cv_job_control_missing=nomissing"
"bash_cv_sys_named_pipes=nomissing"
"bash_cv_getcwd_malloc=yes"
# This check cannot be performed when cross compiling. The "yes"
# default is fine for static linking on Linux (weak symbols?) but
# not with BSDs, when it does clash with the regular `getenv`.
"bash_cv_getenv_redef=${
if !(with stdenv.hostPlatform; isStatic && (isOpenBSD || isFreeBSD)) then "yes" else "no"
}"
]
++ lib.optionals stdenv.hostPlatform.isCygwin [
"--without-libintl-prefix"
"--without-libiconv-prefix"
"--with-installed-readline"
"bash_cv_dev_stdin=present"
"bash_cv_dev_fd=standard"
"bash_cv_termcap_lib=libncurses"
]
++ lib.optionals (stdenv.hostPlatform.libc == "musl") [
"--disable-nls"
]
++ lib.optionals stdenv.hostPlatform.isFreeBSD [
# /dev/fd is optional on FreeBSD. we need it to work when built on a system
# with it and transferred to a system without it! This includes linux cross.
"bash_cv_dev_fd=absent"
];
strictDeps = true;
# Note: Bison is needed because the patches above modify parse.y.
depsBuildBuild = [ buildPackages.stdenv.cc ];
nativeBuildInputs = [
updateAutotoolsGnuConfigScriptsHook
bison
]
++ lib.optional stdenv.hostPlatform.isDarwin stdenv.cc.bintools;
buildInputs = lib.optional interactive readline;
enableParallelBuilding = true;
makeFlags = lib.optionals stdenv.hostPlatform.isCygwin [
"LOCAL_LDFLAGS=-Wl,--export-all,--out-implib,libbash.dll.a"
"SHOBJ_LIBS=-lbash"
];
doCheck = false; # Can't be enabled by default due to dependency cycle, use passthru.tests.withChecks instead
postInstall = ''
ln -s bash "$out/bin/sh"
rm -f $out/lib/bash/Makefile.inc
'';
postFixup =
if interactive then
''
substituteInPlace "$out/bin/bashbug" \
--replace '#!/bin/sh' "#!$out/bin/bash"
''
# most space is taken by locale data
else
''
rm -rf "$out/share" "$out/bin/bashbug"
'';
passthru = {
shellPath = "/bin/bash";
tests.static = pkgsStatic.bash;
tests.withChecks = fa.finalPackage.overrideAttrs (attrs: {
doCheck = true;
nativeCheckInputs = attrs.nativeCheckInputs or [ ] ++ [
util-linux
libredirect.hook
glibcLocales
gnused
];
meta = attrs.meta // {
# Ignore Darwin for now, because the tests fail in many more ways than on Linux
broken = attrs.meta.broken or false || stdenv.buildPlatform.isDarwin;
};
patches = attrs.patches or [ ] ++ [
# See commit comment, also submitted upstream: https://lists.gnu.org/archive/html/bug-bash/2025-10/msg00054.html
./fail-tests.patch
# See commit comment, also submitted upstream: https://lists.gnu.org/archive/html/bug-bash/2025-10/msg00055.html
./failed-tests-output.patch
# The run-builtins test _almost_ succeeds, only has a bit of PATH trouble
# and some odd terminal column mismatch
./fix-builtins-tests.patch
# The run-invocation test _almost_ succeeds, only has a bit of PATH trouble
./fix-invocation-tests.patch
];
preCheck = attrs.preCheck or "" + ''
# Allows looking at actual outputs for failed tests
export BASH_TSTOUT_KEEPDIR=$(mktemp -d)
export HOME=$(mktemp -d)
export NIX_REDIRECTS=${
lib.concatMapAttrsStringSep ":" (name: value: "${name}=${value}") {
"/bin/echo" = lib.getExe' coreutils "echo";
"/bin/cat" = lib.getExe' coreutils "cat";
"/bin/rm" = lib.getExe' coreutils "rm";
"/usr" = "$(mktemp -d)";
}
}
disabled_checks=(
# Unsets PATH and breaks, not clear
run-execscript
# Fails on ZFS & needs a ja_JP.SJIS locale, which glibcLocales doesn't have
run-intl
# These error with "echo: write error: Broken pipe"
run-histexpand
run-lastpipe
run-comsub
run-comsub2
# For some reason has an extra 'declare -x version="5.2p37"'
run-nameref
# These print some extra 'trap -- ''' SIGPIPE'
run-trap
run-varenv
# These rely on /dev/tty
run-read
run-test
run-vredir
# Might also be related to not having a tty: "Inappropriate ioctl for device"
run-history
# Can be enabled in 5.4
run-printf
# This is probably fixable without too much trouble, but just not having a hardcoded PATH in type5.sub doesn't cut it
# 142,143c142,147
# < type5.sub: line 23: mkdir: command not found
# < type5.sub: line 24: cd: /build/type-23722: No such file or directory
# ---
# > cat is /bin/cat
# > cat is aliased to `echo cat'
# > /bin/cat
# > break is a shell builtin
# > break is a special shell builtin
# > ./e
run-type
)
for check in "''${disabled_checks[@]}"; do
# Exit before running the test script
sed -i "1iecho 'Skipping test $check' >&2 && exit 0" "tests/$check"
done
'';
});
};
meta = with lib; {
homepage = "https://www.gnu.org/software/bash/";
description =
"GNU Bourne-Again Shell, the de facto standard shell on Linux"
+ lib.optionalString interactive " (for interactive use)";
longDescription = ''
Bash is the shell, or command language interpreter, that will
appear in the GNU operating system. Bash is an sh-compatible
shell that incorporates useful features from the Korn shell
(ksh) and C shell (csh). It is intended to conform to the IEEE
POSIX P1003.2/ISO 9945.2 Shell and Tools standard. It offers
functional improvements over sh for both programming and
interactive use. In addition, most sh scripts can be run by
Bash without modification.
'';
license = licenses.gpl3Plus;
platforms = platforms.all;
# https://github.com/NixOS/nixpkgs/issues/333338
badPlatforms = [ lib.systems.inspect.patterns.isMinGW ];
maintainers = with lib.maintainers; [ infinisil ];
mainProgram = "bash";
identifiers.cpeParts =
let
versionSplit = lib.split "p" version;
in
{
vendor = "gnu";
product = "bash";
version = lib.elemAt versionSplit 0;
update = lib.elemAt versionSplit 2;
};
};
})