From eb2f551e256474ba7d6808acd58fa6adb7e370b7 Mon Sep 17 00:00:00 2001 From: yangweijie <917647288@qq.com> Date: Fri, 25 Sep 2026 16:44:19 +0800 Subject: [PATCH] Fix Windows --nano build: include entry declaration header in extension TU On Windows, --nano runs in nano-policy mode (nanoMode=false, nanoPolicyMode=true) using the WINDOWS_DLL backend. RINIT then emits a direct C++ call to php_main() instead of relying on ZendVM eval, but the extension translation unit never included the entry function's declaration header, so the php_main() prototype was missing and MSVC failed with C3861. genExtensionIncludeHeaderFiles() only added declaration headers for stub files and attribute-factory owners, never the entry's source file. Include the entry function's declaration header when nano-policy mode is active so php_main() is visible where RINIT references it. Verified: a minimal --nano program now compiles, links and runs on Windows (previously failed at extension-.cc with 'php_main': identifier not found). --- src/Translator.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Translator.php b/src/Translator.php index 097d407d..e060d909 100644 --- a/src/Translator.php +++ b/src/Translator.php @@ -3535,6 +3535,20 @@ private function genExtensionIncludeHeaderFiles(): string $declarationHeaders[] = $header; } } + // Nano policy mode (Windows, the WINDOWS_DLL backend) emits a direct + // php_main() call inside RINIT instead of relying on ZendVM eval, so + // the entry function's declaration header — which carries the + // php_main() prototype — must be visible to this translation unit. + // True Nano mode keeps php_main() encapsulated inside the separate + // nano-entry translation unit, so only the policy path needs this. + if ($this->isNanoPolicyMode() && $this->hasFunction(self::ENTRY_FUNCTION)) { + $entryHeader = $this->declarationHeaderFiles[ + $this->getFunction(self::ENTRY_FUNCTION)->sourceFile + ] ?? null; + if ($entryHeader !== null && !in_array($entryHeader, $declarationHeaders, true)) { + $declarationHeaders[] = $entryHeader; + } + } } return $this->renderIncludeHeaderFiles([