Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deficient documentation for linking external .dylib on macos #4421

Open
za121 opened this issue Aug 21, 2017 · 10 comments
Open

Deficient documentation for linking external .dylib on macos #4421

za121 opened this issue Aug 21, 2017 · 10 comments
Labels
A-documenting-cargo-itself Area: Cargo's documentation A-linkage Area: linker issues, dylib, cdylib, shared libraries, so C-bug Category: bug S-triage Status: This issue is waiting on initial triage.

Comments

@za121
Copy link

za121 commented Aug 21, 2017

This is what we have right now:
http://doc.crates.io/build-script.html

Here's what Mac users go through to link .dylib libraries (still didn't work for me, but closer):
https://stackoverflow.com/questions/40602708/linking-rust-application-with-a-dynamic-library-not-in-the-runtime-linker-search

I haven't been able to find documentation for an FFI "hello world" using a dylib. Here's what my current (bad) flow has been trying to work through this problem.

0.) cargo new foobar --bin
1.) Alright, I'll use a build script to link against /path/to/lib/libfoo.1.dylib
build.rs

fn main()
{
    println!("
            cargo:rustc-link-lib=dylib=foo
            cargo:rustc-link-search=native=/path/to/lib
            ");
}
cargo run
dyld: Library not loaded: @rpath/lib/libfoo.1.dylib
  Referenced from: /foobar/target/debug/foobar
  Reason: image not found

2.) Alright, well after an online search, I've learned that in [profile.dev] that rpath defaults to false for some reason, even on Mac. No big deal though, I'll just set it to true

Cargo.toml

[package]
name = "foobar"
version = "0.1.0"
authors = ["Dummy Mcdumbhead <[email protected]>"]

[dependencies]

[profile.dev]
rpath = true

Exactly the same error. Note that at this point, I haven't even tried to call any library functions from the library, just link it. I've still got cargo's basic hello world in main.rs

3. ) I stumble across the stack overflow question/answer linked at the top of this post and I see this line:
cargo rustc -- -C link-args="-Wl,-rpath,/scratch/library/"
I'm not really sure exactly what it does, I can't really figure out how it works from looking at it, and a search for cargo rustc isn't too helpful, so I paste it into the commandline, changing the /scratch/library/ to /path/to/lib/ and then try cargo run again, but get the same error.

4.) Ah, maybe I need to add that cargo line to the build.rs script? The build.rs main function now looks like this:

fn main()
{
    println!("
            cargo:rustc-link-lib=dylib=foo
            cargo:rustc-link-search=native=/path/to/lib
            cargo rustc -- -C link-args=\"-Wl,-rpath,/path/to/lib/\"
            ");
}

Nope, no dice. At this point, things are working for the stackoverflow question answerer, but I'm still stuck with my binary missing the rpath entry for my library and unable to run on my chosen platform. So in the end, this issue is both a question (how do I make this work on macos?) and a documentation request (linking against an arbitrary c dylib is undoubtedly pretty common especially among c developers who want to incrementally try out Rust but can't just rewrite their whole code base first).

@za121 za121 changed the title Deficien documentation for linking external .dylib on macos Deficient documentation for linking external .dylib on macos Aug 21, 2017
@alexcrichton
Copy link
Member

I think the build script is the problem here because the string literal you're passing to println! has leading whitespace. If you remove that does it work?

@za121
Copy link
Author

za121 commented Aug 22, 2017

Still doesn't work.

This is what I tried:

fn main()
{
    println!("cargo:rustc-link-lib=dylib=foo
              cargo:rustc-link-search=native=/path/to/lib");
}

@alexcrichton
Copy link
Member

That's the same, you need to remove the newline and leading whitespace or use two println! statements.

@za121
Copy link
Author

za121 commented Aug 22, 2017

fn main()
{
    println!("cargo:rustc-link-lib=dylib=foo");
    println!("cargo:rustc-link-search=native=/path/to/lib");
}

same error

@cssivision
Copy link

in my case, it seems that if i have both libfoo.so and foo.so in the search path, it compile without error. but i don't know the reason.

@alexcrichton
Copy link
Member

@za121 is /path/to/lib outside the build directory? Any paths outside the build directory are intended to be managed by the application, not by Cargo

@za121
Copy link
Author

za121 commented Aug 25, 2017

At the time of your reply, /path/to/lib was outside of the build directory. I'm curious what I should do to manage that path by the application, but just to see what would happen, I moved the dylib to be inside the same folder hierarchy as the cargo project (/foobar/path/to/lib where main.rs is located at /foobar/src/main.rs), but it didn't fix the problem.

@alexcrichton
Copy link
Member

The "build directory" in this case is the target output folder, and in general you'll need to modify LD_LIBRARY_PATH yourself before calling Cargo.

@carols10cents carols10cents added A-documenting-cargo-itself Area: Cargo's documentation A-linkage Area: linker issues, dylib, cdylib, shared libraries, so C-bug Category: bug labels Aug 27, 2017
@za121
Copy link
Author

za121 commented Aug 30, 2017

LD_LIBRARY_PATH or DYLD_LIBRARY_PATH as it's called on Mac is no longer the approved way to link libraries. It requires turning off System Integrity Protection, which is not really an option for software you want to distribute. RPath is the "one true way" to link libraries today.

@Townsheriff
Copy link

I fought this issue and in my case I needed to add in the build.rs:

println!("cargo:rustc-link-lib=dylib=ndi");
println!("cargo:rustc-link-search=native=/System/Volumes/Data/Library/NDI SDK for Apple/lib/x64");

dynlib in /System/Volumes/Data/Library/NDI SDK for Apple/lib/x64 was called libndi.4.dynlib I renamed it to libndi.dynlib othewise it could not be found.

At this point I was able to compile.

Then I got runtime errors: Library not loaded: @rpath/libndi.4.dylib and to fix that I used install_name_tool -change @rpath/libndi.4.dylib "/System/Volumes/Data/Library/NDI_SDK_COPY/lib/x64/libndi.dylib" target/debug/libgstndi.dylib

And now I have no errors.

I tried all the environment parameters, RUSTFLAGS, nothing worked..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-documenting-cargo-itself Area: Cargo's documentation A-linkage Area: linker issues, dylib, cdylib, shared libraries, so C-bug Category: bug S-triage Status: This issue is waiting on initial triage.
Projects
None yet
Development

No branches or pull requests

6 participants