Skip to content

feat: Add glibc-based static binary build support#1438

Merged
dunglas merged 23 commits intophp:mainfrom
crazywhalecc:feat/gnu-static-binary
Mar 22, 2025
Merged

feat: Add glibc-based static binary build support#1438
dunglas merged 23 commits intophp:mainfrom
crazywhalecc:feat/gnu-static-binary

Conversation

@crazywhalecc
Copy link
Copy Markdown
Contributor

@crazywhalecc crazywhalecc commented Mar 11, 2025

I have merged the upstream parts into the main branch and made some adjustments to build-static.sh. But I don't know much about the Docker distribution of FrankenPHP, maybe the Dockerfile needs some additional modifications.

This binary is base on gnu libc dynamically linked and other things are all built statically, this allows us to use it on almost all glibc distributions, while also enabling some features that pure static compilation does not have, such as dl(), etc.

Currently I only tested locally both on arm and x86 platform with docker build -t gnu-static -f gnu-static.Dockerfile --build-arg FRANKENPHP_VERSION=1.0 .

@crazywhalecc crazywhalecc changed the title feat: Add gnu static binary build support feat: Add glibc-based static binary build support Mar 11, 2025
Comment thread gnu-static.Dockerfile
@henderkes
Copy link
Copy Markdown
Contributor

henderkes commented Mar 19, 2025

@crazywhalecc would you mind giving me push access to this PR repo?

@crazywhalecc
Copy link
Copy Markdown
Contributor Author

crazywhalecc commented Mar 20, 2025

@crazywhalecc would you mind giving me push access to this PR repo?

Added maintain access.

@henderkes
Copy link
Copy Markdown
Contributor

@crazywhalecc would you mind giving me push access to this PR repo?

Added maintain access.

PS C:\Users\m\source\repos\gnu-frankenphp> git push
remote: Permission to crazywhalecc/frankenphp.git denied to DubbleClick.
fatal: unable to access 'https://github.com/crazywhalecc/frankenphp/': The requested URL returned error: 403

@crazywhalecc
Copy link
Copy Markdown
Contributor Author

@crazywhalecc would you mind giving me push access to this PR repo?

Added maintain access.

PS C:\Users\m\source\repos\gnu-frankenphp> git push remote: Permission to crazywhalecc/frankenphp.git denied to DubbleClick. fatal: unable to access 'https://github.com/crazywhalecc/frankenphp/': The requested URL returned error: 403

Ouch. I added you in static-php/gnu-frankenphp , forgot my account's repo, sorry, added.

@henderkes henderkes force-pushed the feat/gnu-static-binary branch from 5bbef33 to 215acc0 Compare March 20, 2025 02:04
@henderkes
Copy link
Copy Markdown
Contributor

I personally prefer spaces on git over tabs, but most of the file was using tabs, so I changed our added spaces to tabs instead.

@henderkes henderkes force-pushed the feat/gnu-static-binary branch 3 times, most recently from e104766 to 7dff3d8 Compare March 20, 2025 04:03
@henderkes
Copy link
Copy Markdown
Contributor

looks good now other than the CHECKOV check for the Dockerfile. @crazywhalecc can you fix that?

@dunglas
Copy link
Copy Markdown
Member

dunglas commented Mar 20, 2025

Could you also add a GitHub Actions workflow to automatically publish the binary as we do for musl?

@henderkes
Copy link
Copy Markdown
Contributor

henderkes commented Mar 20, 2025

Yes, I'm still finishing up a few things related to this.

When I use the docker build to create frankenphp, my VM slows down to a crawl until I restart it. This doesn't happen when I manually compile frankenphp with the static-php-cli/bin/build-frankenphp script...

image
then:
image

@henderkes
Copy link
Copy Markdown
Contributor

henderkes commented Mar 20, 2025

I'm a bit stumped. Just recompiled with bin/build-frankenphp, which does essentially the same thing, and it's working just fine.

Edit: Just to save for myself to easily paste after, my history keeps messing up when I restart the VM due to hangs...

docker build -t gnu-static -f gnu-static.Dockerfile --build-arg FRANKENPHP_VERSION=1.0 .
docker cp $(docker create --name static-builder gnu-static):/go/src/app/dist/frankenphp-linux-$(uname -m) frankenphp ; docker rm static-builder

@henderkes
Copy link
Copy Markdown
Contributor

seems related to FFI. I will have to investigate that further, because FFI works just fine when I compile spc and frankenphp from my host RHEL 9.5 machine.

@henderkes
Copy link
Copy Markdown
Contributor

I'm a bit concerned that the linux arm runner has been running for 5 hours, it seems to be insanely slow for some reason.

Resulting executable is ~220mb, ~80mb after UPX. The bulk of the size comes from -Wl,--export-dynamic, but it's the only way I managed to keep the symbols required to load extensions in the executable.

Nearly the same dockerfile also works with gcc14 on a almalinux 9 container, which would enable some nice optimisation improvements. I will later benchmark the two.

Comment thread .github/workflows/static.yaml Outdated
matrix:
platform: ${{ fromJson(needs.prepare.outputs.platforms) }}
name: Build ${{ matrix.platform }} GNU static binary
runs-on: ubuntu-24.04
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
runs-on: ubuntu-24.04
runs-on: ${{ startsWith(matrix.platform, 'linux/arm') && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }}

This will run the ARM builds on ARM runners and speed up the builds.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ah, that explains it. thanks.

Comment thread gnu-static.Dockerfile
@henderkes henderkes force-pushed the feat/gnu-static-binary branch from 8aae759 to 437323f Compare March 21, 2025 10:31
@henderkes
Copy link
Copy Markdown
Contributor

Nearly the same dockerfile also works with gcc14 on a almalinux 9 container, which would enable some nice optimisation improvements. I will later benchmark the two.

Haha, gcc 14 isn't too happy with php source code. I patched a few sections and got it to build, doing performance testing against the gcc 10 (with -O3 -march native too) now.

@henderkes
Copy link
Copy Markdown
Contributor

Green CI! Will still rename the job description.

Should we rename the uploaded binaries from frankenphp-linux-arch to frankenphp-linux-arch-musl as well? It's your call considering backwards compatibility in the naming scheme, in case people rely on the name in their automatic deployments.

New ones are called frankenphp-linux-arch-gnu.

@dunglas
Copy link
Copy Markdown
Member

dunglas commented Mar 21, 2025

For GCC 14, we should wait for proper upstream support then, isn't it?

@henderkes
Copy link
Copy Markdown
Contributor

Yeah that's why I haven't committed anything for it. It would also require a more modern glibc version so it wouldn't make sense to distribute frankenphp with it.

@henderkes
Copy link
Copy Markdown
Contributor

henderkes commented Mar 21, 2025

Well, I can't make out any performance improvements by gcc 14 over gcc 10 on my old Ryzen 3700X. I'm guessing there may be some when running on a modern cpu, but I can't confirm that until tomorrow night. Can't benchmark our production servers while they're in use :P.

Weirdly enough, I actually get slightly better response times out of -Os than -O3 for php's compilation. Edit: Nevermind, not reproducable, was just volatile cpu load I guess.

Haven't tested different options for FrankenPHP itself because I would guess that you've benchmarked that. If anything we could try to use LTO but I suspect it wouldn't cause a major change.

@henderkes
Copy link
Copy Markdown
Contributor

henderkes commented Mar 21, 2025

Well I just spent the better part of two hours benchmarking various compilation settings and performance (and file size) are all very similar, to the point where I can't make any definitive statements. I think this is probably fine to be merged the way it is now.

The main benefit lies in being able to load extensions. Glibc + mimalloc being up to a few percent faster than musl/mimalloc in specific scenarios is nice to have, but not a game changer the same way that worker mode is in general.

Comment thread docker-bake.hcl Outdated
@dunglas dunglas merged commit 3bc4264 into php:main Mar 22, 2025
9 checks passed
@dunglas
Copy link
Copy Markdown
Member

dunglas commented Mar 22, 2025

Thank you very much for this @DubbleClick and @crazywhalecc. That's a huge step forward for the project.

@henderkes
Copy link
Copy Markdown
Contributor

You're welcome, I've already solved our dependency on dynamic plugins and am fine with continuing to use musl/mimalloc, but I'm sure it will help some people out.

Next up will be a small convenience PR for mimalloc.

With dynamic extension loading being possible, are there any that you'd like to offer out of the box or will this be up to package maintainers?

@dunglas
Copy link
Copy Markdown
Member

dunglas commented Mar 22, 2025

For convenience I think we should continue to package extensions statically as much as possible

@henderkes
Copy link
Copy Markdown
Contributor

For convenience I think we should continue to package extensions statically as much as possible

I'm talking about extensions that cannot be compiled statically, such as xdebug, new relic (well, if they supported ZTS builds), or blackfire.

@dunglas
Copy link
Copy Markdown
Member

dunglas commented Mar 22, 2025

Got it. Maybe xdebug then. The other ones are proprietary.

@henderkes henderkes deleted the feat/gnu-static-binary branch March 23, 2025 04:28
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