diff --git a/scripts/aria2/build.sh b/scripts/aria2/build.sh index 91e5e22..91aef8f 100755 --- a/scripts/aria2/build.sh +++ b/scripts/aria2/build.sh @@ -10,6 +10,29 @@ if command -v cygpath >/dev/null 2>&1; then export ACLOCAL_PATH="/mingw64/share/aclocal:/usr/share/aclocal${ACLOCAL_PATH:+:$ACLOCAL_PATH}" export PKG_CONFIG_PATH=/mingw64/lib/pkgconfig fi + +copy_mingw_runtime_dependencies() { + local binary="$1" + local runtime_dir="$2" + local dependency + local source + local destination + + while IFS= read -r dependency; do + [[ -z "$dependency" ]] && continue + source="/mingw64/bin/$dependency" + if [[ ! -f "$source" ]]; then + continue + fi + destination="$runtime_dir/$dependency" + if [[ -e "$destination" ]]; then + continue + fi + cp "$source" "$destination" + copy_mingw_runtime_dependencies "$destination" "$runtime_dir" + done < <(objdump -p "$binary" | awk '/DLL Name:/{print $3}') +} + cd "$source_root" patch --batch -p1 < "$patch_file" autoreconf -fi @@ -23,3 +46,16 @@ export PKG_CONFIG="pkg-config --static" --without-libgmp --without-libnettle --without-libgcrypt \ --with-libssh2 --with-libcares make -j2 + +if command -v cygpath >/dev/null 2>&1; then + command -v objdump >/dev/null 2>&1 || { + echo "MinGW objdump is required to collect Aria2 runtime dependencies." >&2 + exit 1 + } + runtime_dir="$source_root/aria2-libs" + mkdir -p "$runtime_dir" + copy_mingw_runtime_dependencies "$source_root/firelink-build/src/aria2c.exe" "$runtime_dir" + if [[ -d /mingw64/lib/ossl-modules ]]; then + find /mingw64/lib/ossl-modules -maxdepth 1 -type f -iname '*.dll' -exec cp {} "$runtime_dir/" \; + fi +fi diff --git a/scripts/smoke-aria2-resolver.js b/scripts/smoke-aria2-resolver.js index b5a95c1..2fb76b9 100644 --- a/scripts/smoke-aria2-resolver.js +++ b/scripts/smoke-aria2-resolver.js @@ -189,11 +189,15 @@ await new Promise((resolve, reject) => { }); const contentPort = contentServer.address().port; const libraryPath = path.join(path.dirname(binaryPath), 'aria2-libs'); +const pathKey = Object.keys(process.env).find(key => key.toLowerCase() === 'path') || 'PATH'; const environment = fs.existsSync(libraryPath) ? { ...process.env, OPENSSL_MODULES: libraryPath, ...(process.platform === 'darwin' ? { DYLD_LIBRARY_PATH: libraryPath } : {}), + ...(process.platform === 'win32' + ? { [pathKey]: `${libraryPath}${path.delimiter}${process.env[pathKey] || ''}` } + : {}), } : process.env; const child = spawn(binaryPath, [ diff --git a/scripts/smoke-aria2-transfers.js b/scripts/smoke-aria2-transfers.js index 941b3cd..725dd15 100644 --- a/scripts/smoke-aria2-transfers.js +++ b/scripts/smoke-aria2-transfers.js @@ -315,11 +315,15 @@ const secret = `firelink-transfers-${crypto.randomUUID()}`; const configPath = path.join(tempRoot, 'aria2.conf'); fs.writeFileSync(configPath, `rpc-secret=${secret}\n`, { mode: 0o600 }); const libraryPath = path.join(path.dirname(binaryPath), 'aria2-libs'); +const pathKey = Object.keys(process.env).find(key => key.toLowerCase() === 'path') || 'PATH'; const environment = fs.existsSync(libraryPath) ? { ...process.env, OPENSSL_MODULES: libraryPath, ...(process.platform === 'darwin' ? { DYLD_LIBRARY_PATH: libraryPath } : {}), + ...(process.platform === 'win32' + ? { [pathKey]: `${libraryPath}${path.delimiter}${process.env[pathKey] || ''}` } + : {}), } : process.env; const child = spawn(binaryPath, [ diff --git a/scripts/smoke-torrent.js b/scripts/smoke-torrent.js index 6e33e78..ea73b1d 100644 --- a/scripts/smoke-torrent.js +++ b/scripts/smoke-torrent.js @@ -262,9 +262,15 @@ async function listen(server) { function daemonEnvironment() { const libraries = path.join(path.dirname(binaryPath), 'aria2-libs'); - return fs.existsSync(libraries) - ? { ...process.env, OPENSSL_MODULES: libraries } - : process.env; + if (!fs.existsSync(libraries)) return process.env; + const pathKey = Object.keys(process.env).find(key => key.toLowerCase() === 'path') || 'PATH'; + return { + ...process.env, + OPENSSL_MODULES: libraries, + ...(process.platform === 'win32' + ? { [pathKey]: `${libraries}${path.delimiter}${process.env[pathKey] || ''}` } + : {}), + }; } async function rpc(port, secret, method, params = [], { signal = runtimeAbortController.signal } = {}) { diff --git a/scripts/verify-binaries.js b/scripts/verify-binaries.js index b04b3a6..a62db43 100644 --- a/scripts/verify-binaries.js +++ b/scripts/verify-binaries.js @@ -160,9 +160,13 @@ function engineEnv(engine) { return process.env; } + const pathKey = Object.keys(process.env).find(key => key.toLowerCase() === 'path') || 'PATH'; return { ...process.env, OPENSSL_MODULES: modulesDir, + ...(process.platform === 'win32' + ? { [pathKey]: `${modulesDir}${path.delimiter}${process.env[pathKey] || ''}` } + : {}), }; } diff --git a/src-tauri/src/engines.rs b/src-tauri/src/engines.rs index 9daebe2..05d163a 100644 --- a/src-tauri/src/engines.rs +++ b/src-tauri/src/engines.rs @@ -160,19 +160,49 @@ pub fn ytdlp_internal_dir(binary_path: &Path) -> Option { } pub fn apply_aria2_environment(command: &mut std::process::Command, binary_path: &Path) { - if let Some(modules_dir) = aria2_openssl_modules_dir(binary_path) { - command.env("OPENSSL_MODULES", modules_dir); - } + apply_aria2_runtime_environment(command, binary_path); } pub fn apply_aria2_tokio_environment(command: &mut tokio::process::Command, binary_path: &Path) { + apply_aria2_runtime_environment(command, binary_path); +} + +fn apply_aria2_runtime_environment(command: &mut C, binary_path: &Path) +where + C: Aria2CommandEnvironment, +{ if let Some(modules_dir) = aria2_openssl_modules_dir(binary_path) { - command.env("OPENSSL_MODULES", modules_dir); + command.set_env("OPENSSL_MODULES", &modules_dir); + #[cfg(target_os = "windows")] + { + let mut path = modules_dir.as_os_str().to_os_string(); + path.push(";"); + if let Some(existing) = std::env::var_os("PATH") { + path.push(existing); + } + command.set_env("PATH", path); + } + } +} + +trait Aria2CommandEnvironment { + fn set_env(&mut self, key: &str, value: impl AsRef); +} + +impl Aria2CommandEnvironment for std::process::Command { + fn set_env(&mut self, key: &str, value: impl AsRef) { + self.env(key, value); + } +} + +impl Aria2CommandEnvironment for tokio::process::Command { + fn set_env(&mut self, key: &str, value: impl AsRef) { + self.env(key, value); } } fn aria2_openssl_modules_dir(binary_path: &Path) -> Option { - if !cfg!(target_os = "macos") { + if !cfg!(any(target_os = "macos", target_os = "windows")) { return None; }