Skip to content

Commit c631a59

Browse files
feat: auto-download pre-built WebView helper binaries on install
- Add build-webview-helper.yml: CI builds binaries for Linux x86_64, macOS x86_64, macOS ARM64, and Windows x86_64 on tag push, then attaches them to a GitHub Release - Add scripts/install-webview-helper.php: detects platform, downloads the matching binary from the latest release, skips if already present - Wire composer post-install/post-update hooks to run the installer - ProcessWebView::findBinary() now auto-triggers the installer if the binary is missing, with build-from-source fallback Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f0baf78 commit c631a59

4 files changed

Lines changed: 292 additions & 1 deletion

File tree

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
name: Build WebView Helper Binaries
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
build-linux:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Install build dependencies
18+
run: sudo apt-get update && sudo apt-get install -y cmake libgtk-3-dev libwebkit2gtk-4.1-dev
19+
20+
- name: Build helper binary
21+
run: cd src/lib/webview_helper && bash build.sh
22+
23+
- name: Upload artifact
24+
uses: actions/upload-artifact@v4
25+
with:
26+
name: webview_helper_linux_x86_64
27+
path: src/lib/webview_helper_linux_x86_64
28+
29+
build-macos-intel:
30+
runs-on: macos-13
31+
steps:
32+
- uses: actions/checkout@v4
33+
34+
- name: Install CMake
35+
run: brew install cmake || true
36+
37+
- name: Build helper binary
38+
run: cd src/lib/webview_helper && bash build.sh
39+
40+
- name: Upload artifact
41+
uses: actions/upload-artifact@v4
42+
with:
43+
name: webview_helper_darwin_x86_64
44+
path: src/lib/webview_helper_darwin_x86_64
45+
46+
build-macos-arm:
47+
runs-on: macos-latest
48+
steps:
49+
- uses: actions/checkout@v4
50+
51+
- name: Install CMake
52+
run: brew install cmake || true
53+
54+
- name: Build helper binary
55+
run: cd src/lib/webview_helper && bash build.sh
56+
57+
- name: Upload artifact
58+
uses: actions/upload-artifact@v4
59+
with:
60+
name: webview_helper_darwin_arm64
61+
path: src/lib/webview_helper_darwin_arm64
62+
63+
build-windows:
64+
runs-on: windows-latest
65+
steps:
66+
- uses: actions/checkout@v4
67+
68+
- name: Build helper binary
69+
shell: cmd
70+
run: |
71+
cd src\lib\webview_helper
72+
mkdir build
73+
cd build
74+
cmake .. -DCMAKE_BUILD_TYPE=Release
75+
cmake --build . --config Release
76+
77+
- name: Upload artifact
78+
uses: actions/upload-artifact@v4
79+
with:
80+
name: webview_helper_windows_x86_64.exe
81+
path: src/lib/webview_helper_windows_x86_64.exe
82+
83+
release:
84+
needs: [build-linux, build-macos-intel, build-macos-arm, build-windows]
85+
runs-on: ubuntu-latest
86+
steps:
87+
- name: Download all artifacts
88+
uses: actions/download-artifact@v4
89+
with:
90+
path: binaries
91+
merge-multiple: true
92+
93+
- name: List binaries
94+
run: ls -la binaries/
95+
96+
- name: Create GitHub Release
97+
uses: softprops/action-gh-release@v2
98+
with:
99+
generate_release_notes: true
100+
files: binaries/*

composer.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,10 @@
1010
"psr-4": {
1111
"PhpGui\\": "src/"
1212
}
13+
},
14+
"scripts": {
15+
"post-install-cmd": "@php scripts/install-webview-helper.php",
16+
"post-update-cmd": "@php scripts/install-webview-helper.php",
17+
"install-webview": "@php scripts/install-webview-helper.php"
1318
}
1419
}

scripts/install-webview-helper.php

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
/**
5+
* Downloads the pre-built WebView helper binary for the current platform.
6+
*
7+
* Called automatically via composer post-install/post-update hooks,
8+
* or manually: php scripts/install-webview-helper.php
9+
*
10+
* Falls back to build-from-source instructions if download fails.
11+
*/
12+
13+
const REPO = 'developersharif/php-gui';
14+
15+
function getOs(): string
16+
{
17+
return match (PHP_OS_FAMILY) {
18+
'Darwin' => 'darwin',
19+
'Windows' => 'windows',
20+
default => 'linux',
21+
};
22+
}
23+
24+
function getArch(): string
25+
{
26+
$arch = php_uname('m');
27+
if ($arch === 'AMD64') return 'x86_64';
28+
$os = getOs();
29+
if ($os === 'darwin' && $arch === 'aarch64') return 'arm64';
30+
return $arch;
31+
}
32+
33+
function getBinaryName(): string
34+
{
35+
$os = getOs();
36+
$arch = getArch();
37+
$ext = $os === 'windows' ? '.exe' : '';
38+
return "webview_helper_{$os}_{$arch}{$ext}";
39+
}
40+
41+
function getLibDir(): string
42+
{
43+
// When run from project root (development or post-install)
44+
$dir = dirname(__DIR__) . '/src/lib/';
45+
if (is_dir($dir)) {
46+
return $dir;
47+
}
48+
49+
// When installed as a dependency (vendor/developersharif/php-gui/scripts/)
50+
$dir = dirname(__DIR__) . '/src/lib/';
51+
if (!is_dir(dirname($dir))) {
52+
@mkdir(dirname($dir), 0755, true);
53+
}
54+
@mkdir($dir, 0755, true);
55+
return $dir;
56+
}
57+
58+
function getLatestReleaseTag(): ?string
59+
{
60+
$url = 'https://api.github.com/repos/' . REPO . '/releases/latest';
61+
62+
$context = stream_context_create([
63+
'http' => [
64+
'header' => "User-Agent: php-gui-installer\r\n",
65+
'timeout' => 15,
66+
],
67+
]);
68+
69+
$json = @file_get_contents($url, false, $context);
70+
if ($json === false) {
71+
return null;
72+
}
73+
74+
$data = json_decode($json, true);
75+
return $data['tag_name'] ?? null;
76+
}
77+
78+
function downloadBinary(string $tag, string $binaryName, string $destPath): bool
79+
{
80+
$url = sprintf(
81+
'https://github.com/%s/releases/download/%s/%s',
82+
REPO,
83+
$tag,
84+
$binaryName
85+
);
86+
87+
echo " Downloading from: {$url}\n";
88+
89+
$context = stream_context_create([
90+
'http' => [
91+
'header' => "User-Agent: php-gui-installer\r\n",
92+
'timeout' => 60,
93+
'follow_location' => true,
94+
],
95+
]);
96+
97+
$data = @file_get_contents($url, false, $context);
98+
if ($data === false) {
99+
return false;
100+
}
101+
102+
if (file_put_contents($destPath, $data) === false) {
103+
return false;
104+
}
105+
106+
// Make executable on Unix
107+
if (PHP_OS_FAMILY !== 'Windows') {
108+
chmod($destPath, 0755);
109+
}
110+
111+
return true;
112+
}
113+
114+
function buildFromSourceInstructions(): string
115+
{
116+
$os = getOs();
117+
$msg = " Build from source:\n";
118+
$msg .= " cd src/lib/webview_helper && bash build.sh\n";
119+
if ($os === 'linux') {
120+
$msg .= " Requires: sudo apt-get install -y cmake libgtk-3-dev libwebkit2gtk-4.1-dev\n";
121+
} elseif ($os === 'darwin') {
122+
$msg .= " Requires: brew install cmake\n";
123+
} else {
124+
$msg .= " Requires: cmake and Visual Studio Build Tools\n";
125+
}
126+
return $msg;
127+
}
128+
129+
// ── Main ──────────────────────────────────────────────────────────────────
130+
131+
echo "php-gui: Installing WebView helper binary...\n";
132+
133+
$binaryName = getBinaryName();
134+
$libDir = getLibDir();
135+
$destPath = $libDir . $binaryName;
136+
137+
// Skip if binary already exists
138+
if (file_exists($destPath)) {
139+
echo " Binary already exists: {$destPath}\n";
140+
echo " To force re-download, delete it and run again.\n";
141+
exit(0);
142+
}
143+
144+
echo " Platform: " . getOs() . "/" . getArch() . "\n";
145+
echo " Binary: {$binaryName}\n";
146+
147+
// Fetch latest release tag
148+
echo " Fetching latest release...\n";
149+
$tag = getLatestReleaseTag();
150+
151+
if ($tag === null) {
152+
echo " WARNING: Could not fetch release info from GitHub.\n";
153+
echo " This may be due to network issues or no releases published yet.\n";
154+
echo "\n";
155+
echo buildFromSourceInstructions();
156+
exit(1);
157+
}
158+
159+
echo " Release: {$tag}\n";
160+
161+
// Download
162+
if (downloadBinary($tag, $binaryName, $destPath)) {
163+
$size = round(filesize($destPath) / 1024 / 1024, 1);
164+
echo " Installed: {$destPath} ({$size} MB)\n";
165+
exit(0);
166+
}
167+
168+
// Download failed
169+
echo " WARNING: Download failed.\n";
170+
echo "\n";
171+
echo buildFromSourceInstructions();
172+
exit(1);

src/ProcessWebView.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,22 @@ private function findBinary(): string
278278
$binary = $libDir . "webview_helper_{$os}_{$arch}{$ext}";
279279

280280
if (!file_exists($binary)) {
281+
// Try auto-downloading the binary
282+
$installer = dirname(__DIR__) . '/scripts/install-webview-helper.php';
283+
if (file_exists($installer)) {
284+
$exitCode = 0;
285+
passthru('php ' . escapeshellarg($installer), $exitCode);
286+
if ($exitCode === 0 && file_exists($binary)) {
287+
if ($os !== 'windows' && !is_executable($binary)) {
288+
chmod($binary, 0755);
289+
}
290+
return $binary;
291+
}
292+
}
293+
281294
$msg = "WebView helper binary not found: {$binary}\n";
282-
$msg .= "Build from source: cd src/lib/webview_helper && bash build.sh\n";
295+
$msg .= "Run: composer install-webview\n";
296+
$msg .= "Or build from source: cd src/lib/webview_helper && bash build.sh\n";
283297
if ($os === 'linux') {
284298
$msg .= "Requires: sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev\n";
285299
}

0 commit comments

Comments
 (0)