Skip to content

Commit 0634763

Browse files
committed
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
1 parent 022ca55 commit 0634763

3 files changed

Lines changed: 270 additions & 1 deletion

File tree

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
diff --git a/CMakeLists.txt b/CMakeLists.txt
2+
index 897706d..b4d85ec 100644
3+
--- a/CMakeLists.txt
4+
+++ b/CMakeLists.txt
5+
@@ -355,14 +355,6 @@ if (IS_WINDOWS)
6+
INTERFACE_INCLUDE_DIRECTORIES "${PHP_SDK_DIR}/include;${MPDECIMAL_DIR}/libmpdec++"
7+
)
8+
9+
- # 复制 DLL 到输出目录
10+
- file(GLOB MPDEC_DLLS "${PHP_LIBRARY_DIR}/libmpdec-4.0.1.dll" "${PHP_LIBRARY_DIR}/libmpdec++-4.0.1.dll")
11+
- foreach(_dll ${MPDEC_DLLS})
12+
- add_custom_command(TARGET phpx POST_BUILD
13+
- COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_dll}" $<TARGET_FILE_DIR:phpx>
14+
- COMMENT "Copying ${_dll} to output"
15+
- )
16+
- endforeach()
17+
else()
18+
# Linux/macOS: 内置编译 mpdecimal + libmpdec++
19+
message(STATUS "Using bundled mpdecimal with uint128")
20+
@@ -419,6 +411,16 @@ set_target_properties(phpx PROPERTIES
21+
CLEAN_DIRECT_OUTPUT 1
22+
)
23+
24+
+if (IS_WINDOWS)
25+
+ # Register post-build commands only after the phpx target exists.
26+
+ file(GLOB MPDEC_DLLS "${PHP_LIBRARY_DIR}/libmpdec-4.0.1.dll" "${PHP_LIBRARY_DIR}/libmpdec++-4.0.1.dll")
27+
+ foreach(_dll ${MPDEC_DLLS})
28+
+ add_custom_command(TARGET phpx POST_BUILD
29+
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_dll}" $<TARGET_FILE_DIR:phpx>
30+
+ COMMENT "Copying ${_dll} to output")
31+
+ endforeach()
32+
+endif()
33+
+
34+
if (IS_WINDOWS)
35+
target_link_libraries(phpx PRIVATE
36+
${PHP_LIBRARY}
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
name: Windows tpc build
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
11+
concurrency:
12+
group: windows-tpc-${{ github.workflow }}-${{ github.ref }}
13+
cancel-in-progress: true
14+
15+
env:
16+
COMPOSER_NO_INTERACTION: 1
17+
COMPOSER_PROCESS_TIMEOUT: 0
18+
19+
jobs:
20+
build-tpc:
21+
name: tpc.exe (PHP ${{ matrix.php }})
22+
runs-on: windows-2022
23+
timeout-minutes: 90
24+
strategy:
25+
fail-fast: false
26+
matrix:
27+
php: ["8.4", "8.5"]
28+
29+
steps:
30+
- name: Checkout TypePHP
31+
uses: actions/checkout@v4
32+
33+
- name: Setup PHP
34+
uses: shivammathur/setup-php@v2
35+
with:
36+
php-version: ${{ matrix.php }}
37+
coverage: none
38+
tools: composer:v2
39+
env:
40+
fail-fast: true
41+
phpts: nts
42+
update: true
43+
44+
- name: Install matching PHP development SDK
45+
shell: pwsh
46+
run: |
47+
$ErrorActionPreference = 'Stop'
48+
49+
$phpVersion = php -r 'echo PHP_VERSION;'
50+
$phpExe = (Get-Command php).Source
51+
$phpHome = Split-Path -Parent $phpExe
52+
$archiveName = "php-devel-pack-$phpVersion-nts-Win32-vs17-x64.zip"
53+
$archive = Join-Path $env:RUNNER_TEMP $archiveName
54+
$extractDir = Join-Path $env:RUNNER_TEMP "php-devel-$phpVersion"
55+
$downloaded = $false
56+
57+
foreach ($baseUrl in @(
58+
'https://downloads.php.net/~windows/releases',
59+
'https://downloads.php.net/~windows/releases/archives'
60+
)) {
61+
try {
62+
Invoke-WebRequest -Uri "$baseUrl/$archiveName" -OutFile $archive
63+
$downloaded = $true
64+
break
65+
} catch {
66+
Remove-Item $archive -Force -ErrorAction SilentlyContinue
67+
}
68+
}
69+
if (-not $downloaded) {
70+
throw "Unable to download the PHP $phpVersion NTS development pack"
71+
}
72+
73+
Expand-Archive -Path $archive -DestinationPath $extractDir -Force
74+
$sdkSource = Get-ChildItem $extractDir -Directory |
75+
Where-Object { Test-Path (Join-Path $_.FullName 'include\main\php.h') } |
76+
Select-Object -First 1
77+
if ($null -eq $sdkSource) {
78+
throw "The PHP development archive has an unexpected layout: $archiveName"
79+
}
80+
81+
$sdk = Join-Path $phpHome 'SDK'
82+
$sdkInclude = Join-Path $sdk 'include'
83+
$sdkLib = Join-Path $sdk 'lib'
84+
New-Item $sdkInclude, $sdkLib -ItemType Directory -Force | Out-Null
85+
Copy-Item (Join-Path $sdkSource.FullName 'include\*') $sdkInclude -Recurse -Force
86+
Copy-Item (Join-Path $sdkSource.FullName 'lib\*') $sdkLib -Force
87+
88+
$embedLibrary = Join-Path $phpHome 'php8embed.lib'
89+
if (-not (Test-Path $embedLibrary)) {
90+
throw "setup-php did not install php8embed.lib in $phpHome"
91+
}
92+
Copy-Item $embedLibrary $sdkLib -Force
93+
94+
# Temporary compatibility fix for PHP packages predating php/php-src#22940.
95+
$hashHeader = Join-Path $sdkInclude 'ext\hash\php_hash.h'
96+
$hashSource = [IO.File]::ReadAllText($hashHeader)
97+
$invalidAllocation = 'char *base = ecalloc('
98+
if ($hashSource.Contains($invalidAllocation)) {
99+
$hashSource = $hashSource.Replace(
100+
$invalidAllocation,
101+
'char *base = (char *) ecalloc('
102+
)
103+
[IO.File]::WriteAllText(
104+
$hashHeader,
105+
$hashSource,
106+
[Text.UTF8Encoding]::new($false)
107+
)
108+
}
109+
110+
foreach ($required in @(
111+
(Join-Path $sdkInclude 'main\php.h'),
112+
(Join-Path $sdkLib 'php8.lib'),
113+
(Join-Path $sdkLib 'php8embed.lib'),
114+
(Join-Path $phpHome 'php8.dll')
115+
)) {
116+
if (-not (Test-Path $required)) {
117+
throw "Required PHP SDK file is missing: $required"
118+
}
119+
}
120+
121+
"PHP_HOME=$phpHome" | Out-File $env:GITHUB_ENV -Append -Encoding utf8
122+
"PHPX_HOME=${{ github.workspace }}\vendor\swoole\phpx" |
123+
Out-File $env:GITHUB_ENV -Append -Encoding utf8
124+
Write-Host "Using PHP $phpVersion from $phpHome"
125+
126+
- name: Install Composer dependencies
127+
run: composer install --prefer-dist --no-progress
128+
129+
- name: Patch PHPX Windows CMake target ordering
130+
shell: pwsh
131+
run: git apply --directory=vendor/swoole/phpx .github/patches/phpx-windows-mpdecimal-target.patch
132+
133+
- name: Configure MSVC
134+
uses: ilammy/msvc-dev-cmd@v1
135+
with:
136+
arch: x64
137+
138+
- name: Install GMP and MPFR
139+
shell: pwsh
140+
run: |
141+
$ErrorActionPreference = 'Stop'
142+
143+
$triplet = 'x64-windows'
144+
$vcpkg = Join-Path $env:VCPKG_INSTALLATION_ROOT 'vcpkg.exe'
145+
& $vcpkg install "gmp:$triplet" "mpfr:$triplet"
146+
if ($LASTEXITCODE -ne 0) {
147+
throw "vcpkg failed with exit code $LASTEXITCODE"
148+
}
149+
150+
$installed = Join-Path $env:VCPKG_INSTALLATION_ROOT "installed\$triplet"
151+
$sdkInclude = Join-Path $env:PHP_HOME 'SDK\include'
152+
$sdkLib = Join-Path $env:PHP_HOME 'SDK\lib'
153+
Copy-Item (Join-Path $installed 'include\*') $sdkInclude -Recurse -Force
154+
155+
foreach ($library in @('gmp.lib', 'gmpxx.lib', 'mpfr.lib')) {
156+
$source = Join-Path $installed "lib\$library"
157+
if (-not (Test-Path $source)) {
158+
throw "vcpkg did not install $library"
159+
}
160+
Copy-Item $source $sdkLib -Force
161+
}
162+
Copy-Item (Join-Path $installed 'bin\*.dll') $env:PHP_HOME -Force
163+
164+
- name: Build mpdecimal
165+
shell: pwsh
166+
run: |
167+
$ErrorActionPreference = 'Stop'
168+
169+
$buildScript = Join-Path $env:PHPX_HOME 'thirdparty\mpdecimal\vcbuild\vcbuild64.bat'
170+
& cmd.exe /d /s /c "`"$buildScript`""
171+
if ($LASTEXITCODE -ne 0) {
172+
throw "mpdecimal build failed with exit code $LASTEXITCODE"
173+
}
174+
175+
$dist = Join-Path $env:PHPX_HOME 'thirdparty\mpdecimal\vcbuild\dist64'
176+
$sdkInclude = Join-Path $env:PHP_HOME 'SDK\include'
177+
$sdkLib = Join-Path $env:PHP_HOME 'SDK\lib'
178+
Copy-Item (Join-Path $dist '*.lib') $sdkLib -Force
179+
Copy-Item (Join-Path $dist '*.dll') $sdkLib -Force
180+
Copy-Item (Join-Path $dist '*.dll') $env:PHP_HOME -Force
181+
Copy-Item (Join-Path $dist 'mpdecimal.h') $sdkInclude -Force
182+
Copy-Item (Join-Path $dist 'decimal.hh') $sdkInclude -Force
183+
184+
- name: Build PHPX
185+
shell: pwsh
186+
run: |
187+
$ErrorActionPreference = 'Stop'
188+
189+
$phpxBuild = Join-Path $env:PHPX_HOME 'build'
190+
$sdkLib = Join-Path $env:PHP_HOME 'SDK\lib'
191+
cmake -S $env:PHPX_HOME -B $phpxBuild -G Ninja `
192+
-D CMAKE_BUILD_TYPE=Release `
193+
-D BUILD_TESTS=OFF `
194+
-D BUILD_EXT=OFF `
195+
-D GITHUB_ACTION=ON `
196+
-D MPDECIMAL_LIBRARY="$sdkLib\libmpdec-4.0.1.dll.lib" `
197+
-D MPDECIMALXX_LIBRARY="$sdkLib\libmpdec++-4.0.1.dll.lib"
198+
if ($LASTEXITCODE -ne 0) {
199+
throw "PHPX configuration failed with exit code $LASTEXITCODE"
200+
}
201+
202+
cmake --build $phpxBuild --target phpx --parallel 2
203+
if ($LASTEXITCODE -ne 0) {
204+
throw "PHPX build failed with exit code $LASTEXITCODE"
205+
}
206+
207+
foreach ($required in @(
208+
(Join-Path $env:PHPX_HOME 'lib\phpx.lib'),
209+
(Join-Path $phpxBuild 'phpx.dll')
210+
)) {
211+
if (-not (Test-Path $required)) {
212+
throw "Required PHPX build output is missing: $required"
213+
}
214+
}
215+
216+
- name: Build tpc.exe
217+
shell: pwsh
218+
run: |
219+
php bin\tpc.php project.yml --job 1 --no-progress
220+
if ($LASTEXITCODE -ne 0) {
221+
throw "TypePHP build failed with exit code $LASTEXITCODE"
222+
}
223+
if (-not (Test-Path 'tpc.exe')) {
224+
throw 'The compiler did not produce tpc.exe'
225+
}
226+
227+
- name: Upload tpc.exe
228+
uses: actions/upload-artifact@v4
229+
with:
230+
name: tpc-windows-x64-php-${{ matrix.php }}
231+
if-no-files-found: error
232+
retention-days: 7
233+
path: tpc.exe

examples/jni/TUTORIAL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
本文将介绍如何使用`Java``JNI`接口,实现在 `PHP` 代码中直接调用 `Java` 类库 —— 创建 `Java` 对象、调用方法、读写字段,就像在 `Java` 代码中操作一样自然。
88

99
1. 本实例程序的代码全部由 `DeepSeek-4-Pro` 生成,耗时约为`50分钟`
10-
2. GitHub: <https://github.com/swoole/aot-compiler/tree/main/examples/jni>
10+
2. GitHub: <https://github.com/swoole/typephp/tree/main/examples/jni>
1111

1212
## 准备工作
1313

0 commit comments

Comments
 (0)