Skip to content

Add --enable-embed=static support on Windows#22166

Open
luthermonson wants to merge 1 commit into
php:PHP-8.5from
luthermonson:fix/embed-static-windows
Open

Add --enable-embed=static support on Windows#22166
luthermonson wants to merge 1 commit into
php:PHP-8.5from
luthermonson:fix/embed-static-windows

Conversation

@luthermonson

Copy link
Copy Markdown
Contributor

Summary

Unix already supports --enable-embed=static (see sapi/embed/config.m4); the Windows config.w32 ignored the static value and php_embed.c got compiled as a DLL consumer regardless. Result: linking embed without php<N>.dll fails with LNK2019 on every PHP/Zend symbol referenced from php_embed.c, and (under ZTS) LNK4006 on _tsrm_ls_cache due to a duplicate definition between zend.c and php_embed.c.

When --enable-embed=static is passed on Windows:

  • CFLAGS_EMBED gets /D PHP_EXPORTS /D LIBZEND_EXPORTS /D SAPI_EXPORTS /D TSRM_EXPORTS so php_embed.c references core symbols directly instead of through __declspec(dllimport) thunks.
  • php_embed.c's ZEND_TSRMLS_CACHE_DEFINE() is skipped (gated on new PHP_EMBED_STATIC); zend.c provides the canonical definition.

This patches only the source-side adjustments. Producing a fat static lib (composition of php<N>embed.lib) is a separate Makefile concern handled by downstream build tools.

@henderkes

Copy link
Copy Markdown
Contributor

This patches only the source-side adjustments. Producing a fat static lib (composition of phpembed.lib) is a separate Makefile concern handled by downstream build tools.

Seems very much like a concern for here too, in the same breath. There's no reason to support downstream build adjustments in source code here, especially because it's impossible to test them. The entire --enable-embed=static logic isn't so crazy that it wouldn't be possible to upstream it all directly.

@luthermonson

Copy link
Copy Markdown
Contributor Author

I'm sorry, I didn't 100% understand your feedback, are you asking for changes?

@henderkes

henderkes commented May 28, 2026

Copy link
Copy Markdown
Contributor

Yes. There shouldn't be a --enable-embed=static knob that only affects the dllimports, rather than also properly building the php8embed.lib. How is this supposed to be tested without that ability?

@luthermonson

Copy link
Copy Markdown
Contributor Author

Very good feedback, I'll try and get it changed. Thank you

PHP's Unix build already documents and accepts --enable-embed=static
(see sapi/embed/config.m4) for building php<N>embed as a static
library with no DLL at runtime. The Windows config.w32 ignored the
static value, leaving php<N>embed.lib as a thin wrapper that still
depended on php<N>.dll at runtime.

When --enable-embed=static is passed on Windows:

* win32/build/confutils.js generates a Makefile rule for php<N>embed
  .lib that links in PHP core (PHP_GLOBAL_OBJS), statically built
  extensions (STATIC_EXT_OBJS + STATIC_EXT_LIBS), the embed SAPI
  objects, and ASM_OBJS in place of the import lib (BUILD_DIR/PHPLIB).
  The resulting php<N>embed.lib is a self-contained static library
  with no runtime DLL dependency.

* sapi/embed/config.w32 adds /D PHP_EXPORTS /D LIBZEND_EXPORTS
  /D SAPI_EXPORTS /D TSRM_EXPORTS to CFLAGS_EMBED so php_embed.c
  references PHP/Zend/SAPI/TSRM symbols directly instead of through
  __declspec(dllimport) thunks (which would produce LNK2019 with no
  DLL to import from), and defines PHP_EMBED_STATIC as a gate.

* sapi/embed/php_embed.c skips its ZEND_TSRMLS_CACHE_DEFINE() when
  PHP_EMBED_STATIC is set. In static mode zend.c is in the same link
  unit and already defines _tsrm_ls_cache; the duplicate from
  php_embed.c produced LNK4006 and a corrupt binary.
@luthermonson luthermonson force-pushed the fix/embed-static-windows branch from f1c729c to 9eb3202 Compare May 28, 2026 06:59
@iluuu1994 iluuu1994 requested a review from shivammathur June 1, 2026 09:05

@shivammathur shivammathur left a comment

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.

@luthermonson

Thanks for working on this. I think this needs a bit more work before it can land.

  • sapi/embed/config.w32 should handle/document yes, no, shared, and static similarly to config.m4, including the ARG_ENABLE help text.
  • We should expose a public static-embed marker, something like PHP_EMBED_STATIC, through the installed embed headers so external embed consumers do not get PHP/Zend/SAPI/TSRM APIs expanded as dllimport.
  • This likely also needs some confutils.js changes to preserve the generated-file dependency and include the needed static link inputs, plus mkdist.php/packaging changes so php<N>embed.lib is shipped as a devel library under lib.

Could you also test this end-to-end by building with --enable-embed=static and linking a minimal external embed program against the installed headers/libs, and checking that the resulting binary does not depend on php<N>.dll.

luthermonson added a commit to luthermonson/php-src that referenced this pull request Jun 6, 2026
Addresses shivammathur's review on PR php#22166:

* sapi/embed/config.w32: document ARG_ENABLE TYPE values
  (shared|static) to match config.m4's help string. Annotate the
  static branch with a pointer to the confutils.js Makefile rule.

* sapi/embed/php_embed.h: expose a public PHP_EMBED_STATIC marker.
  External consumers linking against a statically built
  php<N>embed.lib define PHP_EMBED_STATIC before including this
  header, which suppresses __declspec(dllimport) decoration on
  PHP/Zend/SAPI/TSRM APIs so they resolve directly against the
  static lib (matches what php-src uses internally when compiling
  its own TUs).

* win32/build/mkdist.php: route .lib SAPI targets (e.g. the static
  php<N>embed.lib) to dist_dir/dev/ instead of dist_dir/, keeping
  the runtime tree free of devel libraries.

* NEWS: extend the embed-static entry to mention the public marker
  and the dist /dev/ routing.
@luthermonson

Copy link
Copy Markdown
Contributor Author

I have this building fine in a fork but still haven't confirmed everything end to end due to other issues in my build pipeline, I am still working on this and have not forgotten.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants