Yeah, my point is homebrew has its own separate toolchain that exists on the same filesystem as the OS, while a container created for building binaries could share the same toolchain (e.g. a Fedora 41 distrobox for Bluefin) and have a lot fewer potential incompatibilities, while also being isolated inside a container - basically a dev container with the intention of exporting the apps you build.
HomeBrew can pretty easily “contaminate” any base OS toolchain because it depends on alternatives to build dependencies used by the base OS during the build process. This contamination happens when $PATH hierarchy inadvertently begins pointing to brew’s dependencies rather than the OS-installed dependencies by accident. It’s not hard for that to happen, given that most people don’t examine their $PATH all that frequently (speaking from experience).
It’s a bigger issue when building packages on a non-immutable system - I don’t think the immutable workflow often includes using base OS dependencies to build packages, especially when compared to a distro like Arch Linux (for the AUR), etc. But it also happens a lot to people who use dev toolchain managers like mise, pyenv, pdm, rust, etc. etc.
If you have two copies of the same executable binary, the easiest way to see which one will be called first by default is by using the which command. If it points to the version installed by HomeBrew, congrats - HomeBrew’s instance is earlier in your $PATH environment, and will be executed when attempting to compile or run software, regardless if whether you meant to use the brew toolchain, or not.
It’s even more complicated when you get into issues like which instance of, say, ldd is being called first, where $ENV is specifying you have tools like CC, GCC, CLANG, LD_LIBRARY_PATH, having both pkgconf and pkg-conf on your system, or even potentially multiples of one, the other, or both, or basically inummerable other potential clusterfucks. It can turn into a mess pretty easily, and it’s not particularly easy to unwind if/when it happens.
These are some bash functions I actually started using to keep my $PATH straight after the scenario I’m describing happened to me while using HomeBrew on another distro. But really the $PATH issue dawned on me a long time ago trying to keep versions of node and related packages installed via nvm and npm straight, because, as I mentioned, it’s a real issue using version managers or any other dev toolchain manager. These functions work both in bash and zsh :
# this will list your $PATH environment in a way that's
# a lot easier to read than `echo $PATH`
function path_list () {
COLONS=$(echo "$(echo $PATH | tr -cd ':' | wc -c) + 1" | bc -l)
printf "there are $COLONS paths in \$PATH variable \n"
for (( SECTION = 1; SECTION <= $COLONS; SECTION++ ))
do
PATH_EXISTS=$(echo "$PATH" | cut -d ':' -f"$SECTION")
if [ "$PATH_EXISTS" ]; then
echo "$PATH_EXISTS"; else
echo "number too high: COLON variable -eq $COLONS"
fi
done
}
# same as above using `rainbowpath`, only with pretty colors
# requires installing `rainbowpath`: https://github.com/Soft/rainbowpath
# not in homebrew, unfortunately
function pretty_path () {
for i in $(echo "$PATH" | tr : '\n'); do
rainbowpath "$i"; done
# Three easier/safer functions to add or remove paths from $PATH env
function path_remove () { export PATH=$(echo -n "${PATH}" | awk -v RS=: -v ORS=: '$0 != "'"$1"'"' | sed 's|:$||'); }
function path_append () { path_remove "$1"; export PATH="${PATH}:$1"; }
function path_prepend () { path_remove "$1"; export PATH="$1:${PATH}"; }
# curtail your $PATH env if it gets out of control
# Removes _any_ extraneous paths and puts /bin before $HOME/bin
# you may want to modify this one for your own installation
function conservative_path () {
unset PATH
export PATH="/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$HOME/bin:$HOME/.local/bin:$HOME/.config/zsh/bin"
}