From fc3556630c917358d98b0f0af77ab143417cf861 Mon Sep 17 00:00:00 2001 From: TenHian Date: Sun, 22 Dec 2024 22:23:11 +0800 Subject: [PATCH 1/4] [feat] Code change for compile on windows. Needs to modify php-src. --- docs/compile_win.md | 15 +++++++++++++++ frankenphp.c | 21 ++++++++++++++++++++- frankenphp.go | 16 ++++++++++++---- 3 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 docs/compile_win.md diff --git a/docs/compile_win.md b/docs/compile_win.md new file mode 100644 index 0000000000..150a3ce13a --- /dev/null +++ b/docs/compile_win.md @@ -0,0 +1,15 @@ +# Compile From Source on windows + +Frankenphp could only dynamic compiled on Windows system. It is still in dev. This steps to compile blew. + +## Compile PHP + +FrankenPHP is compatible with PHP 8.2 and superior. + +### Install PHP-SDK + +TODO: + +### Modify php-src + +TODO: https://github.com/dunglas/frankenphp/issues/880#issuecomment-2242103617 diff --git a/frankenphp.c b/frankenphp.c index e0e5095c40..27c4090224 100644 --- a/frankenphp.c +++ b/frankenphp.c @@ -8,7 +8,11 @@ #include #include #include -#include +#ifdef PHP_WIN32 + #include +#else + #include +#endif #include #include #include @@ -24,6 +28,8 @@ #include #elif defined(__FreeBSD__) || defined(__OpenBSD__) #include +#elif defined(__MINGW64__) +#include #endif #include "_cgo_export.h" @@ -140,7 +146,16 @@ static void frankenphp_worker_request_shutdown() { SG(rfc1867_uploaded_files) = NULL; } +// TODO: Conditional compilation here is to ensure that it will compile under windows. +// I need to see more PHP version to make visibility attributes and linkage +// modifiers clear. +// On PHP-8.3.0 windows, `php_import_environment_variables` could be pointed to +// `void _php_import_environment_variables(zval *array_ptr);` +#ifndef PHP_WIN32 PHPAPI void get_full_env(zval *track_vars_array) { +#else +void get_full_env(zval *track_vars_array) { +#endif struct go_getfullenv_return full_env = go_getfullenv(thread_index); for (int i = 0; i < full_env.r1; i++) { @@ -807,6 +822,8 @@ static void set_thread_name(char *thread_name) { pthread_setname_np(thread_name); #elif defined(__FreeBSD__) || defined(__OpenBSD__) pthread_set_name_np(pthread_self(), thread_name); +#elif defined(__MINGW64__) + pthread_setname_np(pthread_self(), thread_name); #endif } @@ -851,6 +868,7 @@ static void *php_thread(void *arg) { } static void *php_main(void *arg) { +#ifndef __MINGW64__ /* * SIGPIPE must be masked in non-Go threads: * https://pkg.go.dev/os/signal#hdr-Go_programs_that_use_cgo_or_SWIG @@ -863,6 +881,7 @@ static void *php_main(void *arg) { perror("failed to block SIGPIPE"); exit(EXIT_FAILURE); } +#endif set_thread_name("php-main"); diff --git a/frankenphp.go b/frankenphp.go index 8196513d1b..083b614477 100644 --- a/frankenphp.go +++ b/frankenphp.go @@ -12,13 +12,21 @@ package frankenphp // // We also set these flags for hardening: https://github.com/docker-library/php/blob/master/8.2/bookworm/zts/Dockerfile#L57-L59 +// TODO: Add windows CFLAGS -Wall -Werror + // #cgo darwin pkg-config: libxml-2.0 -// #cgo CFLAGS: -Wall -Werror +// #cgo linux CFLAGS: -Wall -Werror +// #cgo darwin CFLAGS: -Wall -Werror +// #cgo openbsd CFLAGS: -Wall -Werror +// #cgo freebsd CFLAGS: -Wall -Werror // #cgo CFLAGS: -I/usr/local/include -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib // #cgo linux CFLAGS: -D_GNU_SOURCE -// #cgo darwin LDFLAGS: -L/opt/homebrew/opt/libiconv/lib -liconv -// #cgo linux LDFLAGS: -lresolv -// #cgo LDFLAGS: -L/usr/local/lib -L/usr/lib -lphp -ldl -lm -lutil +// #cgo windows CFLAGS: -D_WINDOWS -DWINDOWS=1 -DZEND_WIN32=1 -DPHP_WIN32=1 -DWIN32 -D_MBCS -D_USE_MATH_DEFINES -DNDebug -DNDEBUG -DZEND_DEBUG=0 -DZTS=1 -DFD_SETSIZE=256 +// #cgo windows CFLAGS: -IC:/msys64/usr/local/include -IC:/msys64/usr/local/include/php -IC:/msys64/usr/local/include/php/main -IC:/msys64/usr/local/include/php/TSRM -IC:/msys64/usr/local/include/php/Zend -IC:/msys64/usr/local/include/php/ext -IC:/msys64/usr/local/include/php/ext/date/lib -IC:/msys64/usr/local/include/php/main/win32 +// #cgo darwin LDFLAGS: -L/opt/homebrew/opt/libiconv/lib -L/usr/lib -liconv -lphp -ldl -lm -lutil +// #cgo linux LDFLAGS: -L/usr/lib -lresolv -lphp -ldl -lm -lutil +// #cgo windows LDFLAGS: -LC:/msys64/usr/local/lib -lphp8ts -lphp8embed -lbrotlicommon -lbrotlidec -lbrotlienc +// #cgo LDFLAGS: -L/usr/local/lib // #include // #include // #include From 51e6c3a4cd3b49570da3ddfecc4a83484f3d19a0 Mon Sep 17 00:00:00 2001 From: TenHian Date: Tue, 24 Dec 2024 19:30:31 +0800 Subject: [PATCH 2/4] Improved compilation documentation on windows --- docs/compile_win.md | 116 ++++++++++++++++++++++++++++++++++++++++++-- frankenphp.c | 2 - frankenphp.go | 5 +- make_dep.bat | 37 ++++++++++++++ patch.php | 54 +++++++++++++++++++++ 5 files changed, 204 insertions(+), 10 deletions(-) create mode 100644 make_dep.bat create mode 100644 patch.php diff --git a/docs/compile_win.md b/docs/compile_win.md index 150a3ce13a..441529cdaf 100644 --- a/docs/compile_win.md +++ b/docs/compile_win.md @@ -2,14 +2,122 @@ Frankenphp could only dynamic compiled on Windows system. It is still in dev. This steps to compile blew. +## Prepare MSYS2 and FrankenPHP source + +Click [msys2-x86_64-20240507.exe](https://github.com/msys2/msys2-installer/releases/download/2024-05-07/msys2-x86_64-20240507.exe) dowload and install it in `C:\`, then its `C:\msys64`. We use environment 'MSYS2 MINGW64'. + +### Install basic tools + +```bash +# mingw64/msys2 bash +pacman -S git +pacman -S vim +pacman -S make +pacman -S wget +``` + +### Install gcc + +```bash +# mingw64/msys2 bash +# TODO: Check out that why other gcc versions are not able to compile frankenphp +pacman -U https://repo.msys2.org/mingw/mingw64/mingw-w64-x86_64-gcc-13.2.0-6-any.pkg.tar.zst +``` + +### Setup go + +```bash +# mingw64/msys2 bash +# TODO: Better install this version +pacman -U https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-go-1.22.2-1-any.pkg.tar.zst + +# set go env +export GO111MODULE='on' +export GOBIN='/home/you-user-name/go/bin' +export GOCACHE='/home/you-user-name/.cache/go-build' +export GOENV='/home/you-user-name/.config/go/env' +export GOROOT="/mingw64/lib/go" +export GOPATH="/home/you-user-name/go" +mkdir ~/go/bin ~/go/pkg ~/go/src +``` + +### Install brotli +```bash +# mingw64/msys2 bash +pacman -S mingw-w64-x86_64-brotli +``` + +### Get Frankenphp source + +```bash +# mingw64/msys2 bash +cd ~/go/src +git clone https://github.com/dunglas/frankenphp.git +cd frankenphp +git checkout win +``` + + ## Compile PHP -FrankenPHP is compatible with PHP 8.2 and superior. +FrankenPHP is compatible with PHP 8.2 and superior. In dev stage, php-8.3.0 recommanded. ### Install PHP-SDK -TODO: +Recommend reference [build php on windows](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2). + +The first step, you should install visual studio. For php-8.3.0, its visual_studio_2019(vs16). Here are some older [visual studio](https://github.com/user-attachments/files/18225924/visual_studio.zip) releases. +After visual C++ installed(may need reboot), windows terminal will provide a 'Developer PowerShell for VS 2019'. If not have windows terminal, click [windows terminal](https://aka.ms/terminal). + +Then download [php-sdk-binary-tools](https://github.com/php/php-sdk-binary-tools/releases). Unzip it, remove and rename the folder under `C:\`, then its `C:\php-sdk`. + +### Patch, compile, and copy to target path + +Enter 'Developer PowerShell for VS 2019', then: +``` +cd C:\php-sdk +.\phpsdk-vs16-x64.bat +phpsdk_buildtree phpdev +# now in C:\php-sdk\phpdev\vs16\x64 +git clone -b php-8.3.0 https://github.com/php/php-src.git php-8.3.0 +cd php-8.3.0 +phpsdk_deps -u -b 8.3 +buildconf +# basic configure +configure --with-prefix="C:\php-sdk\phpdev\vs16\x64\php-8.3.0\php" --enable-zts --enable-embed --enable-cli --disable-opcache-jit +COPY C:\msys64\home\TenHian\go\src\frankenphp\patch.php .\ +COPY C:\msys64\home\TenHian\go\src\frankenphp\make_dep.bat .\ +# modify php-src and Makefile generated by configure +..\..\..\..\bin\php\php.exe patch.php +make +make devel +# modifiy a header file, mv includes and dll in target paths +make_dep.bat +``` + +## Compile Frankenphp + +Back to 'MSYS2 MINGW64'. + +```bash +cp /mingw64/lib/libbrotlicommon.a /mingw64/lib/libbrotlidec.a /mingw64/lib/libbrotlienc.a /usr/local/lib +# now you should in ~/go/src/frankenphp +cd caddy/frankenphp +# TODO: compile with watcher +go build -tags nowatcher +# for clean +# go clean && go clean -cache +# for build details +# go build -tags nowatcher -x +``` + +Now you get frankenphp.exe in `~/go/src/frankenphp/caddy/frankenphp` -### Modify php-src +## After compile -TODO: https://github.com/dunglas/frankenphp/issues/880#issuecomment-2242103617 +The frankenphp.exe needs some shared libraries in the same directory to run. Like `libcrypto-3-x64.dll` `libpq.dll` `libssh2.dll` `libssl-3-x64.dll` `libwinpthread-1.dll` `nghttp2.dll` `php_openssl.dll` `php8embed.dll` `php8ts.dll`. +`libwinpthread-1.dll` in `C:\msys64\mingw64\bin`. +`libcrypto-3-x64.dll` `libpq.dll` `libssh2.dll` `libssl-3-x64.dll` `nghttp2.dll` in `C:\php-sdk\phpdev\vs16\x64\deps\bin`. +`php_openssl.dll` `php8embed.dll` `php8ts.dll` in `C:\php-sdk\phpdev\vs16\x64\php-8.3.0\x64\Release_TS`. +You could use `ldd frankenphp.exe` `ldd php8ts.dll` in 'MSYS2 MINGW64', or `dumpbin /dependents frankenphp.exe` `dumpbin /dependents php8ts.dll` in php-sdk console to see libriaries that need by frankenphp.exe. +The .dll files start with 'php_' are php extensions, you can find them in `C:\php-sdk\phpdev\vs16\x64\php-8.3.0\x64\Release_TS`. In order to use the extensions, you need to move them to the same path as frankenphp and edit php.ini in this path. \ No newline at end of file diff --git a/frankenphp.c b/frankenphp.c index 27c4090224..07ff91bce3 100644 --- a/frankenphp.c +++ b/frankenphp.c @@ -28,8 +28,6 @@ #include #elif defined(__FreeBSD__) || defined(__OpenBSD__) #include -#elif defined(__MINGW64__) -#include #endif #include "_cgo_export.h" diff --git a/frankenphp.go b/frankenphp.go index 083b614477..2c7e1784ef 100644 --- a/frankenphp.go +++ b/frankenphp.go @@ -15,10 +15,7 @@ package frankenphp // TODO: Add windows CFLAGS -Wall -Werror // #cgo darwin pkg-config: libxml-2.0 -// #cgo linux CFLAGS: -Wall -Werror -// #cgo darwin CFLAGS: -Wall -Werror -// #cgo openbsd CFLAGS: -Wall -Werror -// #cgo freebsd CFLAGS: -Wall -Werror +// #cgo unix CFLAGS: -Wall -Werror // #cgo CFLAGS: -I/usr/local/include -I/usr/local/include/php -I/usr/local/include/php/main -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib // #cgo linux CFLAGS: -D_GNU_SOURCE // #cgo windows CFLAGS: -D_WINDOWS -DWINDOWS=1 -DZEND_WIN32=1 -DPHP_WIN32=1 -DWIN32 -D_MBCS -D_USE_MATH_DEFINES -DNDebug -DNDEBUG -DZEND_DEBUG=0 -DZTS=1 -DFD_SETSIZE=256 diff --git a/make_dep.bat b/make_dep.bat new file mode 100644 index 0000000000..db3b9a3cb1 --- /dev/null +++ b/make_dep.bat @@ -0,0 +1,37 @@ +@echo off + +REM process php.h +set "php_h_path=.\x64\Release_TS\php-8.3.0-devel-vs16-x64\include\main\php.h" +if exist "%php_h_path%" ( + echo Updating pid_t definition in %php_h_path%... + powershell -Command "(Get-Content '%php_h_path%' | ForEach-Object { $_ -replace '^typedef int pid_t;', 'typedef long long pid_t;' }) | Set-Content '%php_h_path%'" +) else ( + echo File %php_h_path% does not exist. +) + +REM copy include +set "src_include_dir=.\x64\Release_TS\php-8.3.0-devel-vs16-x64\include" +set "dest_include_dir=C:\msys64\usr\local\include\php" + +if not exist "%dest_include_dir%" ( + echo Creating directory %dest_include_dir%... + mkdir "%dest_include_dir%" +) + +echo Copying folders from %src_include_dir% to %dest_include_dir%... +xcopy "%src_include_dir%\*" "%dest_include_dir%\" /E /I /Y + +REM copy php8ts.dll php8embed.dll +set "src_php_dll_dir=.\x64\Release_TS" +set "dest_lib_dir=C:\msys64\usr\local\lib" + +if not exist "%dest_lib_dir%" ( + echo Creating directory %dest_lib_dir%... + mkdir "%dest_lib_dir%" +) + +echo Copying php8ts.dll and php8embed.dll to %dest_lib_dir%... +copy "%src_php_dll_dir%\php8ts.dll" "%dest_lib_dir%\" /Y +copy "%src_php_dll_dir%\php8embed.dll" "%dest_lib_dir%\" /Y + +echo Done! diff --git a/patch.php b/patch.php new file mode 100644 index 0000000000..29e89d9d6c --- /dev/null +++ b/patch.php @@ -0,0 +1,54 @@ + Date: Thu, 9 Jan 2025 13:07:00 +0800 Subject: [PATCH 3/4] [fix] Corrected one translation of script output. --- patch.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch.php b/patch.php index 29e89d9d6c..0c9b9f3db7 100644 --- a/patch.php +++ b/patch.php @@ -20,7 +20,7 @@ if ($content !== $new_content) { file_put_contents($file_path, $new_content); - echo "$file_path 中的 __forceinline 已替换为 inline\n"; + echo "\"__forceinline\" in $file_path has been replace by \"inline\"\n"; } } } From d059f870157d51252db8ca69c553a87d1856f844 Mon Sep 17 00:00:00 2001 From: TenHian Date: Wed, 15 Jan 2025 10:04:33 +0800 Subject: [PATCH 4/4] Completes the principle of porting to windows in docs and code comments. --- docs/compile_win.md | 9 ++++++++- patch.php | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/compile_win.md b/docs/compile_win.md index 441529cdaf..f59218aba6 100644 --- a/docs/compile_win.md +++ b/docs/compile_win.md @@ -120,4 +120,11 @@ The frankenphp.exe needs some shared libraries in the same directory to run. Lik `libcrypto-3-x64.dll` `libpq.dll` `libssh2.dll` `libssl-3-x64.dll` `nghttp2.dll` in `C:\php-sdk\phpdev\vs16\x64\deps\bin`. `php_openssl.dll` `php8embed.dll` `php8ts.dll` in `C:\php-sdk\phpdev\vs16\x64\php-8.3.0\x64\Release_TS`. You could use `ldd frankenphp.exe` `ldd php8ts.dll` in 'MSYS2 MINGW64', or `dumpbin /dependents frankenphp.exe` `dumpbin /dependents php8ts.dll` in php-sdk console to see libriaries that need by frankenphp.exe. -The .dll files start with 'php_' are php extensions, you can find them in `C:\php-sdk\phpdev\vs16\x64\php-8.3.0\x64\Release_TS`. In order to use the extensions, you need to move them to the same path as frankenphp and edit php.ini in this path. \ No newline at end of file +The .dll files start with 'php_' are php extensions, you can find them in `C:\php-sdk\phpdev\vs16\x64\php-8.3.0\x64\Release_TS`. In order to use the extensions, you need to move them to the same path as frankenphp and edit php.ini in this path. + +# Principle + +First, the windows cgo support MinGW-w64 compiler suite is more complete. In fact all GNU C compilers are relatively ok, but almost all cgo compilation is based on MinGW-w64. +Second, PHP offical only recommand compile with Visual C++(MSVC). + +So the core problem is to make Mingw-w64 compiler set could link with .dll that PHP on Windows. The `patch.php` does those work, see its comments for more details. \ No newline at end of file diff --git a/patch.php b/patch.php index 0c9b9f3db7..f7625facf8 100644 --- a/patch.php +++ b/patch.php @@ -1,4 +1,9 @@