Skip to content

Commit 728638d

Browse files
author
Kévin Dunglas
committed
feat: Windows support
1 parent e0f01d1 commit 728638d

28 files changed

+197
-93
lines changed

caddy/frankenphp/cbrotli.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//go:build !nobrotli
2+
3+
package main
4+
5+
import _ "github.com/dunglas/caddy-cbrotli"

caddy/frankenphp/main.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55

66
// plug in Caddy modules here.
77
_ "github.com/caddyserver/caddy/v2/modules/standard"
8-
_ "github.com/dunglas/caddy-cbrotli"
98
_ "github.com/dunglas/frankenphp/caddy"
109
_ "github.com/dunglas/mercure/caddy"
1110
_ "github.com/dunglas/vulcain/caddy"

caddy/php-cli.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//go:build !windows
2+
13
package caddy
24

35
import (

cgi.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ package frankenphp
88
// #cgo noescape frankenphp_register_variables_from_request_info
99
// #cgo noescape frankenphp_register_variable_safe
1010
// #cgo noescape frankenphp_register_single
11-
// #include <php_variables.h>
1211
// #include "frankenphp.h"
12+
// #include <php_variables.h>
1313
import "C"
1414
import (
1515
"context"

cgo.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package frankenphp
22

33
// #cgo darwin pkg-config: libxml-2.0
4-
// #cgo CFLAGS: -Wall -Werror
4+
// #cgo unix CFLAGS: -Wall -Werror
55
// #cgo linux CFLAGS: -D_GNU_SOURCE
6-
// #cgo LDFLAGS: -lphp -lm -lutil
6+
// #cgo unix LDFLAGS: -lphp -lm -lutil
77
// #cgo linux LDFLAGS: -ldl -lresolv
88
// #cgo darwin LDFLAGS: -Wl,-rpath,/usr/local/lib -liconv -ldl
9+
// #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
10+
// #cgo windows LDFLAGS: -lpthreadVC3
911
import "C"

cli.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//go:build !windows
2+
3+
// TODO: ignored on Windows for now (even if it should work with a custom PHP build),
4+
// because static builds of the embed SAPI aren't available yet and php.exe is ship with
5+
// the standard PHP distribution.
6+
7+
package frankenphp
8+
9+
// #include "frankenphp.h"
10+
import "C"
11+
import "unsafe"
12+
13+
// ExecuteScriptCLI executes the PHP script passed as parameter.
14+
// It returns the exit status code of the script.
15+
func ExecuteScriptCLI(script string, args []string) int {
16+
// Ensure extensions are registered before CLI execution
17+
registerExtensions()
18+
19+
cScript := C.CString(script)
20+
defer C.free(unsafe.Pointer(cScript))
21+
22+
argc, argv := convertArgs(args)
23+
defer freeArgs(argv)
24+
25+
return int(C.frankenphp_execute_script_cli(cScript, argc, (**C.char)(unsafe.Pointer(&argv[0])), false))
26+
}
27+
28+
func ExecutePHPCode(phpCode string) int {
29+
// Ensure extensions are registered before CLI execution
30+
registerExtensions()
31+
32+
cCode := C.CString(phpCode)
33+
defer C.free(unsafe.Pointer(cCode))
34+
return int(C.frankenphp_execute_script_cli(cCode, 0, nil, true))
35+
}

cli_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//go:build !windows
2+
3+
package frankenphp_test
4+
5+
import (
6+
"errors"
7+
"os"
8+
"os/exec"
9+
"testing"
10+
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func TestExecuteScriptCLI(t *testing.T) {
15+
if _, err := os.Stat("internal/testcli/testcli"); err != nil {
16+
t.Skip("internal/testcli/testcli has not been compiled, run `cd internal/testcli/ && go build`")
17+
}
18+
19+
cmd := exec.Command("internal/testcli/testcli", "testdata/command.php", "foo", "bar")
20+
stdoutStderr, err := cmd.CombinedOutput()
21+
assert.Error(t, err)
22+
23+
var exitError *exec.ExitError
24+
if errors.As(err, &exitError) {
25+
assert.Equal(t, 3, exitError.ExitCode())
26+
}
27+
28+
stdoutStderrStr := string(stdoutStderr)
29+
30+
assert.Contains(t, stdoutStderrStr, `"foo"`)
31+
assert.Contains(t, stdoutStderrStr, `"bar"`)
32+
assert.Contains(t, stdoutStderrStr, "From the CLI")
33+
}
34+
35+
func TestExecuteCLICode(t *testing.T) {
36+
if _, err := os.Stat("internal/testcli/testcli"); err != nil {
37+
t.Skip("internal/testcli/testcli has not been compiled, run `cd internal/testcli/ && go build`")
38+
}
39+
40+
cmd := exec.Command("internal/testcli/testcli", "-r", "echo 'Hello World';")
41+
stdoutStderr, err := cmd.CombinedOutput()
42+
assert.NoError(t, err)
43+
44+
stdoutStderrStr := string(stdoutStderr)
45+
assert.Equal(t, stdoutStderrStr, `Hello World`)
46+
}
47+
48+
func ExampleExecuteScriptCLI() {
49+
if len(os.Args) <= 1 {
50+
log.Println("Usage: my-program script.php")
51+
os.Exit(1)
52+
}
53+
54+
os.Exit(frankenphp.ExecuteScriptCLI(os.Args[1], os.Args))
55+
}

ext.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package frankenphp
22

3-
//#include "frankenphp.h"
3+
// #include "frankenphp.h"
44
import "C"
55
import (
66
"sync"

frankenphp.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1+
#include "frankenphp.h"
12
#include <SAPI.h>
23
#include <Zend/zend_alloc.h>
34
#include <Zend/zend_exceptions.h>
45
#include <Zend/zend_interfaces.h>
5-
#include <Zend/zend_types.h>
66
#include <errno.h>
77
#include <ext/spl/spl_exceptions.h>
88
#include <ext/standard/head.h>
99
#include <inttypes.h>
1010
#include <php.h>
11+
#ifdef PHP_WIN32
12+
#include <config.w32.h>
13+
#else
1114
#include <php_config.h>
15+
#endif
1216
#include <php_ini.h>
1317
#include <php_main.h>
1418
#include <php_output.h>
@@ -19,7 +23,9 @@
1923
#include <stdint.h>
2024
#include <stdio.h>
2125
#include <stdlib.h>
26+
#ifndef ZEND_WIN32
2227
#include <unistd.h>
28+
#endif
2329
#if defined(__linux__)
2430
#include <sys/prctl.h>
2531
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
@@ -205,7 +211,7 @@ bool frankenphp_shutdown_dummy_request(void) {
205211
return true;
206212
}
207213

208-
PHPAPI void get_full_env(zval *track_vars_array) {
214+
void get_full_env(zval *track_vars_array) {
209215
go_getfullenv(thread_index, track_vars_array);
210216
}
211217

@@ -959,6 +965,7 @@ static void *php_thread(void *arg) {
959965
}
960966

961967
static void *php_main(void *arg) {
968+
#ifndef ZEND_WIN32
962969
/*
963970
* SIGPIPE must be masked in non-Go threads:
964971
* https://pkg.go.dev/os/signal#hdr-Go_programs_that_use_cgo_or_SWIG
@@ -971,6 +978,7 @@ static void *php_main(void *arg) {
971978
perror("failed to block SIGPIPE");
972979
exit(EXIT_FAILURE);
973980
}
981+
#endif
974982

975983
set_thread_name("php-main");
976984

@@ -1188,6 +1196,7 @@ static void sapi_cli_register_variables(zval *track_vars_array) /* {{{ */
11881196
}
11891197
/* }}} */
11901198

1199+
#ifndef ZEND_WIN32
11911200
static void *execute_script_cli(void *arg) {
11921201
void *exit_status;
11931202
bool eval = (bool)arg;
@@ -1249,6 +1258,7 @@ int frankenphp_execute_script_cli(char *script, int argc, char **argv,
12491258

12501259
return (intptr_t)exit_status;
12511260
}
1261+
#endif
12521262

12531263
int frankenphp_reset_opcache(void) {
12541264
zend_function *opcache_reset =
@@ -1266,7 +1276,7 @@ static zend_module_entry *modules = NULL;
12661276
static int modules_len = 0;
12671277
static int (*original_php_register_internal_extensions_func)(void) = NULL;
12681278

1269-
PHPAPI int register_internal_extensions(void) {
1279+
int register_internal_extensions(void) {
12701280
if (original_php_register_internal_extensions_func != NULL &&
12711281
original_php_register_internal_extensions_func() != SUCCESS) {
12721282
return FAILURE;

frankenphp.go

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ package frankenphp
1414

1515
// #include <stdlib.h>
1616
// #include <stdint.h>
17+
// #include "frankenphp.h"
1718
// #include <php_variables.h>
1819
// #include <zend_llist.h>
1920
// #include <SAPI.h>
20-
// #include "frankenphp.h"
2121
import "C"
2222
import (
2323
"bytes"
@@ -753,30 +753,6 @@ func go_is_context_done(threadIndex C.uintptr_t) C.bool {
753753
return C.bool(phpThreads[threadIndex].frankenPHPContext().isDone)
754754
}
755755

756-
// ExecuteScriptCLI executes the PHP script passed as parameter.
757-
// It returns the exit status code of the script.
758-
func ExecuteScriptCLI(script string, args []string) int {
759-
// Ensure extensions are registered before CLI execution
760-
registerExtensions()
761-
762-
cScript := C.CString(script)
763-
defer C.free(unsafe.Pointer(cScript))
764-
765-
argc, argv := convertArgs(args)
766-
defer freeArgs(argv)
767-
768-
return int(C.frankenphp_execute_script_cli(cScript, argc, (**C.char)(unsafe.Pointer(&argv[0])), false))
769-
}
770-
771-
func ExecutePHPCode(phpCode string) int {
772-
// Ensure extensions are registered before CLI execution
773-
registerExtensions()
774-
775-
cCode := C.CString(phpCode)
776-
defer C.free(unsafe.Pointer(cCode))
777-
return int(C.frankenphp_execute_script_cli(cCode, 0, nil, true))
778-
}
779-
780756
func convertArgs(args []string) (C.int, []*C.char) {
781757
argc := C.int(len(args))
782758
argv := make([]*C.char, argc)

0 commit comments

Comments
 (0)