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
158 changes: 126 additions & 32 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 @@ -61,25 +52,45 @@ jobs:
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 }} > /dev/null 2>&1
git checkout ${{ matrix.v8-versions }} > /dev/null 2>&1
gclient sync -D > /dev/null 2>&1

# 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
cp out.gn/$V8CONFIG/lib*.${LIB_EXT} out.gn/$V8CONFIG/*_blob.bin out.gn/$V8CONFIG/icudtl.dat /opt/v8/self-built/lib/
cp -R include/* /opt/v8/self-built/include/

# Go back to origin
cd "${GITHUB_WORKSPACE}"
Expand All @@ -91,6 +102,44 @@ 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: 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: |
phpize
Expand All @@ -102,12 +151,12 @@ jobs:
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 All @@ -120,7 +169,7 @@ jobs:
- name: Install dependencies
run: |
cat /etc/alpine-release
apk add php83-dev nodejs-dev g++ make
apk add php83-dev nodejs-dev nodejs g++ make file
shell: alpine.sh --root {0}

- name: Build extension
Expand All @@ -135,7 +184,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.
1 change: 1 addition & 0 deletions config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ if test "$PHP_V8JS" != "no"; then

CPPFLAGS="$CPPFLAGS -I$V8_INCLUDE_DIR -std=$ac_cv_v8_cstd"
LDFLAGS="$LDFLAGS -L$V8_LIBRARY_DIR"
LIBS="-L$V8_LIBRARY_DIR $LIBS"

if test "$libname" = "v8"; then
AC_MSG_CHECKING([for libv8_libplatform])
Expand Down
15 changes: 9 additions & 6 deletions tests/set_memory_limit_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,23 @@ if (getenv("SKIP_SLOW_TESTS")) {

$JS = <<< EOT
var jsfunc = function() {
var text = "abcdefghijklmnopqrstuvwyxz0123456789";
var text = "abcdefghijklmnopqrstuvwyxz0123456789"; // 36 bytes
var memory = "";
for (var i = 0; i < 100; ++i) {
for (var j = 0; j < 10000; ++j) {
// should generate 360 MB
for (var i = 0; i < 10_000; ++i) {
for (var j = 0; j < 1000; ++j) {
memory += text;
}
sleep(0);
}
sleep(0);
}

return memory;
};
jsfunc;
EOT;

$v8 = new V8Js();
$v8->setMemoryLimit(10000000);
$v8->setMemoryLimit(10_000_000);

$func = $v8->executeString($JS);
var_dump($func);
Expand Down
48 changes: 48 additions & 0 deletions tests/set_memory_limit_002.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
--TEST--
Test V8::setMemoryLimit() : Memory limit can be set but does not trigger when not exceeded
--SKIPIF--
<?php
require_once(dirname(__FILE__) . '/skipif.inc');

if (getenv("SKIP_SLOW_TESTS")) {
die("skip slow test");
}
?>
--FILE--
<?php

$JS = <<< EOT
var jsfunc = function() {
var text = "abcdefghijklmnopqrstuvwyxz0123456789"; // 36 bytes
var memory = "";
// should generate ~ 800 kB
for (var i = 0; i < 22; ++i) {
for (var j = 0; j < 1000; ++j) {
memory += text;
}
sleep(0);
}

return memory;
};
jsfunc;
EOT;

$v8 = new V8Js();
$v8->setMemoryLimit(10_000_000);

$func = $v8->executeString($JS);
var_dump($func);

try {
$func();
} catch (V8JsMemoryLimitException $e) {
print get_class($e); print PHP_EOL;
print $e->getMessage(); print PHP_EOL;
}
?>
===EOF===
--EXPECTF--
object(V8Function)#%d (0) {
}
===EOF===
Loading
Loading