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

how to link shared library in compiling #28

Closed
HiroiImanishi opened this issue Dec 3, 2019 · 6 comments
Closed

how to link shared library in compiling #28

HiroiImanishi opened this issue Dec 3, 2019 · 6 comments

Comments

@HiroiImanishi
Copy link

Excuse me, I have a question.

When $ mix compile, I would like to link shared library(.so).
For example, I'd like to add "-L project_root/c_src/example/c_libs -ltest" to command to make.
├── _build
├── c_src
│ └── example
│ ├── c_libs
│ │ └─libtest.so
│ ├── _generated
│ ├example.spec.exs
│ ├example.c
│ └ example.h
├── bundlex.exs
├── deps
├── lib
└── test

I tried to edit bundlex.exs as follows:

defmodule Example.BundlexProject do
  use Bundlex.Project

  def project() do
    [
      nifs: nifs(Bundlex.platform())
    ]
  end

  def nifs(_platform) do
    [
      example: [
        deps: [unifex: :unifex],
        src_base: "example",
        sources: ["_generated/example.c","example.c"],
        lib_dirs: ["c_libs"],  #<---
        libs:    ["test"]  #<---
      ]
    ]
  end
end

in result, I had a error
/usr/bin/ld: cannot find -ltest
collect2: error: ld returned 1 exit status
...

What is missing in this setting?

@mat-hek
Copy link
Member

mat-hek commented Dec 3, 2019

Hi @HiroiImanishi , paths in lib_dirs should be absolute, not relative to c_src. Path.join(__DIR__, "c_src/c_libs") should help.

@HiroiImanishi
Copy link
Author

Hi @mat-hek , thank you for comment.
I could build natives.
but, when I do $ iex -S mix, I have this error.

22:06:06.736 [error] Process #PID<0.208.0> raised an exception
** (RuntimeError) Bundlex cannot load nif "example" of app :unifex_proto
from "/home/imanishi/mix_proj/unifex_proto/_build/dev/lib/unifex_proto/priv/bundlex/example", check bundlex.exs file for information about nifs.
Reason: :load_failed, Failed to load NIF library /home/imanishi/mix_proj/unifex_proto/_build/dev/lib/unifex_proto/priv/bundlex/example: 
'libtest.so: cannot open shared object file: No such file or directory'

    (unifex_proto) lib/runmodule.ex:1: Example.Native.Nif.load_nif/0
    (kernel) code_server.erl:1340: anonymous fn/1 in :code_server.handle_on_load/5
** (UndefinedFunctionError) function Example.Native.Nif.unifex_add/2 is undefined (module Example.Native.Nif is not available)
    (unifex_proto) Example.Native.Nif.unifex_add(2, 5)
iex(1)> 
22:06:06.743 [warn]  The on_load function for module Elixir.Example.Native.Nif returned:
{%RuntimeError{message: "Bundlex cannot load nif \"example\" of app 
:unifex_proto\nfrom \"/home/imanishi/mix_proj/unifex_proto/_build/dev/lib/unifex_proto/priv/bundlex/example\", 
check bundlex.exs file for information about nifs.\nReason: :load_failed, 
Failed to load NIF library /home/imanishi/mix_proj/unifex_proto/_build/dev/lib/unifex_proto/priv/bundlex/example:
 'libtest.so: cannot open shared object file: No such file or directory'\n"}, 
[{Example.Native.Nif, :load_nif, 0, [file: 'lib/runmodule.ex', line: 1]}, {:code_server, :"-handle_on_load/5-fun-0-", 1, [file: 'code_server.erl', line: 1340]}]}

Why isn't NIF library be loaded ?
I'll be happy if I get advice. My project is as follows.
https://github.com/HiroiImanishi/elixir_mix/tree/master/unifex_proto

@mat-hek
Copy link
Member

mat-hek commented Dec 3, 2019

Your lib_dirs specification is still invalid. You have [__DIR__, "c_src/example/c_libs"], while there should be [Path.join(__DIR__, "c_src/example/c_libs")].

@HiroiImanishi
Copy link
Author

Sorry for my omission,
I've already built the project according to your comment "there should be [Path.join(__DIR__...]", but the result is same.

@mat-hek
Copy link
Member

mat-hek commented Dec 4, 2019

Ok, I think I see your actual problem - you link a shared library, that is loaded in runtime by the OS, which assumes such libraries are located in specific places, as described e.g. here. You should either place your library there or use a statically-linked library (.a or .o) instead. However, note that mix's working directory is no longer going to be the project root directory once somebody uses your project as a dependency, so placing a .so there or using relative paths in lib_dirs is rather not a good idea.

@HiroiImanishi
Copy link
Author

Hi, @mat-hek. Actually, I thought that there was no problem just linking libraries "-L" option. I understood what is the reason of this error. I tried to edit LD_LIBRARY_PATH to add the absolute path where a.so exists, and I checked program successes to run, but I have to think a better way.
Thank you so much for a detailed answer!!

@mat-hek mat-hek closed this as completed Dec 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants