feat(build): add support for building shared libraries in addition to binaries and extensions

- Add BUILD_MODE_LIB constant to CompilerBase class
- Implement isBuildModeLib and isBuildModeEmbed methods for library detection
- Update Clang backend to handle lib build mode with -fPIC flag and DLL linking
- Modify GccLikeBackend to support lib build mode with shared library flags
- Update MSVC backend to handle lib build mode with DLL compilation
- Extend PlatformBase to return correct extensions for lib builds
- Add proper handling for misc directory files during preprocessing
- Create new example project demonstrating library build functionality
- Update Translator to include main.cc for embed modes and add PHPX_NO_MAIN define for libraries
- Expand mode mapping to accept multiple library-related build mode aliases
- Increment version number from 1082 to 1084
- Update documentation to reflect new lib build option alongside bin and ext modes
pull/16/head
韩天峰 2 months ago
parent d2b7a36430
commit 7e28e8441b
  1. 19
      examples/lib-demo/cpp-src/exports.cc
  2. 8
      examples/lib-demo/php-src/logic.php
  3. 7
      examples/lib-demo/project.yml
  4. 4
      src/Backend/Clang.php
  5. 4
      src/Backend/GccLikeBackend.php
  6. 2
      src/Backend/Msvc.php
  7. 13
      src/CompilerBase.php
  8. 2
      src/Constants.php
  9. 4
      src/Platform/PlatformBase.php
  10. 4
      src/Platform/Windows.php
  11. 11
      src/Preprocessor.php
  12. 20
      src/Translator.php
  13. 2
      version.txt

@ -0,0 +1,19 @@
#include <php_typephp_lib_demo_func_decl.h>
#ifdef _WIN32
#define TYPEPHP_API extern "C" __declspec(dllexport)
#else
#define TYPEPHP_API extern "C" __attribute__((visibility("default")))
#endif
extern "C" int php_aot_runtime_init(int argc, char **argv);
TYPEPHP_API int typephp_lib_demo_add(int a, int b)
{
char app_name[] = "typephp_lib_demo";
char *argv[] = {app_name, nullptr};
if (php_aot_runtime_init(1, argv) != 0) {
return 0;
}
return static_cast<int>(php_demo_add(a, b));
}

@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
function demo_add(int $a, int $b): int
{
return $a + $b;
}

@ -0,0 +1,7 @@
name: typephp_lib_demo
mode: lib
version: 0.1.0
cxx-std: c++17
sources:
- php-src
- cpp-src

@ -90,7 +90,7 @@ class Clang extends GccLikeBackend
if ($this->platform instanceof Windows) {
return '';
}
if ((!empty($config['build_mode']) && $config['build_mode'] === 'ext') || !empty($config['pic'])) {
if ((!empty($config['build_mode']) && ($config['build_mode'] === 'ext' || $config['build_mode'] === 'lib')) || !empty($config['pic'])) {
return ' -fPIC';
}
return '';
@ -108,7 +108,7 @@ class Clang extends GccLikeBackend
}
$flags .= ' ' . $this->platform->getCrtConfig();
if (!empty($config['build_mode']) && $config['build_mode'] === 'ext') {
if (!empty($config['build_mode']) && ($config['build_mode'] === 'ext' || $config['build_mode'] === 'lib')) {
$flags .= ' /DLL';
}
return $flags;

@ -53,7 +53,7 @@ abstract class GccLikeBackend extends CompilerBackend
/** 获取 PIC 标志 */
protected function getPICFlag(array $config): string
{
if ((!empty($config['build_mode']) && $config['build_mode'] === 'ext') || !empty($config['pic'])) {
if ((!empty($config['build_mode']) && ($config['build_mode'] === 'ext' || $config['build_mode'] === 'lib')) || !empty($config['pic'])) {
return ' -fPIC';
}
return '';
@ -121,7 +121,7 @@ abstract class GccLikeBackend extends CompilerBackend
{
$flags = '';
if ((!empty($config['build_mode']) && $config['build_mode'] === 'ext') || !empty($config['shared'])) {
if ((!empty($config['build_mode']) && ($config['build_mode'] === 'ext' || $config['build_mode'] === 'lib')) || !empty($config['shared'])) {
$flags .= ' ' . $this->platform->getSharedLinkFlag();
if ($this->platform instanceof \TypePhp\Platform\Macos && !empty($config['install_name'])) {

@ -393,7 +393,7 @@ class Msvc extends CompilerBackend
$cmd .= ' ' . $this->platform->getCrtConfig();
// 扩展模块选项
if (!empty($config['build_mode']) && $config['build_mode'] === 'ext') {
if (!empty($config['build_mode']) && ($config['build_mode'] === 'ext' || $config['build_mode'] === 'lib')) {
$cmd .= ' /DLL';
}

@ -177,6 +177,7 @@ class CompilerBase implements PropertyAccessContext
public const string OP_NOP = "if (0) {}\n";
public const string BUILD_MODE_BIN = 'bin';
public const string BUILD_MODE_EXT = 'ext';
public const string BUILD_MODE_LIB = 'lib';
public const string ENTRY_FUNCTION = 'main';
public const string PHPX_VENDOR_DIR = '/vendor/swoole/phpx';
protected const string PHASE_IDLE = 'idle';
@ -523,6 +524,16 @@ class CompilerBase implements PropertyAccessContext
return $this->buildMode === self::BUILD_MODE_EXT;
}
public function isBuildModeLib(): bool
{
return $this->buildMode === self::BUILD_MODE_LIB;
}
public function isBuildModeEmbed(): bool
{
return $this->isBuildModeBin() || $this->isBuildModeLib();
}
public function getPhpDir(): string
{
try {
@ -2860,7 +2871,7 @@ class CompilerBase implements PropertyAccessContext
// extension 和 bin 模式都需要链接 PHP 库
if ($platform instanceof Windows) {
// Windows: 根据构建模式选择不同的库
if ($this->isBuildModeBin()) {
if ($this->isBuildModeEmbed()) {
// bin 模式:需要同时链接 php8ts.lib 和 php8embed.lib
// 注意:php8ts.lib 必须在 php8embed.lib 之前,因为 embed 依赖 core
// php8ts.lib 提供 PHP 核心全局符号(executor_globals, compiler_globals, sapi_globals)

@ -165,7 +165,7 @@ class Constants
'mode' => [
'longPrefix' => 'mode',
'prefix' => 'm',
'description' => 'Build mode, -m bin(binary) or -m ext(extension), default: bin',
'description' => 'Build mode, -m bin(binary), -m lib(shared library), or -m ext(PHP extension), default: bin',
'required' => false,
'defaultValue' => CompilerBase::BUILD_MODE_BIN,
],

@ -83,7 +83,7 @@ abstract class PlatformBase
*/
public function getTargetExtension(string $buildMode): string
{
return $buildMode === 'ext'
return ($buildMode === 'ext' || $buildMode === 'lib')
? '.so'
: $this->getExecutableExtension();
}
@ -93,7 +93,7 @@ abstract class PlatformBase
*/
public function getBuildLibraryWarnings(string $phpDir, string $phpxDir, string $buildMode): array
{
if ($buildMode !== 'bin') {
if ($buildMode !== 'bin' && $buildMode !== 'lib') {
return [];
}

@ -105,7 +105,7 @@ class Windows extends PlatformBase
public function getTargetExtension(string $buildMode): string
{
return $buildMode === 'ext' ? '.dll' : '.exe';
return ($buildMode === 'ext' || $buildMode === 'lib') ? '.dll' : '.exe';
}
public function getDefaultCompiler(): string
@ -177,7 +177,7 @@ class Windows extends PlatformBase
public function getBuildLibraryWarnings(string $phpDir, string $phpxDir, string $buildMode): array
{
if ($buildMode !== 'bin') {
if ($buildMode !== 'bin' && $buildMode !== 'lib') {
return [];
}

@ -88,6 +88,17 @@ class Preprocessor extends CompilerBase
$ext = $this->getPlatform()->getObjectExtension();
// 保持与 cppFile 相同的路径分隔符
$normalizedFile = str_replace('\\', '/', $cppFile);
$normalizedMiscDir = str_replace('\\', '/', $this->getPhpxDir() . '/src/misc/');
if (str_starts_with($normalizedFile, $normalizedMiscDir)) {
$separator = $this->getPlatform()->getPathSeparator();
$objectDir = $this->buildDir . $separator . 'phpx-misc' . $separator . $this->targetName;
if (!is_dir($objectDir)) {
mkdir($objectDir, 0777, true);
}
return $objectDir . $separator . $info['filename'] . $ext;
}
return $info['dirname'] . $this->getPlatform()->getPathSeparator() . $info['filename'] . $ext;
}

@ -642,7 +642,7 @@ class Translator extends Preprocessor
// shell_exec 和 define 已通过 php::fn:: 直接调用,无需动态符号表
// 根据平台检查库文件(仅在构建二进制文件时需要)
if ($this->isBuildModeBin()) {
if ($this->isBuildModeEmbed()) {
foreach ($this->getPlatform()->getBuildLibraryWarnings($this->getPhpDir(), $this->getPhpxDir(), $this->buildMode) as $message) {
$this->climate->warning($message['warning']);
if (!empty($message['info'])) {
@ -1285,8 +1285,11 @@ CODE;
$job = $this->maxJob;
// embed 需要 main 函数,以及 cli 的内置函数定义
if ($this->isBuildModeBin()) {
if ($this->isBuildModeEmbed()) {
$sourceFiles[] = $this->getPhpxDir() . '/src/misc/main.cc';
}
if ($this->isBuildModeBin()) {
$sourceFiles[] = $this->getPhpxDir() . '/src/misc/php_cli_process_title.c';
$sourceFiles[] = $this->getPhpxDir() . '/src/misc/ps_title.c';
}
@ -1575,6 +1578,11 @@ CODE;
$includePaths = array_merge($includePaths, $this->userIncludePaths);
}
$userDefines = $this->userDefines;
if ($this->isBuildModeLib()) {
$userDefines[] = 'PHPX_NO_MAIN=1';
}
return [
'include_paths' => $includePaths,
'optimize' => $this->optimizeLevel,
@ -1586,7 +1594,7 @@ CODE;
'build_mode' => $this->buildMode,
'enable_profiler' => $this->enableProfiler,
'prof_output' => $this->targetName . '.prof',
'user_defines' => $this->userDefines,
'user_defines' => $userDefines,
'lto' => $this->enableLto,
];
}
@ -2240,6 +2248,12 @@ CODE;
$modeMap = [
'extension' => self::BUILD_MODE_EXT,
'ext' => self::BUILD_MODE_EXT,
'library' => self::BUILD_MODE_LIB,
'lib' => self::BUILD_MODE_LIB,
'shared' => self::BUILD_MODE_LIB,
'dll' => self::BUILD_MODE_LIB,
'dylib' => self::BUILD_MODE_LIB,
'so' => self::BUILD_MODE_LIB,
'binary' => self::BUILD_MODE_BIN,
'bin' => self::BUILD_MODE_BIN,
'cli' => self::BUILD_MODE_BIN,

@ -1 +1 @@
1082
1084
Loading…
Cancel
Save