brew doctor output
Your system is ready to brew.
Verification
brew config output
HOMEBREW_VERSION: 7.0.6
ORIGIN: https://github.com/Homebrew/brew
HEAD: 570982948a8a194f0f42f43f4a5bce2d1c9f64cb
Last commit: 26 hours ago
Branch: stable
Core tap: N/A
Core cask tap: N/A
HOMEBREW_PREFIX: /home/u/.b
HOMEBREW_REPOSITORY: /home/u/.b/Homebrew
HOMEBREW_CELLAR: /home/u/.b/Cellar
HOMEBREW_NO_ANALYTICS: set
HOMEBREW_NO_AUTO_UPDATE: set
HOMEBREW_NO_ENV_HINTS: set
Homebrew Ruby: 4.0.7 => /home/u/.b/Homebrew/Library/Homebrew/vendor/portable-ruby/4.0.7/bin/ruby
CPU: 16-core 64-bit zen4
Clang: N/A
Git: 2.55.0 => /bin/git
Curl: 8.15.0 => /bin/curl
Kernel: Linux 7.2.5-100.fc43.x86_64 x86_64 GNU/Linux
Landlock ABI: 10
OS: Fedora Linux 43 (Container Image)
Host glibc: 2.42
Host libstdc++: 6.0.34
/usr/bin/gcc: 15.3.1
/usr/bin/ruby: N/A
glibc: N/A
gcc@13: N/A
gcc: N/A
xorg: N/A
What were you trying to do (and why)?
What: Use Homebrew on Linux at a per-user prefix (/home/u/.b) instead of /home/linuxbrew/.linuxbrew.
Why: We are building a Linux-based immutable OS and rely on brew for the users' package management. To better support multi-user situations, we install brew per user in ~/.b.
What happened (include all command output)?
I ran into this issue when installing fonts and fontconfig:
$ ~/.b/bin/fc-match sans-serif
Fontconfig error: Cannot load default config file: File not found
DejaVuSans.ttf: "DejaVu Sans" "Book"
$ strace -e trace=access -P /home/linuxbrew/.linuxbrew/etc/fonts/fonts.conf ~/.b/bin/fc-match sans-serif
access("/home/linuxbrew/.linuxbrew/etc/fonts/fonts.conf", R_OK) = -1 ENOENT (No such file or directory)
When Homebrew is installed at a prefix other than /home/linuxbrew/.linuxbrew, it rewrites the build prefix in
the installed files. The rewrite currently only finds the prefix where it is stored as one string. Compiled code sometimes
holds a path in 8-byte pieces spread over several instructions instead, which the rewrite doesn't touch:
$ ruby split-prefix.rb ~/.b/Cellar
avahi/0.9-rc5/sbin/avahi-daemon: /home/li|nuxbrew/|.linuxbr|ew/var/r|un/avahi|-daemon/|socket
avahi/0.9-rc5/sbin/avahi-dnsconfd: /home/li|nuxbrew/|.linuxbr|ew/var/r|un/avahi|-daemon/|socket
fontconfig/2.18.3/lib/libfontconfig.so.1.17.0: /home/li|nuxbrew/|.linuxbr|ew/etc/f|c/fonts
glib/2.90.0/lib/libgio-2.0.so.0.9000.0: /home/li|nuxbrew/|.linuxbr|ew/lib/g|io/modul
glib/2.90.0/lib/libgirepository-2.0.so.0.9000.0: /home/li|nuxbrew/|.linuxbr|ew/lib/g|ireposit|ory-1.0
glib/2.90.0/lib/libglib-2.0.so.0.9000.0: /home/li|nuxbrew/|.linuxbr|ew/Cella|r/glib/2|.90.0/li|charset.|t.alias
gtk+3/3.24.52/lib/libgtk-3.so.0.2420.32: /home/li|nuxbrew/|.linuxbr|ew/Cella|r/gtk+3/|3.24.52/|2/share
gtk+3/3.24.52/lib/libgtk-3.so.0.2420.32: /home/li|nuxbrew/|.linuxbr|ew/Cella|r/libx11|/1.8.13/|share/X1|1/locale
util-linux/2.42.3/lib/libuuid.so.1.3.0: /home/li|nuxbrew/|.linuxbr|ew/Cella|r/util-l|inux/2.4|2.3/var/|run/uuid|d/reques
Script listing paths stored in 8-byte pieces inside machine code `split-prefix.rb`
#!/usr/bin/env ruby
# List ELF files under a directory in which the Homebrew build prefix is
# written 8 bytes at a time by x86-64 `movabs` instructions instead of being
# stored as one string. Prints the file and the pieces the immediates hold.
require "find"
PREFIX = "/home/linuxbrew/.linuxbrew".b
MOVABS = /\x48[\xb8-\xbf](.{8})/mn
CHAIN_START = /\x48[\xb8-\xbf]#{Regexp.escape(PREFIX[0, 8])}/mn
root = ARGV.fetch(0)
Find.find(root) do |path|
next if File.symlink?(path) || !File.file?(path)
data = File.binread(path)
next unless data.start_with?("\x7fELF".b)
data.to_enum(:scan, CHAIN_START).map { Regexp.last_match.begin(0) }.each do |start|
pieces = []
pos = start
while (m = MOVABS.match(data, pos)) && m.begin(0) < pos + 40
pieces << m[1]
pos = m.end(0)
end
next unless pieces.join.start_with?(PREFIX)
puts "#{path.delete_prefix("#{root}/")}: #{pieces.join("|")}"
end
end
What did you expect to happen?
fc-match reads /home/u/.b/etc/fonts/fonts.conf and prints no error, as it does with FONTCONFIG_PATH=~/.b/etc/fonts set:
$ FONTCONFIG_PATH=~/.b/etc/fonts ~/.b/bin/fc-match sans-serif
DejaVuSans.ttf: "DejaVu Sans" "Book"
Step-by-step reproduction instructions (running brew commands)
NONINTERACTIVE=1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -- --path="$HOME/.b"
export PATH="$HOME/.b/bin:$PATH"
brew install fontconfig
fc-match sans-serif
Full repro in containers:
*Ubuntu 24.04*
podman run --rm ubuntu:24.04 bash -c "$(cat <<'EOF'
set -e
apt-get update -qq >/dev/null
apt-get install -y -qq build-essential procps curl file git strace >/dev/null 2>&1
useradd -m u
su - u -s /bin/bash <<'USER'
export PATH=$HOME/.b/bin:$PATH HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_ANALYTICS=1 HOMEBREW_NO_ENV_HINTS=1
NONINTERACTIVE=1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -- --path="$HOME/.b" >/dev/null 2>&1
set -x
brew update </dev/null
brew update </dev/null
brew install fontconfig </dev/null 2>&1 | grep Pouring.fontconfig
brew doctor
ls -l ~/.b/etc/fonts/fonts.conf
fc-match sans-serif
strace -e trace=access -P /home/linuxbrew/.linuxbrew/etc/fonts/fonts.conf fc-match sans-serif
FONTCONFIG_PATH=~/.b/etc/fonts fc-match sans-serif
USER
EOF
)"
Output:
+ brew update
==> Updating Homebrew...
Already up-to-date.
+ brew update
==> Updating Homebrew...
Already up-to-date.
+ brew install fontconfig
+ grep Pouring.fontconfig
==> Pouring fontconfig--2.18.3.x86_64_linux.bottle.tar.gz
+ brew doctor
Your system is ready to brew.
+ ls -l /home/u/.b/etc/fonts/fonts.conf
-rw-r--r--. 1 u u 2710 Sep 22 18:08 /home/u/.b/etc/fonts/fonts.conf
+ fc-match sans-serif
Fontconfig error: Cannot load default config file: File not found
DejaVuSans.ttf: "DejaVu Sans" "Book"
+ strace -e trace=access -P /home/linuxbrew/.linuxbrew/etc/fonts/fonts.conf fc-match sans-serif
access("/home/linuxbrew/.linuxbrew/etc/fonts/fonts.conf", R_OK) = -1 ENOENT (No such file or directory)
Fontconfig error: Cannot load default config file: File not found
DejaVuSans.ttf: "DejaVu Sans" "Book"
+++ exited with 0 +++
+ FONTCONFIG_PATH=/home/u/.b/etc/fonts
+ fc-match sans-serif
DejaVuSans.ttf: "DejaVu Sans" "Book"
*Fedora 43*
podman run --rm fedora:43 bash -c "$(cat <<'EOF'
set -e
dnf install -y -q gcc gcc-c++ make procps-ng curl file git strace dejavu-sans-fonts >/dev/null 2>&1
useradd -m u
su - u -s /bin/bash <<'USER'
export PATH=$HOME/.b/bin:$PATH HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_ANALYTICS=1 HOMEBREW_NO_ENV_HINTS=1
NONINTERACTIVE=1 bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -- --path="$HOME/.b" >/dev/null 2>&1
set -x
brew update </dev/null
brew update </dev/null
brew install fontconfig </dev/null 2>&1 | grep Pouring.fontconfig
brew doctor
ls -l ~/.b/etc/fonts/fonts.conf
fc-match sans-serif
strace -e trace=access -P /home/linuxbrew/.linuxbrew/etc/fonts/fonts.conf fc-match sans-serif
FONTCONFIG_PATH=~/.b/etc/fonts fc-match sans-serif
USER
EOF
)"
Output:
+ brew update
==> Updating Homebrew...
Already up-to-date.
+ brew update
==> Updating Homebrew...
Already up-to-date.
+ brew install fontconfig
+ grep Pouring.fontconfig
==> Pouring fontconfig--2.18.3.x86_64_linux.bottle.tar.gz
+ brew doctor
Your system is ready to brew.
+ ls -l /home/u/.b/etc/fonts/fonts.conf
-rw-r--r--. 1 u u 2710 Sep 22 18:09 /home/u/.b/etc/fonts/fonts.conf
+ fc-match sans-serif
Fontconfig error: Cannot load default config file: File not found
DejaVuSans.ttf: "DejaVu Sans" "Book"
+ strace -e trace=access -P /home/linuxbrew/.linuxbrew/etc/fonts/fonts.conf fc-match sans-serif
access("/home/linuxbrew/.linuxbrew/etc/fonts/fonts.conf", R_OK) = -1 ENOENT (No such file or directory)
Fontconfig error: Cannot load default config file: File not found
DejaVuSans.ttf: "DejaVu Sans" "Book"
+++ exited with 0 +++
+ FONTCONFIG_PATH=/home/u/.b/etc/fonts
+ fc-match sans-serif
DejaVuSans.ttf: "DejaVu Sans" "Book"
Debugged with the help of Claude Code (Fable 5.1)
brew doctoroutputVerification
brew updatetwice and am still able to reproduce my issue.brew doctoroutput above and it seems unrelated to my issue.brew install wget. If they do, open an issue at https://github.com/Homebrew/homebrew-core/issues/new/choose instead.brew configoutputWhat were you trying to do (and why)?
What: Use Homebrew on Linux at a per-user prefix (
/home/u/.b) instead of/home/linuxbrew/.linuxbrew.Why: We are building a Linux-based immutable OS and rely on brew for the users' package management. To better support multi-user situations, we install brew per user in
~/.b.What happened (include all command output)?
I ran into this issue when installing fonts and fontconfig:
When Homebrew is installed at a prefix other than
/home/linuxbrew/.linuxbrew, it rewrites the build prefix inthe installed files. The rewrite currently only finds the prefix where it is stored as one string. Compiled code sometimes
holds a path in 8-byte pieces spread over several instructions instead, which the rewrite doesn't touch:
Script listing paths stored in 8-byte pieces inside machine code `split-prefix.rb`
What did you expect to happen?
fc-matchreads/home/u/.b/etc/fonts/fonts.confand prints no error, as it does withFONTCONFIG_PATH=~/.b/etc/fontsset:Step-by-step reproduction instructions (running
brewcommands)