How to install an old HomeBrew package

I accidentally ran brew upgrade on a set of packages which caused brew to bump most library packages that were installed on my computer. This caused issues compiling PHP via asdf.

I thought it would be easy to install an older version of the offending package, icu4c, but I was very wrong. In recent (2021?) versions of brew. I ended up learning a bit about the homebrew internals and solving

Installing an old version of icu4c to fix PHP compilation on macOS

I discovered the offending package was icu4c, but the PHP compile script did not indicate that I was using an unsupported package version. make emitted an error with an 'international' (intl) identifier in the offending file, which after some googling indicated that icu4c was the offending package:

3 errors generated.
make: *** [ext/intl/dateformat/dateformat_attr.lo] Error 1

Brew used to support installing packages via a formula URL. Unfortunately, this method of installation was removed in a recent version of brew. Instead of something like brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/284ffd99cb862671202e685d7eced806bbc30dc4/Formula/icu4c.rb you need to execute (found this snippet through this blog post):

brew tap-new $USER/local-tap
brew extract --version=68.2 icu4c $USER/local-tap
brew install icu4c@68.2

You can determine the last supported version in homebrew using git history via the URL exposed when running brew info icu4c.

However, extracting a specific version through this method does not use the same package name. The package name is icu4c@68.2 with version 68.2 which means any scripts which check for a package via brew list --version icu4c will fail. If it wasn't for this nuance, this StackOverflow answer would have had all of the information I needed.

Additionally, even if the package name was the same, brew removed the switch command. Now, the preferred way to switch versions is to relink a specific version:

brew link --overwrite --force icu4c@68.2

However, this doesn't work:

Warning: Refusing to link macOS provided/shadowed software: icu4c@68.2

If you need to have icu4c first in your PATH, run:
  echo 'export PATH="/usr/local/opt/icu4c@68.2/bin:$PATH"' >> ~/.zshrc
  echo 'export PATH="/usr/local/opt/icu4c@68.2/sbin:$PATH"' >> ~/.zshrc

For compilers to find icu4c you may need to set:
  export LDFLAGS="-L/usr/local/opt/icu4c@68.2/lib"
  export CPPFLAGS="-I/usr/local/opt/icu4c@68.2/include"

For pkg-config to find icu4c you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/icu4c@68.2/lib/pkgconfig"

From what I can tell, the only real workaround for this error is to manually specify the environment variables indicated in the installation post-install message. The downside with this approach is if you aren't installing the package directly you'd have to modify the underlying script which could be a major pain.

If you don't want to go that route, here's the easiest alternative I found:

# uninstall the newer version of the package that you accidentally installed
brew uninstall --ignore-dependencies icu4c

# `extract` the version you'd like to install into a custom tap
brew tap-new $USER/local-tap
brew extract --version=68.2 icu4c $USER/local-tap

# jump into the new tap you created
cd $(brew --repository $USER/local-tap)/Formula

# rename the formula
mv icu4c@68.2.rb icu4c.rb

# change the name of the formula by removing "AT682" from the `class` definition
nano icu4c.rb

# then, install this specific formula directly
brew install $(brew --repository $USER/local-tap)/Formula/icu4c.rb

PHP 7.4.x & 8.x works with icu4c 68.2. PHP 7.2 did not compile properly with this version. To my surprise the PHP compilation script will not notify you that you are using an unsupported version of a package. php-build is a great project, which is probably worth using instead of asdf, and is a look place to look for PHP compilation tips & tricks.

Worth noting that the only reason I couldn't use the simple extract and install route is I needed brew list --version $package_name to split out a valid package reference. If you don't need that, you should be able to get away with the extract route and setting export PKG_CONFIG_PATH directly in the shell.

I'm very surprised installing an older version of a package was this messy. I can see why using a docker container is a better way to go for PHP development. The build story for PHP isn't much better than what it was 10 years ago.

Installing the PHP ImageMagick Pecl extension

I also ran into issues installing the imagemagick extension with PHP8 (pecl install imagick) . Here's what I found as far as version compatibility goes:

  • You need to brew install imagemagick to install the pecl extension
  • Imagick pecl extension works with the latest ImageMagick from homebrew 7
  • Imagick doesn't work with PHP8 yet
  • You need to enable the extension "extension=imagick.so" > $(asdf where php)/conf.d/php.ini

Upgrading an old brew-powered MySQL installation

I had MySQL data from an older installation on my machine that was causing issues. MySQL would not start properly and brew services was not listing the correct status.

Here's what worked for me to fix it, although you might need to do more:

# this will wipe all mysql data
# if you want to keep data from your old mysql installation, do not do this
sudo rm -rf /usr/local/var/mysql/

brew remove mysql
brew cleanup

brew install mysql

I was then able to mysql.server start without an issue. If you want MySQL to start automatically on boot, run brew services start mysql. Quick pro-tip: take a look Sequel ace, a great GUI MySQL client.