Installing PHP 8 on MacOS, Linux, and Windows with phpenv — The Hard Way (But Right)
You don’t install PHP manually on macOS unless you’re one of three things:
- a developer,
- someone building something reusable,
- or a masochist with too much time.
In my case? All three.
This guide is the result of a battle-tested PHP 8.4.8 installation via phpenv
on macOS, where we will patch, downgrade, link, unlink, modify, and manually whisper sweet nothings to configuration files until the PHP gods grant us a working setup.
Let’s go.
Step 0: The Environment
You're on a Mac (Apple Silicon in my case). You want to install PHP 8.4.8, possibly for a clean reproducible dev environment using phpenv
, rather than cluttering your system PHP.
You also want to build a reusable PHP package (like php-multidispatch
), and you want the environment stable and configurable.
Step 1: Install phpenv and php-build
brew install phpenv php-build
# OR clone manually if you want more control:
git clone https://github.com/phpenv/phpenv.git ~/.phpenv
echo 'export PATH="$HOME/.phpenv/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(phpenv init -)"' >> ~/.zshrc
source ~/.zshrc
# Install php-build plugin
git clone https://github.com/php-build/php-build.git ~/.phpenv/plugins/php-build
Verify:
phpenv --version
Step 2: Install the required libraries via Homebrew
To compile PHP from source, a bunch of headers and libraries are needed:
brew install \
autoconf \
bison \
re2c \
libxml2 \
libjpeg \
freetype \
icu4c \
libpng \
libzip \
oniguruma \
bzip2 \
libiconv \
tidy-html5 \
pkg-config
Ensure these environment variables are set (adapt paths if needed):
export CPPFLAGS="-I$(brew --prefix bzip2)/include -I$(brew --prefix libzip)/include -I$(brew --prefix libxml2)/include -I$(brew --prefix icu4c)/include"
export LDFLAGS="-L$(brew --prefix bzip2)/lib -L$(brew --prefix libzip)/lib -L$(brew --prefix libxml2)/lib -L$(brew --prefix icu4c)/lib"
export PKG_CONFIG_PATH="$(brew --prefix icu4c)/lib/pkgconfig:$(brew --prefix bzip2)/lib/pkgconfig"
Check:
echo $CPPFLAGS
echo $LDFLAGS
Step 3: Downgrade ICU if Needed
PHP 8.3 might fail to compile with newer icu4c
. You can install an older version:
brew unlink icu4c
brew tap-new josephus/oldicu
brew extract --version=72 icu4c homebrew/core --tap=josephus/oldicu
brew install josephus/oldicu/icu4c@72
brew link --force --overwrite icu4c@72
export ICU_VERSION="72"
export ICU_PATH="$(brew --prefix icu4c@72)"
export CPPFLAGS="-I$ICU_PATH/include"
export LDFLAGS="-L$ICU_PATH/lib"
export PKG_CONFIG_PATH="$ICU_PATH/lib/pkgconfig"
Test:
pkg-config --modversion icu-uc
# Should return something like 72.1
Step 4: Edit the php-build Definition File
Create or edit the PHP version definition to include required options:
nano ~/.phpenv/plugins/php-build/share/php-build/definitions/8.4.8
Add these lines (you can copy/paste over the file if needed):
configure_option "--enable-gd"
configure_option "--with-jpeg"
configure_option "--with-zip"
configure_option "--with-mhash"
configure_option "--with-bz2=$(brew --prefix bzip2)" # added manually
configure_option "--with-iconv=$(brew --prefix libiconv)" # added manually
configure_option "--with-tidy=$(brew --prefix tidy-html5)" # added manually
configure_option -D "--with-xmlrpc"
export CXXFLAGS="-std=c++17"
install_package "https://www.php.net/distributions/php-8.4.8.tar.bz2"
install_xdebug "3.4.4"
enable_builtin_opcache
Step 5: Finally Install PHP 8.4.8
Clean up if a previous build failed:
rm -rf /var/tmp/php-build/source/8.4.8
Then install:
phpenv install 8.4.8
Set as default:
phpenv global 8.4.8
Test:
php --version
If you see PHP 8.4.8, you're done.
Bonus: Switch ICU Back If Needed
After the install, if other tools break due to ICU version, you can revert:
brew unlink icu4c@72
brew link --force icu4c
Appendix: Troubleshooting
- Check logs under
/tmp/php-build.*.log
if anything fails. - Make sure you don’t have Conda or other
bzip2
/icu
/libxml2
versions shadowing the Homebrew ones.conda deactivate
might help. - Double-check
pkg-config
is pointing to Homebrew versions.
Linux (Ubuntu): Installing PHP with phpenv
The installation in Linux is very similar to the steps for MacOS:
1. Install Dependencies
sudo apt update
sudo apt install -y make build-essential libssl-dev \
zlib1g-dev libbz2-dev libreadline-dev \
libsqlite3-dev wget curl llvm \
libncurses5-dev libncursesw5-dev \
xz-utils tk-dev libxml2-dev libzip-dev \
libjpeg-dev libpng-dev autoconf bison re2c
2. Install phpenv
git clone https://github.com/phpenv/phpenv.git ~/.phpenv
echo 'export PATH="$HOME/.phpenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(phpenv init -)"' >> ~/.bashrc
source ~/.bashrc
3. Install php-build
Plugin
git clone https://github.com/php-build/php-build.git ~/.phpenv/plugins/php-build
4. Install PHP
phpenv install 8.4.8 # Or whichever version you want
phpenv global 8.4.8
php -v
5. Install Composer and PHPUnit
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
composer --version
composer global require phpunit/phpunit
~/.composer/vendor/bin/phpunit --version
Windows: Installing PHP with phpenv
via WSL
Note: phpenv does not run natively on Windows, but you can use it inside WSL (Windows Subsystem for Linux). On standard Windows, use Scoop or Chocolatey instead.
1. Install WSL & Ubuntu
Install WSL and Ubuntu from the Windows Store if you haven’t already.
wsl --install
# Or, from an admin PowerShell:
wsl --install -d Ubuntu
2. Open Ubuntu in WSL and Follow Linux Steps
Follow the exact same steps as above for Ubuntu:
- Install dependencies
- Clone phpenv
- Install php-build
- Install PHP versions
- Set your desired PHP version as global
3. Composer & PHPUnit
Same as Linux:
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
composer --version
composer global require phpunit/phpunit
~/.composer/vendor/bin/phpunit --version
Summary Table
Platform |
phpenv Available? |
Method |
---|---|---|
macOS |
Yes |
brew install phpenv php-build (see your article) |
Linux (Ubuntu) |
Yes |
See steps above |
Windows (native) |
No |
Use Scoop or Chocolatey |
Windows (via WSL) |
Yes |
Use the Linux method inside WSL |
Tip:
If you want simple prebuilt PHP on Windows, just use Scoop:
scoop install php composer phpunit
…but for advanced devs wanting multiple PHP versions and more control, use phpenv
on Linux/macOS/WSL.
Final Words
Yes, this is not the easiest way. But it's the cleanest way to:
- build your own PHP extensions,
- maintain multiple versions side-by-side,
- ensure reproducibility,
- and understand exactly what your PHP installation is made of.
It’s pain now, freedom later.
Happy hacking!