Skip to content

Ensure MacOS support by tests #539

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

Draft
wants to merge 9 commits into
base: php8
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 202 additions & 33 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,29 @@ permissions:
contents: read

jobs:
build:
self-built-v8-cache-warmup:
strategy:
# set in accordance with number of v8-versions, so caching can kick in properly
max-parallel: 2

matrix:
operating-system:
operating-system: # &self-built-v8-operating-systems
- ubuntu-latest
# - windows-latest
# - macos-latest
php-versions:
# - '8.1'
# - '8.2'
- '8.3'
- '8.4'
v8-versions:
- macos-latest
v8-versions: # &self-built-v8-v8-versions
- 10.9.194
# - 11.9.172
- 12.9.203
# - 13.1.104
- 13.5.212

runs-on: ${{ matrix.operating-system }}

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
coverage: none
- name: Prepare cache folder v8 ${{ matrix.v8-versions }}
run: |
sudo mkdir -p /opt/v8/self-built/{lib,include}
sudo chown -R $(id -u):$(id -g) /opt/v8/self-built

- name: Restore cache v8 ${{ matrix.v8-versions }} build
id: v8-build-cache
Expand All @@ -57,29 +48,79 @@ jobs:
if: steps.v8-build-cache.outputs.cache-hit != 'true'
uses: newkdev/setup-depot-tools@v1.0.1

- name: Set up Clang
if: ${{ matrix.operating-system == 'ubuntu-latest' }}
run: |
sudo apt update
sudo apt install -y clang-19 lld-19
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-19 100
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-19 100

- name: Build v8 ${{ matrix.v8-versions }}
if: steps.v8-build-cache.outputs.cache-hit != 'true'
run: |
# Store extra tools somewhere undisturbing
set -x
cd "$(mktemp -d)"

fetch v8
ARCH=$(uname -m)
if [[ "$ARCH" == "x86_64" ]]; then
V8CONFIG="x64.release"
ARCH_SHORT="x64"
elif [[ "$ARCH" == "arm64" ]]; then
V8CONFIG="arm64.release"
ARCH_SHORT="arm64"
else
echo "Unknown architecture: $ARCH" >&2
exit 1
fi
fetch --nohooks --no-history v8
cd v8

git checkout ${{ matrix.v8-versions }}
gclient sync -D
git fetch --tag origin refs/tags/${{ matrix.v8-versions }} 1>&2 > /dev/null
git checkout ${{ matrix.v8-versions }} 1>&2 > /dev/null
gclient sync -D 1>&2 > /dev/null

# Setup GN
# Warnings are no errors - @see https://issues.chromium.org/issues/42203398#comment9
tools/dev/v8gen.py -vv x64.release -- is_component_build=true use_custom_libcxx=false treat_warnings_as_errors=false
if [[ "${{ runner.os }}" == "macOS" ]]; then
# Run gn gen with args as v8gen does not override target_cpu properly
gn gen out.gn/$V8CONFIG --args='target_cpu="'$ARCH_SHORT'" v8_target_cpu="'$ARCH_SHORT'" is_component_build=true use_custom_libcxx=true treat_warnings_as_errors=false'
else
tools/dev/v8gen.py -vv $V8CONFIG -- is_component_build=true use_custom_libcxx=true treat_warnings_as_errors=false
fi

# Build
ninja -C out.gn/x64.release/
ninja -C out.gn/$V8CONFIG/

# Install to /opt/v8/self-built
sudo mkdir -p /opt/v8/self-built/{lib,include}
sudo cp out.gn/x64.release/lib*.so out.gn/x64.release/*_blob.bin out.gn/x64.release/icudtl.dat /opt/v8/self-built/lib/
sudo cp -R include/* /opt/v8/self-built/include/
if [[ "${{ runner.os }}" == "macOS" ]]; then
LIB_EXT=dylib
else
LIB_EXT=so
fi
# Copy all V8 libraries and support files
cp -v out.gn/$V8CONFIG/lib*.${LIB_EXT}* out.gn/$V8CONFIG/*_blob.bin out.gn/$V8CONFIG/icudtl.dat /opt/v8/self-built/lib/
# Copy all V8 static libraries as well
cp -v out.gn/$V8CONFIG/obj/libv8_*.a /opt/v8/self-built/lib/ 2>/dev/null || true
# Copy headers
cp -R include/* /opt/v8/self-built/include/
# Create symlinks for libraries without version numbers
cd /opt/v8/self-built/lib/
for lib in lib*.${LIB_EXT}.*; do
if [[ $lib == *\.${LIB_EXT}.* ]]; then
ln -sf $lib ${lib%%.*} 2>/dev/null || true
fi
done
# Set library search path
if [[ "${{ runner.os }}" == "Linux" ]]; then
echo "/opt/v8/self-built/lib" | sudo tee /etc/ld.so.conf.d/v8.conf
sudo ldconfig
elif [[ "${{ runner.os }}" == "macOS" ]]; then
# On macOS, update DYLD_LIBRARY_PATH for the current session
echo "DYLD_LIBRARY_PATH=/opt/v8/self-built/lib" >> $GITHUB_ENV
# Also create symlinks in /usr/local/lib for system-wide access
sudo mkdir -p /usr/local/lib/v8
sudo ln -sf /opt/v8/self-built/lib/*.dylib* /usr/local/lib/v8/
fi

# Go back to origin
cd "${GITHUB_WORKSPACE}"
Expand All @@ -91,23 +132,106 @@ jobs:
path: /opt/v8/self-built
key: ${{ steps.v8-build-cache.outputs.cache-primary-key }}

self-built-v8:
needs: self-built-v8-cache-warmup

strategy:
matrix:
operating-system: # *self-built-v8-operating-systems
- ubuntu-latest
# - windows-latest
- macos-latest
v8-versions: # *self-built-v8-v8-versions
- 10.9.194
# - 11.9.172
- 12.9.203
- 13.5.212
php-versions:
# - '8.1'
- '8.2'
- '8.3'
- '8.4'

runs-on: ${{ matrix.operating-system }}

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
coverage: none

- name: Set up Clang
if: ${{ matrix.operating-system == 'ubuntu-latest' }}
run: |
sudo apt update
sudo apt install -y clang-19 lld-19
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-19 100
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-19 100

- name: Download cache v8 ${{ matrix.v8-versions }} build
uses: actions/cache/restore@v4
with:
path: /opt/v8/self-built
key: ${{ runner.os }}-${{ matrix.v8-versions }}-v8-build

- name: Build extension
run: |
# Set library paths based on OS
if [[ "${{ runner.os }}" == "Linux" ]]; then
export LD_LIBRARY_PATH="/opt/v8/self-built/lib:${LD_LIBRARY_PATH:-}"
# Ensure linker can find the libraries
echo "/opt/v8/self-built/lib" | sudo tee /etc/ld.so.conf.d/v8js.conf
sudo ldconfig
echo "=== Library search paths ==="
ldconfig -p | grep v8 || true
elif [[ "${{ runner.os }}" == "macOS" ]]; then
export DYLD_LIBRARY_PATH="/opt/v8/self-built/lib:${DYLD_LIBRARY_PATH:-}"
fi

# List V8 libraries for debugging
echo "=== Available V8 libraries ==="
ls -la /opt/v8/self-built/lib/

# Build the extension
phpize
./configure --with-v8js=/opt/v8/self-built LDFLAGS="-lstdc++" CPPFLAGS="-DV8_COMPRESS_POINTERS -DV8_ENABLE_SANDBOX"
make

# Configure with explicit library paths
echo "=== Running configure ==="
./configure \
--with-v8js=/opt/v8/self-built \
LDFLAGS="-L/opt/v8/self-built/lib -Wl,-rpath=/opt/v8/self-built/lib" \
CPPFLAGS="-I/opt/v8/self-built/include -DV8_COMPRESS_POINTERS -DV8_ENABLE_SANDBOX" \
LIBS="-lstdc++" \
V8_LIBS="-L/opt/v8/self-built/lib -lv8 -lv8_libplatform -lv8_libbase -lstdc++ -lpthread -ldl"

# Build with verbose output
echo "=== Building extension ==="
make -j$(nproc) V=1

# Verify the linked libraries
if [[ "${{ runner.os }}" == "Linux" ]]; then
echo "=== Checking linked libraries ==="
ldd modules/v8js.so | grep -i v8 || true
fi

# Run tests
echo "=== Running tests ==="
make test

- name: Archive test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: phpt-test-results
name: phpt-test-results-on-${{ runner.os }}-${{ matrix.v8-versions }}-${{ matrix.php-versions }}
path: |
php_test_results*.txt
tests/*.out

alpine:
alpine-package-manager-apk:
runs-on: ubuntu-latest

steps:
Expand Down Expand Up @@ -135,7 +259,52 @@ jobs:
if: failure()
uses: actions/upload-artifact@v4
with:
name: phpt-test-results
name: phpt-test-results-on-alpine
path: |
php_test_results*.txt
tests/*.out

macos-package-manager-brew:
strategy:
matrix:
php-versions:
- '8.2'
- '8.3'
- '8.4'

runs-on: macos-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
coverage: none

- name: Set up Homebrew
uses: Homebrew/actions/setup-homebrew@master

- name: Install dependencies
run: |
brew install v8
# Symlink icudtl.dat to the default location
ln -sf /opt/homebrew/Cellar/v8/$(brew list --versions v8 | awk '{print $2}')/libexec/icudtl.dat /opt/homebrew/lib/icudtl.dat

- name: Build extension
run: |
phpize
./configure --with-v8js=/opt/homebrew CPPFLAGS="-DV8_COMPRESS_POINTERS -DV8_ENABLE_SANDBOX"
make
make test

- name: Archive test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: phpt-test-results-on-macos-brew-${{ matrix.php-versions }}
path: |
php_test_results*.txt
tests/*.out
14 changes: 9 additions & 5 deletions README.Linux.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,23 +89,27 @@ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:"$PATH"

# Download v8
fetch v8
fetch --nohooks --no-history v8
gclient sync -D --no-history
cd v8

# (optional) If you'd like to build a certain version:
git fetch --tag origin refs/tags/12.0.267.36
git checkout 12.0.267.36
gclient sync -D

ARCH=$(uname -m)

# Setup GN
tools/dev/v8gen.py -vv x64.release -- is_component_build=true use_custom_libcxx=false
tools/dev/v8gen.py -vv ${ARCH}.release -- is_component_build=true use_custom_libcxx=false

# Build
ninja -C out.gn/x64.release/
ninja -C out.gn/${ARCH}.release/

# Install to /opt/v8/
sudo mkdir -p /opt/v8/{lib,include}
sudo cp out.gn/x64.release/lib*.so out.gn/x64.release/*_blob.bin \
out.gn/x64.release/icudtl.dat /opt/v8/lib/
sudo cp out.gn/${ARCH}.release/lib*.so out.gn/${ARCH}.release/*_blob.bin \
out.gn/${ARCH}.release/icudtl.dat /opt/v8/lib/
sudo cp -R include/* /opt/v8/include/
```

Expand Down
18 changes: 17 additions & 1 deletion README.MacOS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,24 @@ cd /tmp
git clone https://github.com/phpv8/v8js.git
cd v8js
phpize
./configure --with-v8js=/opt/homebrew CPPFLAGS="-DV8_COMPRESS_POINTERS"
./configure --with-v8js=/opt/homebrew CPPFLAGS="-DV8_COMPRESS_POINTERS -DV8_ENABLE_SANDBOX"
make -j4
make test
make install
```

V8Js' build system assumes that the `icudtl.dat` file is located next to the `libv8.so`
library file and compiles the path into the library itself. If for whatever reason the
`icudtl.dat` file is stored at a different place during runtime, you need to set the
php.ini variable `v8js.icudtl_dat_path` to point to the file. Otherwise locale-aware
features of V8 will not work as expected.

To avoid having to configure `v8js.icudtl_dat_path` manually, you can symlink or copy the ICU data file into the default library location. For Homebrew users, run:

In case of a brew installed v8, run:

```
ln -sf /opt/homebrew/Cellar/v8/$(brew list --versions v8 | awk '{print $2}')/libexec/icudtl.dat /opt/homebrew/lib/icudtl.dat
```

This ensures V8Js will find `icudtl.dat` automatically and timezone/i18n support will work out of the box.
Loading
Loading