Dll lookup fails on application load time

Viewed 253

I'm trying to follow bevy's tutorial and setup everything on Windows 10 (21H1) x64. The setup kinda works. I did the following build optimizations (from bevy's tutorial):

  1. bevy's dynamic link feature
  2. switch to the LLD linker
  3. switch to latest rust nightly
  4. disable shared generics (because of this issue)

My cargo.toml

[package]
name = "foo"
version = "0.1.0"
authors = ["foo <foo@bar.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bevy = "0.5"

My main.rs (the only code file so far):

use bevy::prelude::*;

fn main() {
    println!("hello");
    App::build().run();
}

My .cargo/config.toml:

[target.x86_64-pc-windows-msvc]
linker = "rust-lld.exe"
rustflags = ["-Zshare-generics=off"]

After building my application, target/debug/ looks something like this (I removed some entries):

deps/
bevy_dylib.dll
bevy_dylib.dll.lib
bevy_dylib.pdb
foo.d
foo.exe
foo.pdb

I can build and run the application just fine using cargo with the command cargo run --features bevy/dynamic. The program prints "hello" and exists normally. However, if I run the program from the terminal (powershell in my case) nothing is print and the program exists with no error code. Seeing that lldb also crashes with "unknown error" I went ahead and took a closer look with procmon.

cargo run vs .\foo.exe

Using cargo run --features bevy/dynamic works fine, but .\foo.exe (run directly from powershell) fails without errors. Procmon reveals that .\foo.exe tries to load a different dll, it searches for bevy_dylib-d54840081e5b3869.dll instead of bevy_dylib.dll. This obviously fails because this file doesn't exist and so the program terminates before it even reaches main().

But why does cargo run --features bevy/dynamic work then? Well it turns out that the program still tries to load bevy_dylib-d54840081e5b3869.dll, however this time the loader looks up different paths. There is an additional search path: {my_project}/target/debug/deps/. And that directory actually has a dll with that exact name which is then loaded and the program can execute normally. So it turns out we never even try to use the dll target/debug/bevy_dylib.dll which makes me wonder why it's there in the first place.

My questions are:

  1. Why does cargo run use additional lookup directories at load time linking?
  2. Why does the program search for bevy_dylib-d54840081e5b3869.dll instead of bevy_dylib.dll?
  3. Is this fixable without some nasty post build tasks that copy dlls manually around?
0 Answers
Related