lucidstack / ex-portmidi

Elixir bindings to the portmidi library
MIT License
34 stars 12 forks source link

Problem adding ex-portmidi to a project #1

Closed jimm closed 8 years ago

jimm commented 8 years ago

I can download and compile ex-portmidi fine, and use it in iex. Now I'm trying to use it in a new project. I added it to the mix.exs file as described in the README and run mix deps.get. When I try running mix deps.compile I see the following error messages. What am I doing wrong?

ruby ~/src/github/sysex$ mix deps.compile
==> portmidi
make: Nothing to be done for `all'.
Compiled lib/portmidi/input.ex
Compiled lib/portmidi/device.ex
Compiled lib/mix/tasks/portmidi.devices.ex

== Compilation error on file lib/portmidi/nifs/devices.ex ==
** (MatchError) no match of right hand side value: {:error, :on_load_failure}
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6

08:55:54.870 [warn]  The on_load function for module Elixir.PortMidi.Nifs.Devices returned {:error,
 {:load_failed,
  'Failed to load NIF library: \'dlopen(/Users/jim.menard/src/github/sysex/_build/dev/lib/portmidi/priv/portmidi_devices.so, 2): Library not loaded: /usr/local/opt/portmidi/lib/libportmidi.dylib\n  Referenced from: /Users/jim.menard/src/github/sysex/_build/dev/lib/portmidi/priv/portmidi_devices.so\n  Reason: image not found\''}}

could not compile dependency :portmidi, "mix compile" failed. You can recompile this dependency with "mix deps.compile portmidi", update it with "mix deps.update portmidi" or clean it with "mix deps.clean portmidi"

08:55:54.871 [error] Process #PID<0.155.0> raised an exception
** (MatchError) no match of right hand side value: {:error, {:load_failed, 'Failed to load NIF library: \'dlopen(/Users/jim.menard/src/github/sysex/_build/dev/lib/portmidi/priv/portmidi_in.so, 2): Library not loaded: /usr/local/opt/portmidi/lib/libportmidi.dylib\n  Referenced from: /Users/jim.menard/src/github/sysex/_build/dev/lib/portmidi/priv/portmidi_in.so\n  Reason: image not found\''}}
    lib/portmidi/nifs/input.ex:4: PortMidi.Nifs.Input.init/0
    (kernel) code_server.erl:1669: anonymous fn/1 in :code_server.handle_on_load/4

08:55:54.872 [warn]  The on_load function for module Elixir.PortMidi.Nifs.Input returned {{:badmatch,
  {:error,
   {:load_failed,
    'Failed to load NIF library: \'dlopen(/Users/jim.menard/src/github/sysex/_build/dev/lib/portmidi/priv/portmidi_in.so, 2): Library not loaded: /usr/local/opt/portmidi/lib/libportmidi.dylib\n  Referenced from: /Users/jim.menard/src/github/sysex/_build/dev/lib/portmidi/priv/portmidi_in.so\n  Reason: image not found\''}}},
 [{PortMidi.Nifs.Input, :init, 0,
   [file: 'lib/portmidi/nifs/input.ex', line: 4]},
  {:code_server, :"-handle_on_load/4-fun-0-", 1,
   [file: 'code_server.erl', line: 1669]}]}

The file portmidi_in.so exists. Here is a listing of deps/portmidi/priv:

ruby ~/src/github/sysex$ ll deps/portmidi/priv
total 96
-rwxr-xr-x  1 jim.menard  staff  10568 May 29 08:55 portmidi_devices.so
drwxr-xr-x  3 jim.menard  staff    102 May 29 08:55 portmidi_devices.so.dSYM
-rwxr-xr-x  1 jim.menard  staff  11672 May 29 08:55 portmidi_in.so
drwxr-xr-x  3 jim.menard  staff    102 May 29 08:55 portmidi_in.so.dSYM
-rwxr-xr-x  1 jim.menard  staff  11664 May 29 08:55 portmidi_out.so
drwxr-xr-x  3 jim.menard  staff    102 May 29 08:55 portmidi_out.so.dSYM
-rwxr-xr-x  1 jim.menard  staff   9276 May 29 08:55 portmidi_shared.so
drwxr-xr-x  3 jim.menard  staff    102 May 29 08:55 portmidi_shared.so.dSYM

I'm on Mac OSX. I installed portmidi via MacPorts.

If there is a better place for me to be asking for help about this, please let me know. Thank you for creating ex-portmidi.

jimm commented 8 years ago

The only thing I had to do to get ex-portmidi to compile and run with the MacPorts version of portmidi was define the CPATH and LIBRARY_PATH environment variables:

export CPATH="/opt/local/include"
export LIBRARY_PATH="/opt/local/lib"

Here's proof that I have no problem with running ex-portmidi itself:

ruby [master] ~/src/misc/ex-portmidi$ iex -S mix
Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false]

make: Nothing to be done for `all'.
Interactive Elixir (1.2.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> PortMidi.devices
%{input: [%PortMidi.Device{input: 1, interf: "CoreMIDI",
    name: "IAC Driver Bus 1", opened: 0, output: 0}],
  output: [%PortMidi.Device{input: 0, interf: "CoreMIDI",
    name: "IAC Driver Bus 1", opened: 0, output: 1}]}

If you need any more information, please let me know.

lucidstack commented 8 years ago

Thank you for reporting this issue, and trying out the ex-portmidi, @jimm! I believe that your last comment shines some light on what the issue might be.

In the compilation error message, Library not loaded: /usr/local/opt/portmidi/lib/libportmidi.dylib seems to indicate that elixir is somehow ignoring your LIBRARY_PATH, which I believe contains the libportmidi libraries. As it is a dynamic library, it might be switching to the LD_LIBRARY_PATH variable, and eventually falling back to /usr/local/opt/portmidi/lib/, which doesn't have the needed library.

Could you try exporting the LD_LIBRARY_PATH environment variable to the same path, /opt/local/lib, and retry the compilation? Sorry if this is far off the actual solution, I have never been a user of MacPorts and I'm not too accustomed to compilation issues.

jimm commented 8 years ago

Great catch! I tried setting both LD_LIBRARY_PATH and DYLD_LIBRARY_PATH to /opt/local/lib but got the same error message. https://github.com/oracle/node-oracledb/issues/231 implies that DYLD_LIBRARY_PATH might be ignored until I switch off something called System Integrity Protection, but I haven't tried that yet. I may give that a try (http://www.macworld.com/article/2986118/security/how-to-modify-system-integrity-protection-in-el-capitan.html) when I am able but that looks like a bit of a pain.

Here's a simple solution that works: link the portmidi lib files into /usr/local/lib. I'm not happy with having to do that, but c'est la vie.

$ cd /usr/local/lib
$ sudo ln -s /opt/local/lib/libportmidi.dylib .
$ sudo ln -s /opt/local/lib/libportmidi_s.a .

After doing that, I can compile and run my Elixir project and use PortMidi. Yay! Now to write the app!

How did you compile/install portmidi? I downloaded it a few weeks ago it but I couldn't get it to compile. I just tried downloading the source again and my attempt to compile it it failed miserably. I don't expect you to help with this problem, just letting you know.

Thank you again for your help.

lucidstack commented 8 years ago

Nice, glad that worked out!

I honestly haven't tried compiling portmidi; just installed it via homebrew, and it worked out of the box. Sorry I can't be more helpful!

Anyway, thanks again for using the library, and don't hesitate to open new issues/contact me if you find problems or have suggestions for improvements. 😃