Build the dev Docker image:
docker build -t frankenphp-dev -f dev.Dockerfile .
docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -p 8080:8080 -p 443:443 -p 443:443/udp -v $PWD:/go/src/app -it frankenphp-devThe image contains the usual development tools (Go, GDB, Valgrind, Neovim...) and uses the following php setting locations
- php.ini:
/etc/frankenphp/php.iniA php.ini file with development presets is provided by default. - additional configuration files:
/etc/frankenphp/php.d/*.ini - php extensions:
/usr/lib/frankenphp/modules/
If your docker version is lower than 23.0, the build will fail due to dockerignore pattern issue. Add directories to .dockerignore.
!testdata/*.php
!testdata/*.txt
+!caddy
+!internalFollow the instructions to compile from sources and pass the --debug configuration flag.
go test -tags watcher -race -v ./...Build Caddy with the FrankenPHP Caddy module:
cd caddy/frankenphp/
go build -tags watcher,brotli,nobadger,nomysql,nopgx
cd ../../Run the Caddy with the FrankenPHP Caddy module:
cd testdata/
../caddy/frankenphp/frankenphp runThe server is listening on 127.0.0.1:80:
Note
if you are using Docker, you will have to either bind container port 80 or execute from inside the container
curl -vk http://127.0.0.1/phpinfo.phpBuild the minimal test server:
cd internal/testserver/
go build
cd ../../Run the test server:
cd testdata/
../internal/testserver/testserverThe server is listening on 127.0.0.1:8080:
curl -v http://127.0.0.1:8080/phpinfo.phpPrint bake plan:
docker buildx bake -f docker-bake.hcl --printBuild FrankenPHP images for amd64 locally:
docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/amd64"Build FrankenPHP images for arm64 locally:
docker buildx bake -f docker-bake.hcl --pull --load --set "*.platform=linux/arm64"Build FrankenPHP images from scratch for arm64 & amd64 and push to Docker Hub:
docker buildx bake -f docker-bake.hcl --pull --no-cache --push-
Download the debug version of the FrankenPHP binary from GitHub or create your custom static build including debug symbols:
docker buildx bake \ --load \ --set static-builder.args.DEBUG_SYMBOLS=1 \ --set "static-builder.platform=linux/amd64" \ static-builder docker cp $(docker create --name static-builder-musl dunglas/frankenphp:static-builder-musl):/go/src/app/dist/frankenphp-linux-$(uname -m) frankenphp
-
Replace your current version of
frankenphpby the debug FrankenPHP executable -
Start FrankenPHP as usual (alternatively, you can directly start FrankenPHP with GDB:
gdb --args frankenphp run) -
Attach to the process with GDB:
gdb -p `pidof frankenphp` -
If necessary, type
continuein the GDB shell -
Make FrankenPHP crash
-
Type
btin the GDB shell -
Copy the output
-
Open
.github/workflows/tests.yml -
Enable PHP debug symbols
- uses: shivammathur/setup-php@v2 # ... env: phpts: ts + debug: true -
Enable
tmateto connect to the container- name: Set CGO flags run: echo "CGO_CFLAGS=$(php-config --includes)" >> "$GITHUB_ENV" + - run: | + sudo apt install gdb + mkdir -p /home/runner/.config/gdb/ + printf "set auto-load safe-path /\nhandle SIG34 nostop noprint pass" > /home/runner/.config/gdb/gdbinit + - uses: mxschmitt/action-tmate@v3 -
Connect to the container
-
Open
frankenphp.go -
Enable
cgosymbolizer- //_ "github.com/ianlancetaylor/cgosymbolizer" + _ "github.com/ianlancetaylor/cgosymbolizer"
-
Download the module:
go get -
In the container, you can use GDB and the like:
go test -tags watcher -c -ldflags=-w gdb --args frankenphp.test -test.run ^MyTest$
-
When the bug is fixed, revert all these changes
FrankenPHP cannot be compiled natively on Windows, so to build and debug code, you need to run your IDE in WSL.
-
Install WSL2:
wsl --install
Follow the instructions in compiling from sources. The steps assume the following environment:
- Go installed at
/usr/local/go - PHP source cloned to
~/php-src - PHP built at:
/usr/local/bin/php - FrankenPHP source cloned to
~/frankenphp
-
Install CLion (on your host OS)
-
Download from JetBrains
-
Launch (if on Windows, in WSL):
clion &>/dev/null
-
-
Open Project in CLion
- Open CLion → Open → Select the
~/frankenphpdirectory - Add a build chain: Settings → Build, Execution, Deployment → Custom Build Targets
- Select any Build Target, under
Buildset up an External Tool (call it e.g. go build) - Set up a wrapper script that builds frankenphp for you, called
go_compile_frankenphp.sh
export CGO_CFLAGS="-O0 -g $(php-config --includes)" export CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)" go build -tags=nobadger,nomysql,nopgx
- Under Program, select
go_compile_frankenphp.sh - Leave Arguments blank
- Working Directory:
~/frankenphp/caddy/frankenphp
- Open CLion → Open → Select the
-
Configure Run Targets
- Go to Run → Edit Configurations
- Create:
- frankenphp:
- Type: Native Application
- Target: select the
go buildtarget you created - Executable:
~/frankenphp/caddy/frankenphp/frankenphp - Arguments: the arguments you want to start frankenphp with, e.g.
php-cli test.php
- frankenphp:
-
Debug Go files from CLion
- Right click on a *.go file in the Project view on the left
- Override file type → C/C++
Now you can place breakpoints in C, C++ and Go files. To get syntax highlighting for imports from php-src, you may need to tell CLion about the include paths. Create a
compile_flags.txtfile in~/frankenphpwith the following contents:-I/usr/local/include/php -I/usr/local/include/php/Zend -I/usr/local/include/php/main -I/usr/local/include/php/TSRM
Use GoLand for primary Go development, but the debugger cannot debug C code.
-
Install GoLand (on your host OS)
-
Download from JetBrains
-
Launch (if on Windows, in WSL):
goland &>/dev/null
-
-
Open in GoLand
- Launch GoLand → Open → Select the
~/frankenphpdirectory
- Launch GoLand → Open → Select the
- Select Go Build
- Name
frankenphp - Run kind: Directory
- Name
- Directory:
~/frankenphp/caddy/frankenphp - Output directory:
~/frankenphp/caddy/frankenphp - Working directory:
~/frankenphp/caddy/frankenphp - Environment (adjust for your $(php-config ...) output):
CGO_CFLAGS=-O0 -g -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_LDFLAGS=-lm -lpthread -lsqlite3 -lxml2 -lbrotlienc -lbrotlidec -lbrotlicommon -lwatcher - Go tool arguments:
-tags=nobadger,nomysql,nopgx - Program arguments: e.g.
php-cli -i
You can now place breakpoints and debug through Go code when you debug the frankenphp configuration, but breakpoints
in C code will not work.
- Use CLion for debugging PHP internals and
cgoglue code - Use GoLand for primary Go development and debugging
- FrankenPHP can be added as a run configuration in CLion for unified C/Go debugging if needed, but syntax highlighting won't work in Go files
- PHP embedding in uWSGI
- PHP embedding in NGINX Unit
- PHP embedding in Go (go-php)
- PHP embedding in Go (GoEmPHP)
- PHP embedding in C++
- Extending and Embedding PHP by Sara Golemon
- What the heck is TSRMLS_CC, anyway?
- SDL bindings
apk add strace util-linux gdb
strace -e 'trace=!futex,epoll_ctl,epoll_pwait,tgkill,rt_sigreturn' -p 1To translate the documentation and the site in a new language, follow these steps:
- Create a new directory named with the language's 2-character ISO code in this repository's
docs/directory - Copy all the
.mdfiles in the root of thedocs/directory into the new directory (always use the English version as source for translation, as it's always up to date) - Copy the
README.mdandCONTRIBUTING.mdfiles from the root directory to the new directory - Translate the content of the files, but don't change the filenames, also don't translate strings starting with
> [!(it's special markup for GitHub) - Create a Pull Request with the translations
- In the site repository, copy and translate the translation files in the
content/,data/andi18n/directories - Translate the values in the created YAML file
- Open a Pull Request on the site repository