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

Fails to load native library for OS X #5

Open
define-private-public opened this issue Mar 13, 2020 · 10 comments
Open

Fails to load native library for OS X #5

define-private-public opened this issue Mar 13, 2020 · 10 comments
Labels
bug

Comments

@define-private-public
Copy link

define-private-public commented Mar 13, 2020

This is from my Bassoon project. Everything is working 100% for Windows and Linux. The PortAudioSharp portion is working fine on OS X , but the libsndfileSharp isn't loading the native libsndfile.dylib DLL when trying to run a program. libsndfile.dylib depends on a few other native libraries (e.g. libogg.dylib, libFLAC.dylib, etc). I'm wondering if that's the problem.

Using the FileInfo sample in my repo (which uses libsndfileSharp). I first tried a dotnet run with DYLD_LIBRARY_PATH set to where I compiled out the *.dylib files. And everything worked fine. But then using the NuGet package version (v.0.2), it reported Unable to load shared library 'sndfile' or one of its dependencies. I set DY_PRINT_LIBRARIES=1 and it reported this:

dyld: loaded: /Users/ben/.nuget/packages/libsndfilesharp/0.2.0/lib/netstandard2.0/libsndfile.dylib
dyld: unloaded: /Users/ben/.nuget/packages/libsndfilesharp/0.2.0/lib/netstandard2.0/libsndfile.dylib

At least one of those other native deps should show up after the loaded part, but none of them did.

libsndfileSharp csproj: https://gitlab.com/define-private-public/Bassoon/-/blob/release_nuget_packaging/src/Bassoon/libsndfileSharp/libsndfileSharp.csproj#L37

@define-private-public
Copy link
Author

define-private-public commented Mar 13, 2020

I just tried setting export DYLD_LIBRARY_PATH=/Users/ben/.nuget/packages/libsndfilesharp/0.2.0/lib/netstandard2.0 before doing the dotnet run. I noticed that the extracted .dylib files were found in there. It worked.

I'm wondering if this may just be some path issue.

@olegtarasov
Copy link
Owner

olegtarasov commented May 17, 2020

Hi @define-private-public!

Sorry for such a late reply. I've just pushed version 1.0.19 to Nuget. Library manager now adds the path to which native dependencies are being extracted to DYLD_LIBRARY_PATH under MacOs. Please check if this version solves your problem without specifying DYLD_LIBRARY_PATH manually before dotnet run. If so, I will add similar handlers for Linux and Windows.

@olegtarasov olegtarasov added the question label May 17, 2020
@define-private-public
Copy link
Author

define-private-public commented May 20, 2020

Sorry for the late response. I have this on my TODO within the next days. Thanks!

@olegtarasov
Copy link
Owner

olegtarasov commented May 24, 2020

So I did some testing and it seems that modifying library search path is the way to go. I've pushed v. 1.0.21, where library search path modification is on by default on all platforms, and explicit library loading is off. Automated tests now run on every build and show that this approach works consistently on all three platforms.

I'm closing this issue for now, but feel free to reopen it if v. 1.0.21 doesn't solve your problem.

@olegtarasov olegtarasov added bug and removed question labels May 24, 2020
@olegtarasov
Copy link
Owner

olegtarasov commented May 24, 2020

Orrrrr not :) Seems that variable modification doesn't work all the time, need to poke around some more.

@olegtarasov olegtarasov reopened this May 24, 2020
@olegtarasov
Copy link
Owner

olegtarasov commented May 24, 2020

OK, so here's what I've found. Changing variables such as DYLD_LIBRARY_PATH at runtime is completely useless, since they are taken into account only at process startup, and then any change to them is ignored. That's why it worked when you set this variable before calling dotnet.

The only reliable way of successfully using [DllImport] seems to involve extracting dependencies to process' current directory.

Explicit library loading also works, but only on Windows and Linux, but not MacOs 🤦.

As for your problem, extracting dependencies to current directory instead of assembly's location might help in your particular case. Please update nuget package to v. 1.0.22 and let me know if it solves your problem. You don't need to change anything in your code, but you might want to remove this constructor argument in your code (it just doesn't do anything now): https://gitlab.com/define-private-public/Bassoon/-/blob/release_nuget_packaging/src/Bassoon/libsndfileSharp/libsndfileSharp.cs#L36.

@define-private-public
Copy link
Author

define-private-public commented Jun 15, 2020

Hi, Sorry for responding to this 3 weeks late (been preoccupied).

I took this for a test drive and things do seem to be working on OS X now with my Bassoon package (e.g. if you look at the sample Jukebox app, and have it pull from NuGet with the latest package of Bassoon instead of using a local project reference).

Though, on Linux and OS X, I couldn't simply run dotnet run anymore in the directory where my projects .csproj lives. I had to do "LD_LIBRARY_PATH=pwd dotnet run" and "DYLD_LIBRARY_PATH=pwd dotnet run" respectively. This is a minor inconvenience, but at least it's working on OS X now. An ideal would be not have to manually specify the library path, but that could be taken care of with telling any users (for the moment at least) to wrap their dotnet run commands in a shell script.

I still want to double check things on Windows. Thanks again for your work on this project. I still find it easier to follow than some of the other solutions for doing multi-platform native libraries..

@define-private-public
Copy link
Author

define-private-public commented Jun 17, 2020

I took the new version out for a test run on Window as well. Doing a dotnet run work fine without having to specify any extra path stuff. Both in the windows console and an MSYS2 environment.

An ideal for OS X and Linux would not having to specify the library path (and not populating the running directory with the native DLLs), but I'll take this for now since it works with minimal adjustment. If you want to close this ticket, I don't have any more need for it. I'm willing to help you test this library further.

@jclaessens97
Copy link

jclaessens97 commented Aug 26, 2020

Hi guys, any update on this? I just started to use this library because we're using 3 different environments. Linux for our server, myself for development on osx and the rest of my team to develop on Windows. I'm trying to set it up but like stated in this issue it doesn't seem to work for osx.

I'm not sure what the solution is for now? I set my env vars to the following:

image

But I still get this error:

image

Thanks!

@RobertoMachorro
Copy link

RobertoMachorro commented Jul 18, 2021

I find myself in the same situation. The native library depends on a few Boost (C++) dylibs and doesn't find them unless I set the DYLD path prior to launching. Instead of using _ DYLD_LIBRARY_PATH_, I'm using DYLD_FALLBACK_LIBRARY_PATH, as it is "safer". Setting up the following in code, doesn't work:

Environment.SetEnvironmentVariable("DYLD_FALLBACK_LIBRARY_PATH", ".");

I'm hoping for a more elegant solution that launching with env vars. Using NativeLibraryManager v1.0.23

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug
Projects
None yet
Development

No branches or pull requests

4 participants