Need help linking to third-party dynamic library

I'm building a small Rust command-line tool that needs to use services from a specific third-party C++ DLL that I know will be installed at a specific location. Because this library is not mine, I am not in control of any of the following:

  • where the DLL is installed (on Mac, it is in /Library/Application Support/...)
  • that is is a DLL and not a static library
  • that the interfaces to the DLL are in C++
  • the name of the DLL (which does not contain the lib prefix)

I'm having a bear of a time coming up with a build.rs script that will find it and link to it appropriately.

I've gotten far enough that I can get cargo build to succeed, but I but both cargo test or cargo run fail with message similar to the following:

dyld: Library not loaded: @rpath/MyMagicLibrary.dylib
  Reference from: /Users/scouten/my/repo/target/debug/deps/appname-deadbeefdeadbeef
  Reason: image not found

I was able to get as far as building successfully by sym-linking the DLL into OUT_DIR, but this apparently baked in a reference to @rpath which becomes invalid at subsequent steps.

I'm currently testing on Mac OS, but I expect to have similar issues on an upcoming Windows build.

What tricks are available for me to access this DLL?

I've been wrestling with build failures for hours and I'm running out of ideas.

Cargo doesn't give you control over this, so you will need external tools to fix rpath.

@rpath/MyMagicLibrary.dylib means the executable expects to find MyMagicLibrary.dylib in the same directory where it's been launched from. So that's normal that tests fail, because Cargo doesn't know it needs to copy MyMagicLibrary.dylib into its temporary directories for tests.

On macOS you will need install_name_tool to change this library's path to use an absolute path.

otool -L lists where an executable wants libraries located.

1 Like

Thanks, when I apply install_name_tool manually it works.

Now to figure out how to insert that step into the right place in cargo test and cargo run

For test/run I copy the library into guts of target/debug/ where the default path finds it.