Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

brew ignores HOMEBREW_* variables #668

Closed
2 tasks done
ogerardin opened this issue Jun 11, 2022 · 10 comments
Closed
2 tasks done

brew ignores HOMEBREW_* variables #668

ogerardin opened this issue Jun 11, 2022 · 10 comments
Labels

Comments

@ogerardin
Copy link

ogerardin commented Jun 11, 2022

  • your problem was from running the official install or uninstall script?
  • after installation: ran brew config and brew doctor and included their output with your issue? If you couldn't install: provided your OS version with the output of your issue?

What you were trying to do (and why)

I have installed Homebrew on a Synology NAS (I had to cheat a little bit with glibc check but that's not the point here).
As the home directories on DSM are in /var/services/homes, I have a symbolic link /home -> /var/services/homes, which itself resolves to /volume2/homes on my NAS.

What happened (include command output)

Although Homebrew is effectively installed in /home/linuxbrew/.linuxbrew, it insists that it is installed in /volume2/homes/linuxbrew/.linuxbrew, which is bad because as you know it will compile stuff instead of using prebuilt binaries.

I thought overriding the environment variables set by brew shellenv in ~/.profile would work, so instead of
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
I have explicitly defined all the variables that shellenv would set, replacing /volume2/homes/linuxbrew with /home/linuxbrew:

export HOMEBREW_PREFIX="/home/linuxbrew/.linuxbrew";
export HOMEBREW_CELLAR="/home/linuxbrew/.linuxbrew/Cellar";
export HOMEBREW_REPOSITORY="/home/linuxbrew/.linuxbrew/Homebrew";
export PATH="/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin${PATH+:$PATH}";
export MANPATH="/home/linuxbrew/.linuxbrew/share/man${MANPATH+:$MANPATH}:";
export INFOPATH="/home/linuxbrew/.linuxbrew/share/info:${INFOPATH:-}";

Unfortunately it doesn't change anything, as it seems the variables are ignored and brew always recomputes its real path...
So when I try to install gcc for example I get:

Warning: Building gcc from source as the bottle needs:
- HOMEBREW_CELLAR: /home/linuxbrew/.linuxbrew/Cellar (yours is /volume2/homes/linuxbrew/.linuxbrew/Cellar)
- HOMEBREW_PREFIX: /home/linuxbrew/.linuxbrew (yours is /volume2/homes/linuxbrew/.linuxbrew)

(I didn't let it finish)

So how can I force brew to use the prefix /home/linuxbrew/.linuxbrew ??

brew config
HOMEBREW_VERSION: 3.5.1-43-gad13524
ORIGIN: https://github.com/Homebrew/brew
HEAD: ad13524bcc50c145cc7d3c70dd4d2cff5d16d231
Last commit: 3 hours ago
Core tap ORIGIN: https://github.com/Homebrew/homebrew-core
Core tap HEAD: d9c17c803bae0627449f6d39cab324a91cb9231c
Core tap last commit: 3 hours ago
Core tap branch: master
HOMEBREW_PREFIX: /volume2/homes/linuxbrew/.linuxbrew
HOMEBREW_REPOSITORY: /volume2/homes/linuxbrew/.linuxbrew/Homebrew
HOMEBREW_CELLAR: /volume2/homes/linuxbrew/.linuxbrew/Cellar
HOMEBREW_CASK_OPTS: []
HOMEBREW_CORE_GIT_REMOTE: https://github.com/Homebrew/homebrew-core
HOMEBREW_MAKE_JOBS: 1
Homebrew Ruby: 2.6.8 => /volume2/homes/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/vendor/portable-ruby/2.6.8_1/bin/ruby
CPU: single-core 64-bit unknown_0x6_0x5c
Clang: N/A
Git: 2.33.0 => /bin/git
Curl: 7.54.0 => /bin/curl
Kernel: Linux 4.4.59+ x86_64 GNU/Linux
OS: Unknown
Host glibc: 2.20
/usr/bin/gcc: N/A
/usr/bin/ruby: N/A
glibc: 2.23
gcc@5: N/A
xorg: N/A  
brew doctor
Warning: Some installed formulae are deprecated or disabled.
You should find replacements for the following formulae:
  isl@0.18

Warning: No developer tools installed.
Install Clang or run brew install gcc.

Warning: Your Homebrew's prefix is not /home/linuxbrew/.linuxbrew.
Some of Homebrew's bottles (binary packages) can only be used with the default
prefix (/home/linuxbrew/.linuxbrew).
You will encounter build failures with some formulae.
Please create pull requests instead of asking for help on Homebrew's GitHub,
Twitter or any other official channels. You are responsible for resolving
any issues you experience while you are running this
unsupported configuration.

Warning: /usr/bin occurs before /volume2/homes/linuxbrew/.linuxbrew/bin in your PATH.
This means that system-provided programs will be used instead of those
provided by Homebrew. Consider setting your PATH so that
/volume2/homes/linuxbrew/.linuxbrew/bin occurs before /usr/bin. Here is a one-liner:
echo 'export PATH="/volume2/homes/linuxbrew/.linuxbrew/bin:$PATH"' >> ~/.profile

The following tools exist at both paths:
ldd
locale
localedef

Warning: Homebrew's "bin" was not found in your PATH.
Consider setting your PATH for example like so:
echo 'export PATH="/volume2/homes/linuxbrew/.linuxbrew/bin:$PATH"' >> ~/.profile

Warning: Homebrew's "sbin" was not found in your PATH but you have installed
formulae that put executables in /volume2/homes/linuxbrew/.linuxbrew/sbin.
Consider setting your PATH for example like so:
echo 'export PATH="/volume2/homes/linuxbrew/.linuxbrew/sbin:$PATH"' >> ~/.profile

env
MANPATH=/home/linuxbrew/.linuxbrew/share/man:
TERM=xterm-256color
SHELL=/bin/sh
HOMEBREW_REPOSITORY=/home/linuxbrew/.linuxbrew/Homebrew
SSH_CLIENT=192.168.86.42 63646 2222
SSH_TTY=/dev/pts/10
LC_ALL=en_US.utf8
USER=olivier
PAGER=more
MAIL=/var/mail/olivier
PATH=/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/syno/sbin:/usr/syno/bin:/usr/local/sbin:/usr/local/bin
PWD=/var/services/homes/olivier
LANG=en_US.utf8
SHLVL=1
HOME=/var/services/homes/olivier
TERMINFO=/usr/share/terminfo
HOMEBREW_PREFIX=/home/linuxbrew/.linuxbrew
LOGNAME=olivier
SSH_CONNECTION=192.168.86.42 63646 192.168.86.30 2222
PGDATA=/var/services/pgsql
INFOPATH=/home/linuxbrew/.linuxbrew/share/info:
HOMEBREW_CELLAR=/home/linuxbrew/.linuxbrew/Cellar
_=/bin/env
OLDPWD=/var/services/homes

What you expected to happen

I expected the environment variables HOMEBREW_* that I set manually to override the computed values.
Or even better, that brew would realize that is is actually installed in /home/linuxbrew/.linuxbrew even though it's a link, and not complain...

Step-by-step reproduction instructions (by running brew commands)

See above

@XuehaiPan
Copy link
Contributor

brew always uses the real path (physical path). See pwd -P (not -L) at line 42:

https://github.com/Homebrew/brew/blob/ad13524bcc50c145cc7d3c70dd4d2cff5d16d231/bin/brew#L42-L44

@ogerardin
Copy link
Author

brew always uses the real path (physical path). See pwd -P (not -L) at line 42:

Yes that's what I gathered, but why?
What matters is that Homebrew is accessible using /home/linuxbrew/.linuxbrew, and that's all it should check. Otherwise it defeats the purpose of symbolic links.

@ogerardin
Copy link
Author

What's even the use of the environment variables if brew ignores them and recalculates its path each time ??

@XuehaiPan
Copy link
Contributor

XuehaiPan commented Jun 12, 2022

What matters is that Homebrew is accessible using /home/linuxbrew/.linuxbrew, and that's all it should check.

In Homebrew/Library all paths are resolved by p.realpath and I think using symlinks might break things, such as sandbox on macOS. In addition, brew works fine if you make multiple symlinks to different locations:

ln -s "${HOMEBREW_PREFIX}" /path/to/prefixA
ln -s "${HOMEBREW_PREFIX}" /path/to/prefixB

If we resolve HOMEBREW_PREFIX as the logical path, the following commands will give different results:

brew install ...
$(realpath $(which brew)) install ...
/path/to/prefixA/bin/brew install ...
/path/to/prefixB/bin/brew install ...

Otherwise it defeats the purpose of symbolic links.

Inside HOMEBREW_PREFIX, all things are installed as symbolic links, such as cellar/formula/version to opt/formula, and opt/formula/bin/executable to hombrew_prefix/bin/executable.

What's even the use of the environment variables if brew ignores them and recalculates its path each time ??

brew always recalculates HOMEBREW_PREFIX, HOMEBREW_REPOSITORY, HOMEBREW_LIBRARY, and HOMEBREW_CELLAR.

@XuehaiPan
Copy link
Contributor

As the home directories on DSM are in /var/services/homes, I have a symbolic link /home -> /var/services/homes, which itself resolves to /volume2/homes on my NAS.

I think you can mount /var/services/homes as /home in fstab rather than make a symbolic link.

Moreover, maybe it's fine to use /home/linuxbrew/.linuxbrew as HOMEBREW_PREFIX on Linux if:

if [[ -n "${HOMEBREW_LINUX}" ]]
then
  HOMEBREW_DEFAULT_PREIFX="/home/linuxbrew/.linuxbrew"
  if [[ "$(realpath "${HOMEBREW_BREW_FILE}")" == "$(${HOMEBREW_DEFAULT_PREIFX}/bin/brew)" ]]
  then
    HOMEBREW_PREIFX="${HOMEBREW_DEFAULT_PREIFX}"
  else
    HOMEBREW_PREFIX="${HOMEBREW_BREW_FILE%/*/*}"
  fi
fi

On macOS, we should not allow this.

Any thoughts?

@ogerardin
Copy link
Author

If we resolve HOMEBREW_PREFIX as the logical path, the following commands will give different results:

brew install ...
$(realpath $(which brew)) install ...
/path/to/prefixA/bin/brew install ...
/path/to/prefixB/bin/brew install ...

So what ? you have several paths to brew. Not a problem, and this can't be prevented anyway.
What I care about is that it as accessible using /home/linuxbrew/.linuxbrew, since that is the condition to use prebuilt binaries.

Inside HOMEBREW_PREFIX, all things are installed as symbolic links, such as cellar/formula/version to opt/formula, and opt/formula/bin/executable to hombrew_prefix/bin/executable.

Good, but it doesn't help.

brew always recalculates HOMEBREW_PREFIX, HOMEBREW_REPOSITORY, HOMEBREW_LIBRARY, and HOMEBREW_CELLAR.

I'd like to ask again: why is it done so ? What is the use of environment variables if you can't override them?

@MikeMcQuaid
Copy link
Member

What matters is that Homebrew is accessible using /home/linuxbrew/.linuxbrew, and that's all it should check. Otherwise it defeats the purpose of symbolic links.

No. This is long-running behaviour that Homebrew on macOS on Intel has relied on for many years. If we change this on Linux: we will break existing configurations.

We would consider a new environment variable to adjust this behaviour for cases like yours.

What's even the use of the environment variables if brew ignores them and recalculates its path each time ??

Internal implementation details.

I think you can mount /var/services/homes as /home in fstab rather than make a symbolic link.

This workaround seems preferable to changing Homebrew, though.

What is the use of environment variables if you can't override them?

They are not documented as configurable. How and why Homebrew uses them internally is not really relevant here.

@ogerardin
Copy link
Author

ogerardin commented Jun 13, 2022

I think you can mount /var/services/homes as /home in fstab rather than make a symbolic link.

This workaround seems preferable to changing Homebrew, though.

/var/services/homes is already a symbolic link to /volume2/homes, there is no separate filesystem.
But then I thought of a bind mount, so I removed the /home link and did:

olivier@ds918plus:/$ sudo mkdir /home
olivier@ds918plus:/$ sudo mount -o bind "/volume2/homes" /home

And then the miracle happened:

olivier@ds918plus:/var/services/homes$ brew install gcc
(...)
olivier@ds918plus:/var/services/homes$ brew list
==> Formulae
binutils  gcc  gcc@5  glibc  gmp  isl  isl@0.18  libmpc  linux-headers@4.4  m4	mpfr  zlib  zstd

It seems I now have a fully functional Homebrew on DSM!

We would consider a new environment variable to adjust this behaviour for cases like yours.

That would still be useful. I'm not sure bind mount is a viable option for everyone.

Also, in addition to the bind mount I had to do a little trick to complete the initial install, as follows: DSM does have a supported version of glibc, but it doesn't have the ldd command which the install script uses to determine the version of glibc. So I just created a script named ldd that outputs the version of glibc, and that did the trick.

We are actually this close to having Homebrew install out of the box on DSM. Where do we go from here?

@MikeMcQuaid
Copy link
Member

We are actually this close to having Homebrew install out of the box on DSM. Where do we go from here?

I'm not sure. I'm unsure if it's worth making changes in Homebrew for things that one person has asked for but: it depends what those changes are. I think you'll need to be the one submitting/proposing those changes in PRs, though.

@ogerardin
Copy link
Author

I'm not sure. I'm unsure if it's worth making changes in Homebrew for things that one person has asked for but: it depends what those changes are. I think you'll need to be the one submitting/proposing those changes in PRs, though.

Fine with me. DSM really needs an easy to install and state-of-the-art command line package manager, and the only alternative (Entware/opkg) is not that sexy.

Meanwhile I have published my findings on the Synology forum so that it could benefit others: https://community.synology.com/enu/forum/1/post/153781

I might be the only to have asked here, but there has been some interest for Linuxbrew on DSM e.g. Linuxbrew/brew#893

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants