feat: Add glibc-based static binary build support#1438
Conversation
|
@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 |
Ouch. I added you in static-php/gnu-frankenphp , forgot my account's repo, sorry, added. |
5bbef33 to
215acc0
Compare
|
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. |
e104766 to
7dff3d8
Compare
|
looks good now other than the CHECKOV check for the Dockerfile. @crazywhalecc can you fix that? |
|
Could you also add a GitHub Actions workflow to automatically publish the binary as we do for musl? |
|
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 |
|
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. |
|
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. |
| matrix: | ||
| platform: ${{ fromJson(needs.prepare.outputs.platforms) }} | ||
| name: Build ${{ matrix.platform }} GNU static binary | ||
| runs-on: ubuntu-24.04 |
There was a problem hiding this comment.
| 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.
There was a problem hiding this comment.
ah, that explains it. thanks.
…ilder-gnu run arm64 gnu job on ubuntu-arm
8aae759 to
437323f
Compare
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. |
|
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. |
|
For GCC 14, we should wait for proper upstream support then, isn't it? |
|
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. |
|
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. |
|
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. |
|
Thank you very much for this @DubbleClick and @crazywhalecc. That's a huge step forward for the project. |
|
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? |
|
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. |
|
Got it. Maybe xdebug then. The other ones are proprietary. |


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 .