fix(aria2): bundle MinGW runtime dependencies

- collect the Windows DLL dependency closure into the staged Aria2 payload

- expose the trusted runtime directory to native and CI Aria2 processes

- keep OpenSSL provider modules available for Windows smoke and packaged runs
This commit is contained in:
NimBold
2026-09-06 16:54:52 +03:30
parent 9ac3dc27a3
commit 74eb2f84cf
6 changed files with 92 additions and 8 deletions
+36
View File
@@ -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
+4
View File
@@ -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, [
+4
View File
@@ -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, [
+9 -3
View File
@@ -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 } = {}) {
+4
View File
@@ -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] || ''}` }
: {}),
};
}
+35 -5
View File
@@ -160,19 +160,49 @@ pub fn ytdlp_internal_dir(binary_path: &Path) -> Option<PathBuf> {
}
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<C>(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<std::ffi::OsStr>);
}
impl Aria2CommandEnvironment for std::process::Command {
fn set_env(&mut self, key: &str, value: impl AsRef<std::ffi::OsStr>) {
self.env(key, value);
}
}
impl Aria2CommandEnvironment for tokio::process::Command {
fn set_env(&mut self, key: &str, value: impl AsRef<std::ffi::OsStr>) {
self.env(key, value);
}
}
fn aria2_openssl_modules_dir(binary_path: &Path) -> Option<PathBuf> {
if !cfg!(target_os = "macos") {
if !cfg!(any(target_os = "macos", target_os = "windows")) {
return None;
}