frankenphp icon indicating copy to clipboard operation
frankenphp copied to clipboard

simply use the built-in php-cli

Open withinboredom opened this issue 5 months ago • 18 comments

This uses a new exported function in php 8.5 (I have no idea how to get this to work for <=8.4 while simultaneously working for >=8.5; suggestions welcome) for accessing the php-cli.

This requires a specific branch to be merged into php-src to work (TODO: update with link to PR).

withinboredom avatar Jul 19 '25 14:07 withinboredom

Time to drop php <= 8.4 support. ( ͡° ͜ʖ ͡°)

henderkes avatar Jul 19 '25 15:07 henderkes

I was hoping to finally escape php ./configure, Makefile, cmake and buildconf hell today, but I did not succeed. I made more progress, so that is something. 🤞 maybe tomorrow...

edit to add: I wonder if we need a full auto-build pipeline... we can just do the manual steps I've been doing to test. 🤔 like one of those 'supported-but-not-well-documented' type features.

withinboredom avatar Jul 19 '25 19:07 withinboredom

I was hoping to finally escape php ./configure, Makefile, cmake and buildconf hell today

Join us at static-php-cli and you can enjoy it daily ;) When you link the PR, I'll see if I can pull it in in our 8.5 branch.

henderkes avatar Jul 19 '25 19:07 henderkes

Oh good. Because I have several unknowns:

  1. Does it work in Windows.
  2. Does it work on osx.
  3. Does it work with a static build.

In theory, those are all "yes". I can test (2) now, but the other ones: I cannot.

withinboredom avatar Jul 19 '25 19:07 withinboredom

Join us at static-php-cli and you can enjoy it daily ;)

I would love to steal an hour of your time and learn from you, if you have it to spare. I keep running into weird dead ends.

withinboredom avatar Jul 19 '25 19:07 withinboredom

Sure, hit me with the questions. I haven't technically worked on php source yet (will likely be inevitable soon, because I still want to make the Cachelib extension), but we patch so many weird build shenanigans across toolchains that I might be able to answer your questions.

henderkes avatar Jul 19 '25 19:07 henderkes

I think for BC compatibiltiy you can just do something like

#if (PHP_VERSION_ID >= 84XXX)
#include <sapi/cli/cli.h>
#endif

...

#if (PHP_VERSION_ID >= 84XXX)
  new_php_cli();
#else
  old_php_cli();
#endif

AlliBalliBaba avatar Jul 24 '25 20:07 AlliBalliBaba

I’m not sure this is actually possible. I’ve taken two different approaches to varying degrees of success.

Core problems:

  • CLI has PHP functions that are only available in the CLI SAPI (see: cli_get_process_title).
  • PHP builtin functions are declared statically.

goal: build the CLI as a library that can be imported.

This approach works. However, I’m unable to work out the build process for both windows and Linux and get it to build automatically. Thus, using it will require doing a custom build for frankenphp. You have to use it in place of libphp, but then you get those CLI SAPI functions available in requests... which isn’t ideal — this appears to be exacerbated by the fact that go doesn’t seem to support dynamic loading of .so files, so there isn’t a way to say "on this code path, use this .so file, otherwise, use this other .so file."

I think the best solution is to simply wrap php-cli and then call it. It isn’t ideal, but this solution is even less ideal.

withinboredom avatar Jul 30 '25 15:07 withinboredom

While this would still require a manual, patched build: build CLI as a static library, link against it without having any strong references on its functions except for do_php_cli?

henderkes avatar Jul 30 '25 15:07 henderkes

I tried that as well, but then you get symbol conflicts with libphp. (that was the second approach that I just now realized I forgot to write about in the comment above 🤦 )

withinboredom avatar Jul 30 '25 15:07 withinboredom

--allow-multiple-definition

henderkes avatar Jul 30 '25 16:07 henderkes

Maybe you can push a version of php code and I'll see what I can do with it.

henderkes avatar Jul 30 '25 16:07 henderkes

@henderkes here's my changes -- I should add that I've also tried just building libphp by just including the new C files ... but that doesn't work either.

I build a .a file by simply building php-cli and then running ar rcs libsapi_cli.a sapi/cli/*.o which works well enough.

It appears that --allow-multiple-definition ordering of symbols is "undefined" so I'm a bit reluctant to use it -- that being said, this is entering the dark arts of linking, which I'm largely unfamiliar with.

withinboredom avatar Aug 01 '25 16:08 withinboredom

It appears that --allow-multiple-definition ordering of symbols is "undefined" so I'm a bit reluctant to use it

It's well defined as in that it uses the first definition found. Not a great idea to rely on that being the right one, but the definitions should be the same in this case, so it's fine. At least for ld.bfd, for ld.ld64 it might not be, because it doesn't support allow-multiple-definition.

So we will need to refactor building in a way where symbols don't land in multiple static libraries, but for testing and as a PoC, using --allow-multiple-definition is fine.

henderkes avatar Aug 01 '25 17:08 henderkes

libsapi_cli.a links directly against _tsrm_ls_cache, which is a non-exported symbol in libphp.so. I'll test with static lib first.

henderkes avatar Aug 02 '25 14:08 henderkes

Got it to link, but ./frankenphp php-cli -i gets stuck in an infinite loop in do_cli, ./frankenphp php-cli --ri bcmath does not find the file "bcmath" and then segfaults on exit.

Either way, assuming those problems are fixed, I don't see any conflicts. CLI SAPI doesn't build any symbols that are duplicates of libphp.a. I can compile just fine without --allow-multiple-definition.

[m@M-TH frankenphp]$ comm -12 \
  <(nm -C /home/m/php-src/libsapi_cli.a | awk '{print $3}' | sort -u) \
  <(nm -C /home/m/static-php-cli/buildroot/lib/libphp.a | awk '{print $3}' | sort -u)

additional_functions
arginfo_dl
HARDCODED_INI
ini_entries
.LC0
.LC1
.LC10
.LC17
.LC18
.LC27
.LC3
.LC33
.LC34
.LC35
.LC36
.LC47
.LC76
.LC78
.LC8
module_name_cmp
[m@M-TH frankenphp]$ comm -12   <(nm -Cg --defined-only /home/m/php-src/libsapi_cli.a | awk '$2 ~ /^[TDB]$/ {print $3}' | sort)   <(nm -Cg --defined-only /home/m/static-php-cli/buildroot/lib/libphp.a | awk '$2 ~ /^[TDB]$/ {print $3}' | sort)     
[m@M-TH frankenphp]$

Edit: I got debugging of php-src working in wsl. I'll have to see about debugging frankenphp next.

henderkes avatar Aug 02 '25 14:08 henderkes

argv passed by ./frankenphp php-cli: [0] => "-i" argv passed by ./php: [0] => "/usr/local/bin/php", [1] => "-i"

I'll add the path to frankenphp to cli_argv.

Edit: that works and prints out the php -i text, but then segfaults after. I'll leave that part up to you x)

henderkes avatar Aug 03 '25 07:08 henderkes

#1782

henderkes avatar Aug 03 '25 10:08 henderkes