mirror of
https://github.com/aaif-goose/goose.git
synced 2026-06-02 06:14:27 +02:00
Remove vendored Windows binaries (#9318)
Signed-off-by: jh-block <jhugo@block.xyz>
This commit is contained in:
@@ -28,48 +28,15 @@ release-binary:
|
|||||||
@echo "Generating OpenAPI schema..."
|
@echo "Generating OpenAPI schema..."
|
||||||
cargo run -p goose-server --bin generate_schema
|
cargo run -p goose-server --bin generate_schema
|
||||||
|
|
||||||
# release-windows docker build command
|
# Build Windows executable on a Windows host
|
||||||
win_docker_build_sh := '''rustup target add x86_64-pc-windows-gnu && \
|
[unix]
|
||||||
apt-get update && \
|
|
||||||
apt-get install -y mingw-w64 protobuf-compiler cmake && \
|
|
||||||
export CC_x86_64_pc_windows_gnu=x86_64-w64-mingw32-gcc && \
|
|
||||||
export CXX_x86_64_pc_windows_gnu=x86_64-w64-mingw32-g++ && \
|
|
||||||
export AR_x86_64_pc_windows_gnu=x86_64-w64-mingw32-ar && \
|
|
||||||
export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc && \
|
|
||||||
export PKG_CONFIG_ALLOW_CROSS=1 && \
|
|
||||||
export PROTOC=/usr/bin/protoc && \
|
|
||||||
export PATH=/usr/bin:\$PATH && \
|
|
||||||
protoc --version && \
|
|
||||||
cargo build --release --target x86_64-pc-windows-gnu && \
|
|
||||||
GCC_DIR=\$(ls -d /usr/lib/gcc/x86_64-w64-mingw32/*/ | head -n 1) && \
|
|
||||||
cp \$GCC_DIR/libstdc++-6.dll /usr/src/myapp/target/x86_64-pc-windows-gnu/release/ && \
|
|
||||||
cp \$GCC_DIR/libgcc_s_seh-1.dll /usr/src/myapp/target/x86_64-pc-windows-gnu/release/ && \
|
|
||||||
cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll /usr/src/myapp/target/x86_64-pc-windows-gnu/release/
|
|
||||||
'''
|
|
||||||
|
|
||||||
# Build Windows executable
|
|
||||||
release-windows:
|
release-windows:
|
||||||
#!/usr/bin/env sh
|
@echo "just release-windows requires a Windows host because Goose Windows releases build the MSVC target. Use .github/workflows/bundle-desktop-windows.yml for CI builds."
|
||||||
if [ "$(uname)" = "Darwin" ] || [ "$(uname)" = "Linux" ]; then
|
@exit 1
|
||||||
echo "Building Windows executable using Docker..."
|
|
||||||
docker volume create goose-windows-cache || true
|
[windows]
|
||||||
docker run --rm \
|
release-windows:
|
||||||
-v "$(pwd)":/usr/src/myapp \
|
@powershell.exe -NoProfile -ExecutionPolicy Bypass -Command 'rustup target add x86_64-pc-windows-msvc; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }; cargo build --release --target x86_64-pc-windows-msvc -p goose-server; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }; Write-Host "Windows executable created at ./target/x86_64-pc-windows-msvc/release/goosed.exe"'
|
||||||
-v goose-windows-cache:/usr/local/cargo/registry \
|
|
||||||
-w /usr/src/myapp \
|
|
||||||
rust:latest \
|
|
||||||
sh -c "{{win_docker_build_sh}}"
|
|
||||||
else
|
|
||||||
echo "Building Windows executable using Docker through PowerShell..."
|
|
||||||
powershell.exe -Command "docker volume create goose-windows-cache; \`
|
|
||||||
docker run --rm \`
|
|
||||||
-v ${PWD}:/usr/src/myapp \`
|
|
||||||
-v goose-windows-cache:/usr/local/cargo/registry \`
|
|
||||||
-w /usr/src/myapp \`
|
|
||||||
rust:latest \`
|
|
||||||
sh -c '{{win_docker_build_sh}}'"
|
|
||||||
fi
|
|
||||||
echo "Windows executable and required DLLs created at ./target/x86_64-pc-windows-gnu/release/"
|
|
||||||
|
|
||||||
# Build for Intel Mac
|
# Build for Intel Mac
|
||||||
release-intel:
|
release-intel:
|
||||||
@@ -110,16 +77,22 @@ copy-binary-intel:
|
|||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Copy Windows binary command
|
# Copy Windows binary command on a Windows host
|
||||||
|
[unix]
|
||||||
copy-binary-windows:
|
copy-binary-windows:
|
||||||
@powershell.exe -Command "if (Test-Path ./target/x86_64-pc-windows-gnu/release/goosed.exe) { \
|
@echo "just copy-binary-windows requires a Windows host because it copies the MSVC build output."
|
||||||
Write-Host 'Copying Windows binary and DLLs to ui/desktop/src/bin...'; \
|
@exit 1
|
||||||
Copy-Item -Path './target/x86_64-pc-windows-gnu/release/goosed.exe' -Destination './ui/desktop/src/bin/' -Force; \
|
|
||||||
Copy-Item -Path './target/x86_64-pc-windows-gnu/release/*.dll' -Destination './ui/desktop/src/bin/' -Force; \
|
[windows]
|
||||||
|
copy-binary-windows:
|
||||||
|
@powershell.exe -NoProfile -ExecutionPolicy Bypass -Command 'if (Test-Path ./target/x86_64-pc-windows-msvc/release/goosed.exe) { \
|
||||||
|
Write-Host "Copying Windows binary to ui/desktop/src/bin..."; \
|
||||||
|
New-Item -ItemType Directory -Force "./ui/desktop/src/bin" | Out-Null; \
|
||||||
|
Copy-Item -Path "./target/x86_64-pc-windows-msvc/release/goosed.exe" -Destination "./ui/desktop/src/bin/" -Force; \
|
||||||
} else { \
|
} else { \
|
||||||
Write-Host 'Windows binary not found.' -ForegroundColor Red; \
|
Write-Host "Windows binary not found." -ForegroundColor Red; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
}"
|
}'
|
||||||
|
|
||||||
# Run UI with latest
|
# Run UI with latest
|
||||||
run-ui:
|
run-ui:
|
||||||
@@ -247,25 +220,17 @@ make-ui:
|
|||||||
@just release-binary
|
@just release-binary
|
||||||
cd ui/desktop && pnpm run bundle:default
|
cd ui/desktop && pnpm run bundle:default
|
||||||
|
|
||||||
# make GUI with latest Windows binary
|
# make GUI with latest Windows binary on a Windows host
|
||||||
|
[unix]
|
||||||
|
make-ui-windows:
|
||||||
|
@echo "just make-ui-windows requires a Windows host because Goose Windows releases build the MSVC target. Use .github/workflows/bundle-desktop-windows.yml for CI builds."
|
||||||
|
@exit 1
|
||||||
|
|
||||||
|
[windows]
|
||||||
make-ui-windows:
|
make-ui-windows:
|
||||||
@just release-windows
|
@just release-windows
|
||||||
#!/usr/bin/env sh
|
@just copy-binary-windows
|
||||||
set -e
|
@powershell.exe -NoProfile -ExecutionPolicy Bypass -Command 'Set-Location ui/desktop; $env:ELECTRON_PLATFORM="win32"; node scripts/prepare-platform-binaries.js; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }; pnpm run make --platform=win32 --arch=x64; if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }; Write-Host "Windows package build complete!"'
|
||||||
if [ -f "./target/x86_64-pc-windows-gnu/release/goosed.exe" ]; then \
|
|
||||||
echo "Cleaning destination directory..." && \
|
|
||||||
rm -rf ./ui/desktop/src/bin && \
|
|
||||||
mkdir -p ./ui/desktop/src/bin && \
|
|
||||||
echo "Copying Windows binary and DLLs..." && \
|
|
||||||
cp -f ./target/x86_64-pc-windows-gnu/release/goosed.exe ./ui/desktop/src/bin/ && \
|
|
||||||
cp -f ./target/x86_64-pc-windows-gnu/release/*.dll ./ui/desktop/src/bin/ && \
|
|
||||||
echo "Starting Windows package build..." && \
|
|
||||||
(cd ui/desktop && pnpm run bundle:windows) && \
|
|
||||||
echo "Windows package build complete!"; \
|
|
||||||
else \
|
|
||||||
echo "Windows binary not found."; \
|
|
||||||
exit 1; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# make GUI with latest binary
|
# make GUI with latest binary
|
||||||
make-ui-intel:
|
make-ui-intel:
|
||||||
|
|||||||
@@ -513,7 +513,6 @@ fn replace_binary(new_binary: &Path, current_exe: &Path) -> Result<()> {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Copy any .dll files from the extracted archive alongside the installed binary.
|
/// Copy any .dll files from the extracted archive alongside the installed binary.
|
||||||
/// Windows GNU builds ship with libgcc, libstdc++, libwinpthread DLLs.
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
fn copy_dlls(extracted_binary: &Path, current_exe: &Path) -> Result<()> {
|
fn copy_dlls(extracted_binary: &Path, current_exe: &Path) -> Result<()> {
|
||||||
let source_dir = extracted_binary
|
let source_dir = extracted_binary
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ src/bin/goosed
|
|||||||
src/bin/goose-npm/
|
src/bin/goose-npm/
|
||||||
/src/bin/*.exe
|
/src/bin/*.exe
|
||||||
/src/bin/*.cmd
|
/src/bin/*.cmd
|
||||||
|
/src/platform/windows/bin/*.dll
|
||||||
|
/src/platform/windows/bin/*.exe
|
||||||
/playwright-report/
|
/playwright-report/
|
||||||
/test-results/
|
/test-results/
|
||||||
/src/bin/temporal-service
|
/src/bin/temporal-service
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const https = require('https');
|
||||||
|
const os = require('os');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const { execFileSync } = require('child_process');
|
||||||
|
|
||||||
// Paths
|
// Paths
|
||||||
const srcBinDir = path.join(__dirname, '..', 'src', 'bin');
|
const srcBinDir = path.join(__dirname, '..', 'src', 'bin');
|
||||||
const platformWinDir = path.join(__dirname, '..', 'src', 'platform', 'windows', 'bin');
|
const platformWinDir = path.join(__dirname, '..', 'src', 'platform', 'windows', 'bin');
|
||||||
|
const uvVersion = '0.11.11';
|
||||||
|
const uvDownloadUrl = `https://github.com/astral-sh/uv/releases/download/${uvVersion}/uv-x86_64-pc-windows-msvc.zip`;
|
||||||
|
const uvBinaryHashes = {
|
||||||
|
'uv.exe': 'b1645e948603c12dd741987d0c072471195e18dd299b42334477ceac694f0af8',
|
||||||
|
'uvx.exe': '0305c488dc29c16df1483c02a902d21a6798b0744f8e9eb34271d6b3e4bf6e2a',
|
||||||
|
};
|
||||||
|
|
||||||
// Platform-specific file patterns
|
// Platform-specific file patterns
|
||||||
const windowsFiles = [
|
const windowsFiles = [
|
||||||
@@ -49,6 +59,106 @@ function matchesPattern(filename, patterns) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sha256(filePath) {
|
||||||
|
const hash = crypto.createHash('sha256');
|
||||||
|
hash.update(fs.readFileSync(filePath));
|
||||||
|
return hash.digest('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasExpectedHash(filePath, expectedHash) {
|
||||||
|
return fs.existsSync(filePath) && sha256(filePath) === expectedHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadFile(url, destPath, redirectsRemaining = 5) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
https.get(url, response => {
|
||||||
|
if (
|
||||||
|
response.statusCode >= 300 &&
|
||||||
|
response.statusCode < 400 &&
|
||||||
|
response.headers.location &&
|
||||||
|
redirectsRemaining > 0
|
||||||
|
) {
|
||||||
|
response.resume();
|
||||||
|
downloadFile(response.headers.location, destPath, redirectsRemaining - 1)
|
||||||
|
.then(resolve)
|
||||||
|
.catch(reject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.statusCode !== 200) {
|
||||||
|
response.resume();
|
||||||
|
reject(new Error(`Failed to download ${url}: HTTP ${response.statusCode}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const file = fs.createWriteStream(destPath);
|
||||||
|
response.pipe(file);
|
||||||
|
file.on('finish', () => file.close(resolve));
|
||||||
|
file.on('error', reject);
|
||||||
|
}).on('error', reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractZip(zipPath, destDir) {
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
execFileSync(
|
||||||
|
'powershell.exe',
|
||||||
|
[
|
||||||
|
'-NoProfile',
|
||||||
|
'-ExecutionPolicy',
|
||||||
|
'Bypass',
|
||||||
|
'-Command',
|
||||||
|
`Expand-Archive -LiteralPath '${zipPath.replace(/'/g, "''")}' -DestinationPath '${destDir.replace(/'/g, "''")}' -Force`,
|
||||||
|
],
|
||||||
|
{ stdio: 'inherit' }
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
execFileSync('unzip', ['-q', zipPath, '-d', destDir], { stdio: 'inherit' });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ensureWindowsUvBinaries() {
|
||||||
|
const allPresent = Object.entries(uvBinaryHashes).every(([name, expectedHash]) =>
|
||||||
|
hasExpectedHash(path.join(srcBinDir, name), expectedHash)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (allPresent) {
|
||||||
|
console.log(`Pinned uv ${uvVersion} binaries already present`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'goose-uv-'));
|
||||||
|
const zipPath = path.join(tmpDir, 'uv.zip');
|
||||||
|
const extractDir = path.join(tmpDir, 'extract');
|
||||||
|
fs.mkdirSync(extractDir, { recursive: true });
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log(`Downloading uv ${uvVersion} from ${uvDownloadUrl}`);
|
||||||
|
await downloadFile(uvDownloadUrl, zipPath);
|
||||||
|
extractZip(zipPath, extractDir);
|
||||||
|
|
||||||
|
for (const [name, expectedHash] of Object.entries(uvBinaryHashes)) {
|
||||||
|
const extractedPath = path.join(extractDir, name);
|
||||||
|
if (!fs.existsSync(extractedPath)) {
|
||||||
|
throw new Error(`Downloaded uv archive did not contain ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const actualHash = sha256(extractedPath);
|
||||||
|
if (actualHash !== expectedHash) {
|
||||||
|
throw new Error(
|
||||||
|
`${name} checksum mismatch for uv ${uvVersion}: expected ${expectedHash}, got ${actualHash}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.copyFileSync(extractedPath, path.join(srcBinDir, name));
|
||||||
|
console.log(`Copied pinned ${name}`);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function to clean directory of cross-platform files
|
// Helper function to clean directory of cross-platform files
|
||||||
function cleanBinDirectory(targetPlatform) {
|
function cleanBinDirectory(targetPlatform) {
|
||||||
console.log(`Cleaning bin directory for ${targetPlatform} build...`);
|
console.log(`Cleaning bin directory for ${targetPlatform} build...`);
|
||||||
@@ -95,7 +205,7 @@ function cleanBinDirectory(targetPlatform) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to copy platform-specific files
|
// Helper function to copy platform-specific files
|
||||||
function copyPlatformFiles(targetPlatform) {
|
async function copyPlatformFiles(targetPlatform) {
|
||||||
if (targetPlatform === 'win32') {
|
if (targetPlatform === 'win32') {
|
||||||
console.log('Copying Windows-specific files...');
|
console.log('Copying Windows-specific files...');
|
||||||
|
|
||||||
@@ -109,10 +219,15 @@ function copyPlatformFiles(targetPlatform) {
|
|||||||
fs.mkdirSync(srcBinDir, { recursive: true });
|
fs.mkdirSync(srcBinDir, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy Windows-specific files
|
// Copy Windows-specific scripts and authored support files.
|
||||||
const files = fs.readdirSync(platformWinDir, { withFileTypes: true });
|
const files = fs.readdirSync(platformWinDir, { withFileTypes: true });
|
||||||
files.forEach(file => {
|
files.forEach(file => {
|
||||||
if (file.name === 'README.md' || file.name === '.gitignore') {
|
if (
|
||||||
|
file.name === 'README.md' ||
|
||||||
|
file.name === '.gitignore' ||
|
||||||
|
file.name.endsWith('.exe') ||
|
||||||
|
file.name.endsWith('.dll')
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,17 +242,19 @@ function copyPlatformFiles(targetPlatform) {
|
|||||||
console.log(`Copied: ${file.name}`);
|
console.log(`Copied: ${file.name}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await ensureWindowsUvBinaries();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main function
|
// Main function
|
||||||
function preparePlatformBinaries() {
|
async function preparePlatformBinaries() {
|
||||||
const targetPlatform = process.env.ELECTRON_PLATFORM || process.platform;
|
const targetPlatform = process.env.ELECTRON_PLATFORM || process.platform;
|
||||||
|
|
||||||
console.log(`Preparing binaries for platform: ${targetPlatform}`);
|
console.log(`Preparing binaries for platform: ${targetPlatform}`);
|
||||||
|
|
||||||
// First copy platform-specific files if needed
|
// First copy platform-specific files if needed
|
||||||
copyPlatformFiles(targetPlatform);
|
await copyPlatformFiles(targetPlatform);
|
||||||
|
|
||||||
// Then clean up cross-platform files
|
// Then clean up cross-platform files
|
||||||
cleanBinDirectory(targetPlatform);
|
cleanBinDirectory(targetPlatform);
|
||||||
@@ -147,7 +264,10 @@ function preparePlatformBinaries() {
|
|||||||
|
|
||||||
// Run if called directly
|
// Run if called directly
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
preparePlatformBinaries();
|
preparePlatformBinaries().catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { preparePlatformBinaries };
|
module.exports = { preparePlatformBinaries };
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Windows-Specific Binaries
|
# Windows-Specific Runtime Files
|
||||||
|
|
||||||
This directory contains Windows-specific binaries and scripts that are only included during Windows builds.
|
This directory contains Windows-specific scripts that are only included during Windows builds.
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||
@@ -9,13 +9,13 @@ This directory contains Windows-specific binaries and scripts that are only incl
|
|||||||
- `npx.cmd` - Wrapper script that ensures Node.js is installed and uses system npx
|
- `npx.cmd` - Wrapper script that ensures Node.js is installed and uses system npx
|
||||||
|
|
||||||
### Windows Binaries
|
### Windows Binaries
|
||||||
- `*.dll` files - Required Windows dynamic libraries
|
- `uv.exe` and `uvx.exe` are downloaded from the pinned Astral uv release during packaging.
|
||||||
- `*.exe` files - Windows executables
|
- Compiled `.exe` and `.dll` files are generated or fetched during the build and are not committed.
|
||||||
|
|
||||||
## Build Process
|
## Build Process
|
||||||
|
|
||||||
These files are generated during the Windows build process by:
|
Windows runtime files are prepared during the build process by:
|
||||||
1. `prepare-windows-npm.sh` - Creates Node.js installation scripts
|
1. `prepare-windows-npm.sh` - Creates Node.js installation scripts
|
||||||
2. `copy-windows-dlls.js` - Copies all Windows-specific files to the output directory
|
2. `prepare-platform-binaries.js` - Downloads pinned uv binaries and copies Windows-specific files to `src/bin`
|
||||||
|
|
||||||
None of these files should be committed to the repository - they are generated fresh during each Windows build.
|
None of these files should be committed to the repository - they are generated fresh during each Windows build.
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user