Skip to content
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

Building v8 on windows #287

Closed
pinepain opened this issue Jan 30, 2017 · 16 comments
Closed

Building v8 on windows #287

pinepain opened this issue Jan 30, 2017 · 16 comments

Comments

@pinepain
Copy link
Member

Hi @stesie! I found that it's not an easy task to build both v8js and php-v8 on windows, mostly because of lack of up to date v8 distribution. At this time I don't even build for windows as I don't even have windows machine, though, I think it might be interested for some users.

At this time I found pmed/v8-nuget repo which targets on building v8 for windows platform (see pacakges - https://www.nuget.org/profiles/pmed). I guess it might be interesting for you even in a state it is.

As my extension stick to the bleeding edge, I'm pretty interested to adapt that building script for some 5.8 or at least 5.6. Basically, even 5.6 (the stable branch) would be ok, as v8 changed their build system at 5.5, I guess. At this time I have already adapted build scripts for homebrew and ubuntu, which, with minor tweaks I'm working right now, could be used as a ground for v8-nuget upgrading.

So if you are interested, we may ask @pmed for assisance or offer him some assistance and get that windows packages.

@stesie
Copy link
Member

stesie commented Jan 30, 2017

cc'ing our man for Windows packaging @Jan-E :-)

TBH I'm really undecided what to think of both our PHP V8 extensions wrt. Windows. I'm not a Windows user at all and to me it feels like demand for V8Js on Windows is really little. So so far I was really happy that @Jan-E started to care :) ... after some painful use/debugging on Windows (on AWS instances) before myself.

I'd really appreciate if we'd have up-to-date packages, maybe regularly built on appveyor. Yet I don't have the time to care for the infrastructure myself. I used to have a Windows package builder on the Jenkins instance (with on-demand build slaves on AWS), yet this is broken for a long time

@pinepain
Copy link
Member Author

I'm also not a Windows user, probably like you, but I stick to macOS. I just remembered that you have some windows support, but I see that there is pretty old v8. Also, having proper libv8 builds for windows will make possible building dlls on pecl, which itself should be quite nice for windows users (if any). But let's hear from Jan-E is a nuget good for our goals or not (I have only a brief idea what is it).

@flexarts
Copy link

flexarts commented Mar 3, 2017

@Jan-E
Thank you for your hard work making the windows world happy in terms of PHP extensions ;-) I work for a company which produced enterprise software and we are required to use the M$ plattform by our clients. We are happy users of your up-to-date extension builds of e.g. curl/apcu/ssh2.

Recently we decided to introduce a sandboxed-script engine into our product by using the V8JS extension. As always when integrating new PHP modules I went to this thread. But unfortunatly the Windows builds of the V8 library are broken since you moved from V8 4.9 to 5.4+.
At first sight everythings seems to work when checking out phpinfo(). But if you try to create a new V8 instance in PHP like this:

$v8 = new V8Js();

There is a segmentation fault and the whole PHP Engine terminates like this:

#
# Fatal error in d:\chromium\v8\src\snapshot\natives-external.cc, line 122
# Check failed: holder_.
#

==== C stack trace ===============================

        v8::base::time_internal::TimeBase<v8::base::TimeTicks>::ToInternalValue
[0x00007FF8121621CB+60331]
        v8::base::time_internal::TimeBase<v8::base::TimeTicks>::ToInternalValue
[0x00007FF81215F48D+48749]
        v8::internal::compiler::TopLevelLiveRange::AddUseInterval [0x00007FFFF45
40B4D+11083229]
        v8::internal::compiler::TopLevelLiveRange::AddUseInterval [0x00007FFFF40
296B1+5744961]
        v8::internal::compiler::TopLevelLiveRange::AddUseInterval [0x00007FFFF40
2515E+5727214]
        v8::internal::compiler::TopLevelLiveRange::AddUseInterval [0x00007FFFF41
0B64D+6670557]
        v8::internal::compiler::TopLevelLiveRange::AddUseInterval [0x00007FFFF3B
21915+469925]
        get_module [0x00007FFFFA9436E8+9464]
        (No symbol) [0x00007FF811EF4F17]
        ZEND_DO_FCALL_SPEC_HANDLER [0x00007FFFF762FD51+1153] (c:\php-sdk\php70dev\zend\zend_vm_execute.h:854)
        execute_ex [0x00007FFFF7627014+36] (c:\php-sdk\php70dev\zend\zend_vm_execute.h:417)
        (No symbol) [0x00007FF811EF4C0F]
        zend_execute [0x00007FFFF7626F90+864] (c:\php-sdk\php70dev\zend\zend_vm_execute.h:459)
        zend_execute_scripts [0x00007FFFF75EC5AD+157] (c:\php-sdk\php70dev\zend\zend.c:1443)
        php_execute_script [0x00007FFFF76CEF91+737] (c:\php-sdk\php70dev\main\main.c:2492)
        do_cli [0x00007FF776B42786+2278] (c:\php-sdk\php70dev\sapi\cli\php_cli.c:978)
        main [0x00007FF776B43561+1505] (c:\php-sdk\php70dev\sapi\cli\php_cli.c:1347)
        __scrt_common_main_seh [0x00007FF776B4C119+285] (f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:253)
        BaseThreadInitThunk [0x00007FF822FF13D2+34]
        RtlUserThreadStart [0x00007FF8253D54E4+52]

I think it has something to do with the NativeTypes store that can not be found in V8.

Can you please checkout the problem? Right now we use the V8Js extention from your build php-7.0.12-nts-Win32-VC14-x64 as this uses the old V8 engine 4.9.385.29.

Thanks in advance for your checks!

@Jan-E
Copy link
Contributor

Jan-E commented Mar 4, 2017

Ouch. Nasty bug. Try
https://phpdev.toolsforresearch.com/V8-5.8.301.0.7z
If that works, I will have a PR for v8js.

@flexarts
Copy link

flexarts commented Mar 4, 2017

Hi @Jan-E!
Thanks for your quick response. The build works now (tested with php-7.0.17RC1-nts-Win32-VC14-x64)! Good work 👍

Another thing I recognised was that passing 64-bit integers back-and-forth between PHP and JavaScript does not work (see test 1). When converting the 64-bit integers to strings the passing (see test 2):

// test 1 (Exchange 64-bit ints natively)
$addInt = function ($a, $b) {
    return $a + $b;
};
$v8 = new V8Js('PHP');
$v8->add = $addInt;
$v8->p1 = 10;
$v8->p2 = pow(2,45);
$result1 = $v8->executeString('var res = PHP.p1+PHP.p2;"p1:"+PHP.p1+", p2:"+PHP.p2+", PHP.add(p1,p2)="+PHP.add(PHP.p1,PHP.p2)+", p1+p2="+res+" -> "+(new Date(res)).toISOString();');

// test 2 (Exchange 64-bit ints as STRING)
$addString = function ($a, $b) {
    return (String)(intval($a) + intval($b));
};
$v8 = new V8Js('PHP');
$v8->add = $addString;
$v8->p1 = '10';
$v8->p2 = (String)pow(2,45);
$result2 = $v8->executeString('var res = parseInt(PHP.p1)+parseInt(PHP.p2);"p1:"+PHP.p1+", p2:"+PHP.p2+", PHP.add(p1,p2)="+PHP.add(PHP.p1,PHP.p2)+", p1+p2="+res+" -> "+(new Date(res)).toISOString();');

$result = array('native64' => $result1, 'string64' => $result2);

Even with the V8 Build you attached $result has the following value on Windows:

// v8_version: "5.8.301.0"
// ext_version: "1.3.3"
result: {
native64: "p1:10, p2:0, PHP.add(p1,p2)=10, p1+p2=10 -> 1970-01-01T00:00:00.010Z",
string64: "p1:10, p2:35184372088832, PHP.add(p1,p2)=35184372088842, p1+p2=35184372088842 -> 3084-12-12T12:41:28.842Z"
}

On Linux with @pinepain 's PPA V8 5.2 the $result has the following value:

// v8_version: "5.2.371"
// ext_version: "1.3.3",
result: {
native64: "p1:10, p2:35184372088832, PHP.add(p1,p2)=35184372088842, p1+p2=35184372088842 -> 3084-12-12T12:41:28.842Z",
string64: "p1:10, p2:35184372088832, PHP.add(p1,p2)=35184372088842, p1+p2=35184372088842 -> 3084-12-12T12:41:28.842Z"
}

@Jan-E
Copy link
Contributor

Jan-E commented Mar 5, 2017

Good to hear it works now. With respect to the ints: it even goes wrong with some 32-bits ints. Everything >= pow(2,31) results in either a negative value or zero. Either V8 itself or the extension still treats Windows or PHP7 on Windows as 32-bits. This is not true anymore for PHP7 on 64-bits Windows:

http://php.net/manual/en/language.types.integer.php

I simplified your testscript a little bit to play around with different values:

<?php
$int = pow(2,32) - 1; // >= pow(2,31) => negative, >= pow(2,32) => 0

// test 1 (Exchange ints natively)
$v8 = new V8Js('PHP');
$v8->p2 = $int;
var_dump($v8->p2);
$result1 = $v8->executeString('var res = parseInt(PHP.p2);"p2 = " + PHP.p2 + ", res = " + res;');

// test 2 (Exchange ints as STRING)
$v8 = new V8Js('PHP');
$v8->p2 = (String)$int;
var_dump($v8->p2);
$result2 = $v8->executeString('var res = parseInt(PHP.p2);"p2 = " + PHP.p2 + ", res = " + res;');

$result = array('native' => $result1, 'string' => $result2);
print_r($result);
?>

Result (in PHP 7.1 nts x64):

D:\phpdev\php71nts.x64>php v8js.php
D:\phpdev\php71nts.x64\v8js.php:7:
int(4294967295)
D:\phpdev\php71nts.x64\v8js.php:13:
string(10) "4294967295"
Array
(
    [native] => p2 = -1, res = -1
    [string] => p2 = 4294967295, res = 4294967295
)

@Jan-E
Copy link
Contributor

Jan-E commented Mar 5, 2017

This is how I built V8 5.8.

TL;DR: these are the essential commands for x64.

call git checkout 5.8-lkgr
call gclient sync
call gn gen v5.8\x64.release --args="is_component_build=true is_debug=false v8_use_snapshot=false enable_nacl=false target_cpu=\"x64\"" --ide=vs
cd v5.8\x64.release
msbuild all.sln

Prerequisites:

My initial setup was a mixture of the Linux & Windows commands at https://www.chromium.org/developers/how-tos/install-depot-tools

D:
cd \
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git chromium
set path=D:\chromium;%path%
set GYP_MSVS_VERSION=2015
set DEPOT_TOOLS_WIN_TOOLCHAIN=0
set GYP_CHROMIUM_NO_ACTION=0
cd chromium
fetch v8
git stash

Then I ran the following batch script, inside a 'VS2015 x64 Native Tools Command Prompt' (x64) or a 'VS2015 x86 Native Tools Command Prompt' (x86):

D:
cd \chromium\v8
set WindowsSdkDir=C:\Program Files (x86)\Windows Kits\10\
set WindowsSDK_ExecutablePath_x64=C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools\x64\
set WindowsSDK_ExecutablePath_x86=C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.2 Tools\
set path=D:\chromium;%path%
set GYP_MSVS_VERSION=2015
set DEPOT_TOOLS_WIN_TOOLCHAIN=0
set GYP_CHROMIUM_NO_ACTION=0
set xn=x86
if not %platform%x==x set xn=%platform%
if %xn%==X64 set xn=x64
call git checkout 5.8-lkgr
call git pull
call gclient sync
call gn gen v5.8\%xn%.release --args="is_component_build=true is_debug=false v8_use_snapshot=false enable_nacl=false target_cpu=\"%xn%\"" --ide=vs
cd v5.8\%xn%.release
msbuild all.sln /t:clean
msbuild all.sln
pause
unittests

That is all. In the most condensed form I could describe it...

@Jan-E
Copy link
Contributor

Jan-E commented Mar 5, 2017

From #287 (comment)

I think it has something to do with the NativeTypes store that can not be found in V8.

I spent a couple of hours to solve that. 'v8_use_snapshot=false' was the crux: it disables the inclusion of https://github.com/v8/v8/blob/master/src/snapshot/natives-external.cc

@Jan-E
Copy link
Contributor

Jan-E commented Mar 5, 2017

I created a separate issue for the 32/64-bits integers:
#292

@pinepain
Copy link
Member Author

pinepain commented Mar 5, 2017

@Jan-E thanks for reply. What do you think about packaging v8 to nuget as state in a first comment here?

At this time I found pmed/v8-nuget repo which targets on building v8 for windows platform (see pacakges - https://www.nuget.org/profiles/pmed).

@Jan-E
Copy link
Contributor

Jan-E commented Mar 5, 2017

I would not mind if @pmed adds V8 5.8-lkgr to NuGet but I do not have the time for it.

@pinepain
Copy link
Member Author

pinepain commented Mar 5, 2017

I feel you. Anyway, closing as I'm not using windows and have no plans to introduce it support in my own ext at this time.

@pinepain pinepain closed this as completed Mar 5, 2017
@Jan-E
Copy link
Contributor

Jan-E commented Mar 5, 2017

BTW: I tested the 64-bits integer script ( #292 ) with this x64 NuGet build: https://www.nuget.org/packages/v8-v140-x64/

The output was the same. So the NuGet build has the same issue.

@Jan-E
Copy link
Contributor

Jan-E commented Mar 5, 2017

Another BTW: I always publish my builds at
https://www.apachelounge.com/viewtopic.php?t=6359

These builds are not yet updated with V8 5.8-lkgr, but the RC's are updated already:
https://www.apachelounge.com/viewtopic.php?t=6617

stesie added a commit to stesie/v8js that referenced this issue Mar 8, 2017
@Jan-E
Copy link
Contributor

Jan-E commented Mar 8, 2017

Fixed by #293 in x64-bits builds on https://www.apachelounge.com/viewtopic.php?t=6617

<?php
$int = pow(2,45);

// test 1 (Exchange ints natively)
$v8 = new V8Js('PHP');
$v8->p2 = $int;
var_dump($v8->p2);
$result1 = $v8->executeString('var res = parseInt(PHP.p2);"p2 = " + PHP.p2 + ", res = " + res;');

// test 2 (Exchange ints as STRING)
$v8 = new V8Js('PHP');
$v8->p2 = (String)$int;
var_dump($v8->p2);
$result2 = $v8->executeString('var res = parseInt(PHP.p2);"p2 = " + PHP.p2 + ", res = " + res;');

$result = array('native' => $result1, 'string' => $result2);
print_r($result);
?>
D:\phpdev\php71nts.x64>php v8js_long.php
D:\phpdev\php71nts.x64\v8js_long.php:7:
int(35184372088832)
D:\phpdev\php71nts.x64\v8js_long.php:13:
string(14) "35184372088832"
Array
(
    [native] => p2 = 35184372088832, res = 35184372088832
    [string] => p2 = 35184372088832, res = 35184372088832
)

@flexarts
Copy link

flexarts commented Mar 8, 2017

👍 Thx a lot for your efforts @Jan-E & @stesie. It works in my win x64 setup perfectly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants