feat(compiler): 支持 PHP 嵌入模式并改进 Windows 编译配置

- 添加 php8embed.lib 支持作为嵌入模式首选库文件
- 更新 Windows 库文件查找顺序以支持嵌入模式
- 区分 C 和 C++ 文件的编译选项处理
- 将宏定义应用限制在编译阶段而非链接阶段
- 更新 Windows 链接器使用 link.exe 替代编译器
- 添加 .dll 和 .exe 文件到 .gitignore
- 修复 PHP ZTS 检测逻辑移除严格比较
- 移除示例中的环境变量输出以减少冗余信息
- 添加 C++ 异常处理支持和标准版本指定
pull/1/head
韩天峰 4 months ago
parent be77cfaab1
commit b1df315299
  1. 4
      .gitignore
  2. 2
      examples/hello.php
  3. 144
      src/Php/CompilerBase.php
  4. 28
      src/Php/Translator.php

4
.gitignore vendored

@ -12,4 +12,6 @@
/projects/laravel /projects/laravel
/projects/tmp /projects/tmp
/.php-cs-fixer.cache /.php-cs-fixer.cache
*.o *.o
*.dll
*.exe

@ -5,8 +5,6 @@ function main(): void
echo "Hello World!"; echo "Hello World!";
var_dump(PHP_VERSION); var_dump(PHP_VERSION);
var_dump(php_uname()); var_dump(php_uname());
var_dump($_ENV);
global $argv; global $argv;
var_dump($argv); var_dump($argv);
} }

@ -290,7 +290,7 @@ class CompilerBase extends \PhpAot\Core\Translator
$this->detectPlatform(); $this->detectPlatform();
// 检测 PHP 是否为线程安全版本(ZTS) // 检测 PHP 是否为线程安全版本(ZTS)
$this->isPhpZts = defined('PHP_ZTS') && PHP_ZTS === 1; $this->isPhpZts = defined('PHP_ZTS');
} }
protected function detectPlatform(): void protected function detectPlatform(): void
@ -2304,11 +2304,12 @@ class CompilerBase extends \PhpAot\Core\Translator
if ($this->buildMode === 'bin') { if ($this->buildMode === 'bin') {
// Windows 下 PHP 库文件和 DLL 的查找顺序: // Windows 下 PHP 库文件和 DLL 的查找顺序:
// 1. SDK/lib/php8.lib // 1. SDK/lib/php8embed.lib (嵌入模式首选)
// 2. SDK/lib/php8ts.lib // 2. SDK/lib/php8ts.lib
// 3. lib/php8.lib // 3. SDK/lib/php8.lib
// 4. lib/php8ts.lib // 4. lib/php8embed.lib
// 5. 根目录/php8.dll // 5. lib/php8ts.lib
// 6. lib/php8.lib
$phpDirs = [ $phpDirs = [
$this->getPhpDir() . '\\SDK\\lib', // 优先从 SDK/lib 查找 $this->getPhpDir() . '\\SDK\\lib', // 优先从 SDK/lib 查找
@ -2319,18 +2320,26 @@ class CompilerBase extends \PhpAot\Core\Translator
foreach ($phpDirs as $phpDir) { foreach ($phpDirs as $phpDir) {
if (!is_dir($phpDir)) continue; if (!is_dir($phpDir)) continue;
// 尝试 php8.lib // 尝试 php8embed.lib (嵌入模式)
$phpLib = $phpDir . '\\php8.lib'; $phpEmbedLib = $phpDir . '\\php8embed.lib';
if (file_exists($phpLib)) { if (file_exists($phpEmbedLib)) {
$list[] = '"' . $phpLib . '"'; $list[] = '"' . $phpEmbedLib . '"';
$found = true; $found = true;
break; break;
} }
// 尝试 php8ts.lib // 尝试 php8ts.lib
$altPhpLib = $phpDir . '\\php8ts.lib'; $phpTsLib = $phpDir . '\\php8ts.lib';
if (file_exists($altPhpLib)) { if (file_exists($phpTsLib)) {
$list[] = '"' . $altPhpLib . '"'; $list[] = '"' . $phpTsLib . '"';
$found = true;
break;
}
// 尝试 php8.lib
$phpLib = $phpDir . '\\php8.lib';
if (file_exists($phpLib)) {
$list[] = '"' . $phpLib . '"';
$found = true; $found = true;
break; break;
} }
@ -2340,19 +2349,29 @@ class CompilerBase extends \PhpAot\Core\Translator
if (!$found) { if (!$found) {
$phpDll = $this->getPhpDir() . '\\php8.dll'; $phpDll = $this->getPhpDir() . '\\php8.dll';
if (file_exists($phpDll)) { if (file_exists($phpDll)) {
$this->climate->magenta('php8.lib not found, using php8.dll directly'); $this->climate->magenta('php8embed.lib not found, using php8.dll directly');
$this->climate->info('Note: This may require additional setup'); $this->climate->info('Note: This may require additional setup');
$list[] = '"' . $phpDll . '"'; $list[] = '"' . $phpDll . '"';
} else { } else {
// 尝试 php8ts.dll // 尝试 php8ts.dll
$phpTsDll = $this->getPhpDir() . '\\php8ts.dll'; $phpTsDll = $this->getPhpDir() . '\\php8ts.dll';
if (file_exists($phpTsDll)) { if (file_exists($phpTsDll)) {
$this->climate->magenta('php8.lib not found, using php8ts.dll directly'); $this->climate->magenta('php8embed.lib not found, using php8ts.dll directly');
$this->climate->info('Note: This may require additional setup'); $this->climate->info('Note: This may require additional setup');
$list[] = '"' . $phpTsDll . '"'; $list[] = '"' . $phpTsDll . '"';
} }
} }
} }
// // 添加 Windows 系统库(PHP 嵌入模式必需)
// $list[] = 'ws2_32.lib'; // Winsock
// $list[] = 'advapi32.lib'; // 高级 API
// $list[] = 'user32.lib'; // 用户界面
// $list[] = 'shell32.lib'; // Shell API
// $list[] = 'ole32.lib'; // OLE
// $list[] = 'oleaut32.lib'; // OLE Automation
// $list[] = 'crypt32.lib'; // 加密 API
} }
$out = ''; $out = '';
@ -2381,52 +2400,60 @@ class CompilerBase extends \PhpAot\Core\Translator
$cmd .= ' ' . $this->parseWindowsIncludes(); $cmd .= ' ' . $this->parseWindowsIncludes();
} }
// Windows 平台必需的宏定义(参考 CMakeLists.txt) // Windows 平台必需的宏定义(参考 CMakeLists.txt)- 仅在编译时
$cmd .= ' /DZEND_WIN32'; // 标识 Windows 平台 if (!$link) {
$cmd .= ' /DPHP_WIN32'; // 标识 Windows 平台 $cmd .= ' /DZEND_WIN32'; // 标识 Windows 平台
$cmd .= ' /DZEND_DEBUG=0'; // 禁用调试模式 $cmd .= ' /DPHP_WIN32'; // 标识 Windows 平台
$cmd .= ' /DZEND_DEBUG=0'; // 禁用调试模式
// 根据 PHP 是否为线程安全版本决定是否添加 ZTS 宏
if ($this->isPhpZts) { // 根据 PHP 是否为线程安全版本决定是否添加 ZTS 宏
$cmd .= ' /DZTS'; // 启用线程安全 if ($this->isPhpZts) {
} $cmd .= ' /DZTS'; // 启用线程安全
}
$cmd .= ' /DZEND_ENABLE_STATIC_TSRMLS_CACHE'; // 启用静态 TSRM 缓存
// 优化级别
// 优化级别 switch ($this->optimizeLevel) {
switch ($this->optimizeLevel) { case 0:
case 0: $cmd .= ' /Od'; // 禁用优化
$cmd .= ' /Od'; // 禁用优化 break;
break; case 1:
case 1: case 2:
case 2: $cmd .= ' /O2'; // 最大速度优化
$cmd .= ' /O2'; // 最大速度优化 break;
break; case 3:
case 3: $cmd .= ' /Ox'; // 完全优化
$cmd .= ' /Ox'; // 完全优化 break;
break; }
}
// 调试信息 // 调试信息
if ($this->debugInfo) { if ($this->debugInfo) {
$cmd .= ' /Zi'; // 生成完整调试信息 $cmd .= ' /Zi'; // 生成完整调试信息
} }
// 警告级别 // 警告级别
$cmd .= ' /W3'; $cmd .= ' /W3';
// 禁用 PHP SDK 头文件中的常见警告 // 禁用 PHP SDK 头文件中的常见警告
$cmd .= ' /wd4244'; // 禁用类型转换警告(__int64 到 int) $cmd .= ' /wd4244'; // 禁用类型转换警告(__int64 到 int)
$cmd .= ' /wd4146'; // 禁用一元负运算符应用于无符号类型的警告 $cmd .= ' /wd4146'; // 禁用一元负运算符应用于无符号类型的警告
// 启用 C++ 异常处理(消除 C4530 警告)
$cmd .= ' /EHsc';
// C++ 标准
if (!str_contains($this->cxxflags, '/std:')) {
$cmd .= ' /std:c++17';
}
// 编译时的额外选项
if ($this->cxxflags) {
$cmd .= ' ' . $this->cxxflags;
}
}
// 禁用编译器版权信息输出 // 禁用编译器版权信息输出
$cmd .= ' /nologo'; $cmd .= ' /nologo';
// C++ 标准(仅在编译时)
if (!$link && !str_contains($this->cxxflags, '/std:')) {
$cmd .= ' /std:c++17';
}
// 扩展模块特定选项 // 扩展模块特定选项
if ($this->buildMode === 'ext') { if ($this->buildMode === 'ext') {
if ($link) { if ($link) {
@ -2444,14 +2471,11 @@ class CompilerBase extends \PhpAot\Core\Translator
$cmd .= ' ' . $this->ldflags; $cmd .= ' ' . $this->ldflags;
} }
} else { } else {
// 编译时的额外选项 $cmd .= ' /MD';
if ($this->cxxflags) {
$cmd .= ' ' . $this->cxxflags;
}
} }
// 定义宏 // 定义宏(仅在编译时)
if ($this->enableProfiler) { if (!$link && $this->enableProfiler) {
$cmd .= ' /DPPROF_ON=1'; $cmd .= ' /DPPROF_ON=1';
} }
} }

@ -405,11 +405,12 @@ class Translator extends Preprocessor
if ($this->buildMode === 'bin') { if ($this->buildMode === 'bin') {
$cliHeaders = [ $cliHeaders = [
'#include "ps_title.h"',
'#include "php_cli_process_title.h"', '#include "php_cli_process_title.h"',
'#include "php_cli_process_title_arginfo.h"', '#include "php_cli_process_title_arginfo.h"',
]; ];
$code .= 'extern "C" {' . PHP_EOL;
$code .= implode(PHP_EOL, $cliHeaders) . PHP_EOL; $code .= implode(PHP_EOL, $cliHeaders) . PHP_EOL;
$code .= '}';
} }
$code .= "// global vars \n"; $code .= "// global vars \n";
@ -663,12 +664,31 @@ CODE;
if ($this->isWindows()) { if ($this->isWindows()) {
// Windows MSVC 编译命令 // Windows MSVC 编译命令
$cmd = $this->cppCompiler . ' /c ' . $cppFile . ' /Fo' . $objectFile; $cmd = $this->cppCompiler . ' /c ' . $cppFile . ' /Fo' . $objectFile;
// C 文件和 C++ 文件使用不同的选项
$isCppFile = (pathinfo($cppFile, PATHINFO_EXTENSION) === 'cc' ||
pathinfo($cppFile, PATHINFO_EXTENSION) === 'cpp' ||
pathinfo($cppFile, PATHINFO_EXTENSION) === 'cxx');
// 添加编译选项(C 文件不需要 /EHsc 和 /std:c++17)
if ($isCppFile) {
$this->addCompilationOption($cmd, false);
} else {
// C 文件:只添加基本选项,不添加 C++ 特定选项
$cmd .= ' ' . $this->parseWindowsIncludes();
$cmd .= ' /DZEND_WIN32 /DPHP_WIN32 /DZEND_DEBUG=0';
if ($this->isPhpZts) {
$cmd .= ' /DZTS';
}
$cmd .= ' /DZEND_ENABLE_STATIC_TSRMLS_CACHE';
$cmd .= ' /Od /W3 /wd4244 /wd4146 /nologo';
}
} else { } else {
// Unix/Linux/macOS GCC 编译命令 // Unix/Linux/macOS GCC 编译命令
$cmd = $this->cppCompiler . ' -c ' . $cppFile . ' -o ' . $objectFile; $cmd = $this->cppCompiler . ' -c ' . $cppFile . ' -o ' . $objectFile;
$this->addCompilationOption($cmd, false);
} }
$this->addCompilationOption($cmd, false);
if (!$parallel) { if (!$parallel) {
$this->climate->comment($cmd); $this->climate->comment($cmd);
} }
@ -871,9 +891,9 @@ CODE;
// 根据平台构建链接命令 // 根据平台构建链接命令
if ($this->isWindows()) { if ($this->isWindows()) {
// Windows MSVC 链接命令 // Windows 使用 link.exe 进行链接
$objectList = implode(' ', $objectFiles); $objectList = implode(' ', $objectFiles);
$linkCmd = $this->cppCompiler . ' ' . $objectList . ' /Fe' . $targetFile; $linkCmd = 'link /nologo ' . $objectList . ' /OUT:' . $targetFile;
} else { } else {
// Unix/Linux/macOS GCC 链接命令 // Unix/Linux/macOS GCC 链接命令
$objectList = implode(' ', $objectFiles); $objectList = implode(' ', $objectFiles);

Loading…
Cancel
Save