phpv8 / v8js

V8 Javascript Engine for PHP — This PHP extension embeds the Google V8 Javascript Engine
http://pecl.php.net/package/v8js
MIT License
1.84k stars 200 forks source link

Improve configureless installation on debian and redhat machines #532

Closed JoshuaBehrens closed 1 month ago

JoshuaBehrens commented 2 months ago

Solves #522 Solves #529

This pull request shall allow debian/ubuntu installation to get this extension running quickly. I tested it using this script and empty OS installations:

apt update -yy && apt install -y build-essential git libv8-dev php php-dev
git clone https://github.com/JoshuaBehrens/v8js.git --branch feature/hassle-free-installation
cd v8js
phpize
./configure
make 
make test
make install
php -dextension=v8js -m

I tested this on Debian 12 on amd64 and arm64 Hetzner VMs with no further sources. So I was running php@8.2 and v8@10. Debian 11 provides php@7.4 out of the box and only ships v8@7 and does not run out of the box. Likely works with different php and v8 sources.

I tried it on CentOS 9 Stream on arm64 but there is a really bad support for arm binaries. I tried also on an amd64 machine and it is an installation hell. The v8-devel package depends on nodejs@16. There is a yum module for nodejs but only for nodejs 18, 20 and 22. AFAIK 18 would've be the matching one to v8@10 but v8-devel seems to be for the headers and library. Yikes! I compiled v8 following your instructions in the Linux Readme. This is really helpful and sort of works. Eventually I got it running there but it is not handy on the first try:

yum install git php php-devel unzip curl
curl -L https://github.com/ninja-build/ninja/releases/download/v1.12.1/ninja-linux.zip -o ninja-linux.zip
unzip ninja-linux.zip
export PATH=`pwd`:$PATH

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:"$PATH"
fetch v8
cd v8
git checkout 10.2.154.26
gclient sync

tools/dev/v8gen.py -vv x64.release -- is_component_build=true use_custom_libcxx=false
ninja -C out.gn/x64.release/

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 -R include/* /opt/v8/include/

cd $HOME

git clone https://github.com/JoshuaBehrens/v8js.git --branch feature/hassle-free-installation
cd v8js
phpize
./configure --with-v8js=/opt/v8/ CPPFLAGS="-DV8_COMPRESS_POINTERS"
make
make test
make install
php -dextension=v8js -m

I tried it on alpine but this seems to be a hassle-some story seeing Dockerfiles like this: https://github.com/modprobe/alpine-v8/blob/master/Dockerfile that need an interim debian layer for things to work.

I tried it on macOS 14/SDK 15 and installed v8 via homebrew but this is shipping v8 in version 12. This code is not yet ready for v8@12. I fixed some parts but this is a rabbit hole I am not yet ready to dig through. But I have a change for the config.m4, that understands to work with the filestructure in /opt/homebrew. So it might be a good additional change later, when I got v8@10 on macOS running.

So I tried to build a homebrew formula to build an old version of v8 as there was once a v8 formula compiling version 10 but it collides with the macOS SDK headers and the ones, that llvm ships. Really dumb one. I will try to work that one out because it is a shame, that there is only a "latest" formula. And I really need the macOS support.

JoshuaBehrens commented 2 months ago

@stesie I tried to build a homebrew formula to get an installation of v8@10 and apparently this is not a release anymore, that neither receives features nor is part of the extended support. I queried this using this command:

$ curl -so - https://chromiumdash.appspot.com/fetch_releases\?platform\=Mac | jq '.|map(.hashes.v8)|unique|join("\n")' -r | xargs -n1 printf 'https://chromium.googlesource.com/v8/v8.git/+/%s\n' | xargs -n1 curl -so - | grep -oie 'version 1.*$' | sort -u
Version 12.6.228.21
Version 12.6.228.28
Version 12.6.228.30
Version 12.7.224.16
Version 12.8.374.1
Version 12.8.374.11
Version 12.8.374.21
Version 12.8.374.24
Version 12.8.374.26
Version 12.8.374.31
Version 12.8.374.33
Version 12.8.374.4
Version 12.8.374.7
Version 12.9.117
Version 12.9.191
Version 12.9.202.10
Version 12.9.202.16
Version 12.9.202.18
Version 12.9.202.3
Version 12.9.202.6
Version 12.9.73.1
Version 13.0.194
Version 13.0.244
Version 13.0.245
Version 13.0.245.1
Version 13.0.28
Version 13.0.66990160
Version 13.0.88
Version 13.1.19
Version 13.1.24
Version 13.1.29

With this in mind, should one push this library to support version 12 first?

stesie commented 1 month ago

@JoshuaBehrens once more, huge thank you for this contribution. finally found some time to give it a try :-)

I think the script will have some issues, in case there are spaces in the directory name. But also the old code looks susceptible to that. So no worries. But in case you'd like to continue working on that, feel free :smile:

That said, yes, I think the next goal for this project would be to make it work with recent versions of V8, i.e. 12.x and 13.x

and maybe we should also update the README files, telling that it's now also possible to use the libs that are shipped with Debian, Ubuntu, ...

So, once more, thank you !

stesie commented 1 month ago

hmmm, there seems to be a regression ...

given an Ubuntu 24.04 system, that has the lib installed in /usr ... and also manually compiled (like shown in the README.Linux.md file) in /opt

stesie@schlumpf:~/Projekte/v8js$ ./configure --with-v8js=/opt/v8-12.8.374.34 LDFLAGS="-lstdc++" CPPFLAGS="-DV8_COMPRESS_POINTERS"
...
checking for V8 files in default path... found in /opt/v8-12.8.374.34
found in /opt/v8-12.8.374.34
found in /usr

... the installation in /opt triggers the first and the third if successively. Then it finds the one in /usr ... so after all the one in /usr wins, even the user explicitly gave a different one.

IMHO we should override SEARCH_PATH="$PHP_V8JS" if it is given.

For which kind of installation/system is the first if block? can we maybe make it more explicit, by e.g. checking for a certain .h file, and not just assume stuff !?

and one more thing:

  case $host_os in
    darwin* )
      # MacOS does not support --rpath
      ;;
    * )
      LDFLAGS="$LDFLAGS -Wl,--rpath=$PHP_V8JS/$PHP_LIBDIR"
      ;;
  esac

... I think we should either evaluate this only if PHP_V8JS is actually set (so it matches what was present before) ... or we should also use it in the common path case ... but then probably use V8_LIBRARY_DIR variable instead.

However I think it doesn't make sense to do this in the "common path case", since the library loader should be configured to check these directories anyways.