Skip to content

Conversation

withinboredom
Copy link
Member

@withinboredom withinboredom commented Jul 19, 2025

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).

Signed-off-by: Robert Landers <[email protected]>
@henderkes
Copy link
Contributor

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

@withinboredom
Copy link
Member Author

withinboredom commented Jul 19, 2025

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.

@henderkes
Copy link
Contributor

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.

@withinboredom
Copy link
Member Author

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
Copy link
Member Author

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.

@henderkes
Copy link
Contributor

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.

@AlliBalliBaba
Copy link
Contributor

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

@withinboredom
Copy link
Member Author

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.

@henderkes
Copy link
Contributor

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?

@withinboredom
Copy link
Member Author

withinboredom commented Jul 30, 2025

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 🤦 )

@henderkes
Copy link
Contributor

--allow-multiple-definition

@henderkes
Copy link
Contributor

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

@withinboredom
Copy link
Member Author

@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.

@henderkes
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

henderkes commented Aug 2, 2025

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.

#elif defined(__FreeBSD__) || defined(__OpenBSD__)
#include <pthread_np.h>
#endif
#include <sapi/cli/cli.h>
Copy link
Contributor

@henderkes henderkes Aug 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#include <sapi/cli/cli.h>
#include <main/php_version.h>
#if PHP_VERSION_ID >= 80500
#include <sapi/cli/cli.h>
#endif

php_embed_shutdown();

return exit_status;
return (void *)(intptr_t)do_php_cli(cli_argc, cli_argv);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return (void *)(intptr_t)do_php_cli(cli_argc, cli_argv);
#if PHP_VERSION_ID >= 80500
return (void *)(intptr_t)do_php_cli(cli_argc, cli_argv);
#else
// old code, refactored out to a different file

@henderkes
Copy link
Contributor

henderkes commented Aug 3, 2025

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
Copy link
Contributor

#1782

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants