Signed-off-by: Kévin Dunglas <kevin@dunglas.fr> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
8.8 KiB
Contributing
Compiling PHP
With Docker (Linux)
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-dev
The 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
+!internal
Without Docker (Linux and macOS)
Follow the instructions to compile from sources and pass the --debug configuration flag.
Running the Test Suite
export CGO_CFLAGS=-O0 -g $(php-config --includes) CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)"
go test -race -v ./...
Caddy Module
Build Caddy with the FrankenPHP Caddy module:
cd caddy/frankenphp/
go build -tags nobadger,nomysql,nopgx
cd ../../
Run the Caddy with the FrankenPHP Caddy module:
cd testdata/
../caddy/frankenphp/frankenphp run
The 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.php
Minimal Test Server
Build the minimal test server:
cd internal/testserver/
go build
cd ../../
Run the test server:
cd testdata/
../internal/testserver/testserver
The server is listening on 127.0.0.1:8080:
curl -v http://127.0.0.1:8080/phpinfo.php
Windows Development
-
Configure Git to always use
lfline endingsgit config --global core.autocrlf false git config --global core.eol lf -
Install Visual Studio, Git, and Go:
winget install -e --id Microsoft.VisualStudio.2022.Community --override "--passive --wait --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --includeRecommended" winget install -e --id GoLang.Go winget install -e --id Git.Git -
Install vcpkg:
cd C:\ git clone https://github.com/microsoft/vcpkg .\vcpkg\bootstrap-vcpkg.bat -
Download the latest version of the watcher library for Windows and extract it to a directory named
C:\watcher -
Download the latest Thread Safe version of PHP and of the PHP SDK for Windows, extract them in directories named
C:\phpandC:\php-devel -
Clone the FrankenPHP Git repository:
git clone https://github.com/php/frankenphp C:\frankenphp cd C:\frankenphp -
Install the dependencies:
C:\vcpkg\vcpkg.exe install -
Configure the needed environment variables (PowerShell):
$env:PATH += ';C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\bin' $env:CC = 'clang' $env:CXX = 'clang++' $env:CGO_CFLAGS = "-O0 -g -IC:\frankenphp\vcpkg_installed\x64-windows\include -IC:\watcher -IC:\php-devel\include -IC:\php-devel\include\main -IC:\php-devel\include\TSRM -IC:\php-devel\include\Zend -IC:\php-devel\include\ext" $env:CGO_LDFLAGS = '-LC:\frankenphp\vcpkg_installed\x64-windows\lib -lbrotlienc -LC:\watcher -llibwatcher-c -LC:\php -LC:\php-devel\lib -lphp8ts -lphp8embed' -
Run the tests:
go test -race -ldflags '-extldflags="-fuse-ld=lld"' ./... cd caddy go test -race -ldflags '-extldflags="-fuse-ld=lld"' -tags nobadger,nomysql,nopgx ./... cd .. -
Build the binary:
cd caddy/frankenphp go build -ldflags '-extldflags="-fuse-ld=lld"' -tags nobadger,nomysql,nopgx cd ../..
Building Docker Images Locally
Print Bake plan:
docker buildx bake -f docker-bake.hcl --print
Build 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
Debugging Segmentation Faults With Static Builds
-
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
frankenphpwith 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
Debugging Segmentation Faults in GitHub Actions
-
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=-O0 -g $(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 -c -ldflags=-w gdb --args frankenphp.test -test.run ^MyTest$ -
When the bug is fixed, revert all these changes
Misc Dev Resources
- 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
Docker-Related Resources
Useful Command
apk add strace util-linux gdb
strace -e 'trace=!futex,epoll_ctl,epoll_pwait,tgkill,rt_sigreturn' -p 1
Translating the Documentation
To translate the documentation and the site into 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