frankenphp icon indicating copy to clipboard operation
frankenphp copied to clipboard

Can't use Frankenphp as a golang library

Open hookenz opened this issue 1 year ago • 6 comments

What happened?

I grabbed an example of using Franken as a go library

package main

import (
	"log"
	"net/http"

	"github.com/dunglas/frankenphp"
)

func main() {
	if err := frankenphp.Init(); err != nil {
		panic(err)
	}
	defer frankenphp.Shutdown()

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		req, err := frankenphp.NewRequestWithContext(r, frankenphp.WithRequestDocumentRoot("/var/www/html", false))
		if err != nil {
			panic(err)
		}

		if err := frankenphp.ServeHTTP(w, req); err != nil {
			panic(err)
		}
	})
	log.Fatal(http.ListenAndServe(":8080", nil))
> go mod init example
> go mod tidy
...

❯ go build .
# github.com/dunglas/frankenphp/internal/watcher
watcher.c:5:10: fatal error: wtr/watcher-c.h: No such file or directory
    5 | #include "wtr/watcher-c.h"
      |          ^~~~~~~~~~~~~~~~~
compilation terminated.

I thought perhaps watcher-c.h is in the php code? but I can't locate it. Where does that file come from?

Build Type

Custom (tell us more in the description)

Worker Mode

Yes

Operating System

GNU/Linux

CPU Architecture

x86_64

PHP configuration

See above

Relevant log output

As above

hookenz avatar Nov 14 '24 21:11 hookenz

Ok I seems I need to install watcher.

Why I went wrong here is because the documentation says Install "Optional" Dependencies.

Since the title says "Optional". I skipped it. But it's not optional unless you turn those features off in the configure step I think? That's unclear. I suggest you amend the documentation.

Unfortunately, watcher has really bad documentation on how to actually install it and make it available. According to the watcher docs, I followed the steps and watcher is still not found. And it's been way too many years that I have forgotten how the C compiler finds files. From memory, INCLUDE environment vars or something. But there simply are no examples to get this off the ground with golang. It's a horrible onboarding experience.

Looks like I can copy the watcher includes to: sudo cp -rp watcher-next/include/wtr /usr/local/include/

So this problem is resolved but now I get

❯ go build .
# github.com/dunglas/frankenphp
../go/pkg/mod/github.com/dunglas/[email protected]/cgi.go:3:11: fatal error: php_variables.h: No such file or directory
    3 | // #include <php_variables.h>
      |           ^~~~~~~~~~~~~~~~~
compilation terminated.

Next battle. That's a file in the php sources. Yeah, please provide more thorough examples from start to finish. Nothing quite works out of the gate.

hookenz avatar Nov 14 '24 21:11 hookenz

To build without the watcher you can do something like this in the meantime I think:

go build -tags nowatcher

AlliBalliBaba avatar Nov 14 '24 22:11 AlliBalliBaba

I got a little further.

❯ CGO_CFLAGS="-I/home/hookenz/franken/php-8.2.25/main -I/home/hookenz/franken/php-8.2.25/Zend -I/home/hookenz/franken/php-8.2.25 -I /home/hookenz/franken/php-8.2.25/TSRM" go build .
# frank
/snap/go/10743/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/gcc -m64 -o $WORK/b001/exe/a.out -Wl,--export-dynamic-symbol=_cgo_panic -Wl,--export-dynamic-symbol=_cgo_topofstack -Wl,--export-dynamic-symbol=crosscall2 -Wl,--export-dynamic-symbol=go_apache_request_headers -Wl,--export-dynamic-symbol=go_frankenphp_finish_request -Wl,--export-dynamic-symbol=go_frankenphp_release_known_variable_keys -Wl,--export-dynamic-symbol=go_frankenphp_worker_handle_request_start -Wl,--export-dynamic-symbol=go_getenv -Wl,--export-dynamic-symbol=go_getfullenv -Wl,--export-dynamic-symbol=go_handle_file_watcher_event -Wl,--export-dynamic-symbol=go_handle_request -Wl,--export-dynamic-symbol=go_log -Wl,--export-dynamic-symbol=go_putenv -Wl,--export-dynamic-symbol=go_read_cookies -Wl,--export-dynamic-symbol=go_read_post -Wl,--export-dynamic-symbol=go_register_variables -Wl,--export-dynamic-symbol=go_sapi_flush -Wl,--export-dynamic-symbol=go_sapi_getenv -Wl,--export-dynamic-symbol=go_shutdown -Wl,--export-dynamic-symbol=go_ub_write -Wl,--export-dynamic-symbol=go_write_headers -Wl,--compress-debug-sections=zlib /tmp/go-link-124271613/go.o /tmp/go-link-124271613/000000.o /tmp/go-link-124271613/000001.o /tmp/go-link-124271613/000002.o /tmp/go-link-124271613/000003.o /tmp/go-link-124271613/000004.o /tmp/go-link-124271613/000005.o /tmp/go-link-124271613/000006.o /tmp/go-link-124271613/000007.o /tmp/go-link-124271613/000008.o /tmp/go-link-124271613/000009.o /tmp/go-link-124271613/000010.o /tmp/go-link-124271613/000011.o /tmp/go-link-124271613/000012.o /tmp/go-link-124271613/000013.o /tmp/go-link-124271613/000014.o /tmp/go-link-124271613/000015.o /tmp/go-link-124271613/000016.o /tmp/go-link-124271613/000017.o /tmp/go-link-124271613/000018.o /tmp/go-link-124271613/000019.o /tmp/go-link-124271613/000020.o /tmp/go-link-124271613/000021.o /tmp/go-link-124271613/000022.o /tmp/go-link-124271613/000023.o /tmp/go-link-124271613/000024.o /tmp/go-link-124271613/000025.o /tmp/go-link-124271613/000026.o /tmp/go-link-124271613/000027.o /tmp/go-link-124271613/000028.o /tmp/go-link-124271613/000029.o /tmp/go-link-124271613/000030.o /tmp/go-link-124271613/000031.o -O2 -g -lresolv -L/usr/local/lib -L/usr/lib -lphp -ldl -lm -lutil -O2 -g -lresolv -O2 -g -lpthread -O2 -g -lwatcher-c -lstdc++ -O2 -g -no-pie
/usr/bin/ld: cannot find -lphp: No such file or directory
collect2: error: ld returned 1 exit status

hookenz avatar Nov 14 '24 22:11 hookenz

Ok, I've solved it. I need to "install" the PHP binary and all it's development files with.

So after the ./configure step.

sudo make install.

Then simply run go build .

I also needed to copy the watcher sudo cp -rp watcher-next/include/wtr /usr/local/include/

It would be awesome if the docs could be updated with more full and clear examples. But I think I got there in the end.

hookenz avatar Nov 14 '24 22:11 hookenz

Don't hesitate to send docs PR, improving this is on my (long) todo list, but any help is welcome.

dunglas avatar Nov 14 '24 22:11 dunglas

Ok, I've solved it. I need to "install" the PHP binary and all it's development files with.

Don't forget it needs to be a ZTS build @hookenz!

withinboredom avatar Nov 15 '24 21:11 withinboredom

You can also use the PHP as a lib with PHP embed SAPI (with ZTS enabled): it's the flag --enable embed while running ./configure and you will be able to compile the frankenphp lib without the need to have the full source code of PHP somewhere (static compilation doesn't work)

ptondereau avatar Jul 22 '25 19:07 ptondereau

Documentation about optional dependencies has been improved since, so this can be closed.

henderkes avatar Nov 10 '25 13:11 henderkes