fix(build): correct Windows mpdecimal DLL copying in CMake build

- Moved mpdecimal DLL copying to after phpx target creation on Windows
- Fixed timing issue where post-build commands were registered too early
- Updated GitHub repository URL in JNI tutorial documentation
- Added new Windows build workflow with proper PHP SDK setup
- Implemented vcpkg integration for GMP and MPFR libraries on Windows
- Added mpdecimal build step in Windows CI workflow
- Configured PHPX build with proper
master
韩天峰 1 day ago
parent 022ca55ff0
commit 063476360b
  1. 36
      .github/patches/phpx-windows-mpdecimal-target.patch
  2. 233
      .github/workflows/windows-build.yml
  3. 2
      examples/jni/TUTORIAL.md

@ -0,0 +1,36 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 897706d..b4d85ec 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -355,14 +355,6 @@ if (IS_WINDOWS)
INTERFACE_INCLUDE_DIRECTORIES "${PHP_SDK_DIR}/include;${MPDECIMAL_DIR}/libmpdec++"
)
- # 复制 DLL 到输出目录
- file(GLOB MPDEC_DLLS "${PHP_LIBRARY_DIR}/libmpdec-4.0.1.dll" "${PHP_LIBRARY_DIR}/libmpdec++-4.0.1.dll")
- foreach(_dll ${MPDEC_DLLS})
- add_custom_command(TARGET phpx POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_dll}" $<TARGET_FILE_DIR:phpx>
- COMMENT "Copying ${_dll} to output"
- )
- endforeach()
else()
# Linux/macOS: 内置编译 mpdecimal + libmpdec++
message(STATUS "Using bundled mpdecimal with uint128")
@@ -419,6 +411,16 @@ set_target_properties(phpx PROPERTIES
CLEAN_DIRECT_OUTPUT 1
)
+if (IS_WINDOWS)
+ # Register post-build commands only after the phpx target exists.
+ file(GLOB MPDEC_DLLS "${PHP_LIBRARY_DIR}/libmpdec-4.0.1.dll" "${PHP_LIBRARY_DIR}/libmpdec++-4.0.1.dll")
+ foreach(_dll ${MPDEC_DLLS})
+ add_custom_command(TARGET phpx POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_dll}" $<TARGET_FILE_DIR:phpx>
+ COMMENT "Copying ${_dll} to output")
+ endforeach()
+endif()
+
if (IS_WINDOWS)
target_link_libraries(phpx PRIVATE
${PHP_LIBRARY}

@ -0,0 +1,233 @@
name: Windows tpc build
on:
push:
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: windows-tpc-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
COMPOSER_NO_INTERACTION: 1
COMPOSER_PROCESS_TIMEOUT: 0
jobs:
build-tpc:
name: tpc.exe (PHP ${{ matrix.php }})
runs-on: windows-2022
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
php: ["8.4", "8.5"]
steps:
- name: Checkout TypePHP
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
tools: composer:v2
env:
fail-fast: true
phpts: nts
update: true
- name: Install matching PHP development SDK
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$phpVersion = php -r 'echo PHP_VERSION;'
$phpExe = (Get-Command php).Source
$phpHome = Split-Path -Parent $phpExe
$archiveName = "php-devel-pack-$phpVersion-nts-Win32-vs17-x64.zip"
$archive = Join-Path $env:RUNNER_TEMP $archiveName
$extractDir = Join-Path $env:RUNNER_TEMP "php-devel-$phpVersion"
$downloaded = $false
foreach ($baseUrl in @(
'https://downloads.php.net/~windows/releases',
'https://downloads.php.net/~windows/releases/archives'
)) {
try {
Invoke-WebRequest -Uri "$baseUrl/$archiveName" -OutFile $archive
$downloaded = $true
break
} catch {
Remove-Item $archive -Force -ErrorAction SilentlyContinue
}
}
if (-not $downloaded) {
throw "Unable to download the PHP $phpVersion NTS development pack"
}
Expand-Archive -Path $archive -DestinationPath $extractDir -Force
$sdkSource = Get-ChildItem $extractDir -Directory |
Where-Object { Test-Path (Join-Path $_.FullName 'include\main\php.h') } |
Select-Object -First 1
if ($null -eq $sdkSource) {
throw "The PHP development archive has an unexpected layout: $archiveName"
}
$sdk = Join-Path $phpHome 'SDK'
$sdkInclude = Join-Path $sdk 'include'
$sdkLib = Join-Path $sdk 'lib'
New-Item $sdkInclude, $sdkLib -ItemType Directory -Force | Out-Null
Copy-Item (Join-Path $sdkSource.FullName 'include\*') $sdkInclude -Recurse -Force
Copy-Item (Join-Path $sdkSource.FullName 'lib\*') $sdkLib -Force
$embedLibrary = Join-Path $phpHome 'php8embed.lib'
if (-not (Test-Path $embedLibrary)) {
throw "setup-php did not install php8embed.lib in $phpHome"
}
Copy-Item $embedLibrary $sdkLib -Force
# Temporary compatibility fix for PHP packages predating php/php-src#22940.
$hashHeader = Join-Path $sdkInclude 'ext\hash\php_hash.h'
$hashSource = [IO.File]::ReadAllText($hashHeader)
$invalidAllocation = 'char *base = ecalloc('
if ($hashSource.Contains($invalidAllocation)) {
$hashSource = $hashSource.Replace(
$invalidAllocation,
'char *base = (char *) ecalloc('
)
[IO.File]::WriteAllText(
$hashHeader,
$hashSource,
[Text.UTF8Encoding]::new($false)
)
}
foreach ($required in @(
(Join-Path $sdkInclude 'main\php.h'),
(Join-Path $sdkLib 'php8.lib'),
(Join-Path $sdkLib 'php8embed.lib'),
(Join-Path $phpHome 'php8.dll')
)) {
if (-not (Test-Path $required)) {
throw "Required PHP SDK file is missing: $required"
}
}
"PHP_HOME=$phpHome" | Out-File $env:GITHUB_ENV -Append -Encoding utf8
"PHPX_HOME=${{ github.workspace }}\vendor\swoole\phpx" |
Out-File $env:GITHUB_ENV -Append -Encoding utf8
Write-Host "Using PHP $phpVersion from $phpHome"
- name: Install Composer dependencies
run: composer install --prefer-dist --no-progress
- name: Patch PHPX Windows CMake target ordering
shell: pwsh
run: git apply --directory=vendor/swoole/phpx .github/patches/phpx-windows-mpdecimal-target.patch
- name: Configure MSVC
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: Install GMP and MPFR
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$triplet = 'x64-windows'
$vcpkg = Join-Path $env:VCPKG_INSTALLATION_ROOT 'vcpkg.exe'
& $vcpkg install "gmp:$triplet" "mpfr:$triplet"
if ($LASTEXITCODE -ne 0) {
throw "vcpkg failed with exit code $LASTEXITCODE"
}
$installed = Join-Path $env:VCPKG_INSTALLATION_ROOT "installed\$triplet"
$sdkInclude = Join-Path $env:PHP_HOME 'SDK\include'
$sdkLib = Join-Path $env:PHP_HOME 'SDK\lib'
Copy-Item (Join-Path $installed 'include\*') $sdkInclude -Recurse -Force
foreach ($library in @('gmp.lib', 'gmpxx.lib', 'mpfr.lib')) {
$source = Join-Path $installed "lib\$library"
if (-not (Test-Path $source)) {
throw "vcpkg did not install $library"
}
Copy-Item $source $sdkLib -Force
}
Copy-Item (Join-Path $installed 'bin\*.dll') $env:PHP_HOME -Force
- name: Build mpdecimal
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$buildScript = Join-Path $env:PHPX_HOME 'thirdparty\mpdecimal\vcbuild\vcbuild64.bat'
& cmd.exe /d /s /c "`"$buildScript`""
if ($LASTEXITCODE -ne 0) {
throw "mpdecimal build failed with exit code $LASTEXITCODE"
}
$dist = Join-Path $env:PHPX_HOME 'thirdparty\mpdecimal\vcbuild\dist64'
$sdkInclude = Join-Path $env:PHP_HOME 'SDK\include'
$sdkLib = Join-Path $env:PHP_HOME 'SDK\lib'
Copy-Item (Join-Path $dist '*.lib') $sdkLib -Force
Copy-Item (Join-Path $dist '*.dll') $sdkLib -Force
Copy-Item (Join-Path $dist '*.dll') $env:PHP_HOME -Force
Copy-Item (Join-Path $dist 'mpdecimal.h') $sdkInclude -Force
Copy-Item (Join-Path $dist 'decimal.hh') $sdkInclude -Force
- name: Build PHPX
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$phpxBuild = Join-Path $env:PHPX_HOME 'build'
$sdkLib = Join-Path $env:PHP_HOME 'SDK\lib'
cmake -S $env:PHPX_HOME -B $phpxBuild -G Ninja `
-D CMAKE_BUILD_TYPE=Release `
-D BUILD_TESTS=OFF `
-D BUILD_EXT=OFF `
-D GITHUB_ACTION=ON `
-D MPDECIMAL_LIBRARY="$sdkLib\libmpdec-4.0.1.dll.lib" `
-D MPDECIMALXX_LIBRARY="$sdkLib\libmpdec++-4.0.1.dll.lib"
if ($LASTEXITCODE -ne 0) {
throw "PHPX configuration failed with exit code $LASTEXITCODE"
}
cmake --build $phpxBuild --target phpx --parallel 2
if ($LASTEXITCODE -ne 0) {
throw "PHPX build failed with exit code $LASTEXITCODE"
}
foreach ($required in @(
(Join-Path $env:PHPX_HOME 'lib\phpx.lib'),
(Join-Path $phpxBuild 'phpx.dll')
)) {
if (-not (Test-Path $required)) {
throw "Required PHPX build output is missing: $required"
}
}
- name: Build tpc.exe
shell: pwsh
run: |
php bin\tpc.php project.yml --job 1 --no-progress
if ($LASTEXITCODE -ne 0) {
throw "TypePHP build failed with exit code $LASTEXITCODE"
}
if (-not (Test-Path 'tpc.exe')) {
throw 'The compiler did not produce tpc.exe'
}
- name: Upload tpc.exe
uses: actions/upload-artifact@v4
with:
name: tpc-windows-x64-php-${{ matrix.php }}
if-no-files-found: error
retention-days: 7
path: tpc.exe

@ -7,7 +7,7 @@
本文将介绍如何使用`Java`的`JNI`接口,实现在 `PHP` 代码中直接调用 `Java` 类库 —— 创建 `Java` 对象、调用方法、读写字段,就像在 `Java` 代码中操作一样自然。
1. 本实例程序的代码全部由 `DeepSeek-4-Pro` 生成,耗时约为`50分钟`
2. GitHub: <https://github.com/swoole/aot-compiler/tree/main/examples/jni>
2. GitHub: <https://github.com/swoole/typephp/tree/main/examples/jni>
## 准备工作

Loading…
Cancel
Save