Ruby C 库的扩展包装器无法加载已安装的库
Ruby extension wrapper around C library fails to load installed library
Ruby 扩展
davenport-ruby
到 C 库
davenport
将无法在 Ubuntu 和 Debian 上正确加载。它在开发机器 (MacOS) 上工作正常,如冒烟测试 Ruby 项目的自述文件所示,dvt
RubyGems 加载器(通过捆绑器)按如下方式编译和安装扩展:
~/dvt$ rm -rf ~/.bundle
~/dvt$ bundle install
Fetching gem metadata from https://rubygems.org/.
Using bundler 2.0.2
Fetching davenport 1.0.2.pre
Installing davenport 1.0.2.pre with native extensions
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
~/dvt$ bundle info davenport
* davenport (1.0.2.pre)
Summary: Ruby binding for the Davenport library
Homepage: https://github.com/wbreeze/davenport-ruby
Path: /home/deploy/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0\
/gems/davenport-1.0.2.pre
~/dvt$ ls /home/deploy/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0\
/gems/davenport-1.0.2.pre/lib/davenport_ruby/
davenport_ruby.so
~/dvt$
但是尝试 运行 程序会产生:
deploy@localhost:~/dvt$ ruby test.rb
Traceback (most recent call last):
6: from test.rb:1:in `<main>'
5: from /home/deploy/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems\
/core_ext/kernel_require.rb:34:in `require'
...
1: from /home/deploy/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems\
/core_ext/kernel_require.rb:54:in `require':\
libdavenport.so.0: cannot open shared object file: No such file or\
directory - /home/deploy/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0\
/gems/davenport-1.0.2.pre/lib/davenport_ruby/davenport_ruby.so\
(LoadError)
库文件 libdavenport.so.0
存在于 /usr/local/lib
中。使用 ruby -I /usr/local/lib test.rb
制作加载路径的那一部分会产生相同的结果。
库文件 davenport_ruby.so
存在于 /home/deploy/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/davenport-1.0.2.pre/lib/davenport_ruby
中,如下所示:
/home/deploy/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require': libdavenport.so.0: cannot open shared\
object file: No such file or directory - /home/deploy/.rbenv/versions/2.6.3\
/lib/ruby/gems/2.6.0/gems/davenport-1.0.2.pre/lib/davenport_ruby\
/davenport_ruby.so (LoadError)
~/dvt$ ls -l ~/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/\
davenport-1.0.2.pre/lib/davenport_ruby/
total 72
-rwxr-xr-x 1 deploy deploy 69640 Jul 25 17:02 davenport_ruby.so
~/dvt$
Ruby davenport 扩展的已发布 1.0.2.pre
版本来自 this PR,其中 link 显示了所有代码位(以及相当多的实验)。是扩展部分的某些细节还是部分 gem 不太正确?
davenport_ruby.so
.so
文件是安装gem时编译的共享库文件。它不存在于 gem:
的内容中
~/davenport-ruby/dltem[i1]$ gem unpack davenport-1.0.2.pre.gem
Unpacked gem: '/Users/dcl/davenport-ruby/dltem/davenport-1.0.2.pre'
~/davenport-ruby/dltem[i1]$ ls -R
davenport-1.0.2.pre davenport-1.0.2.pre.gem
./davenport-1.0.2.pre:
History.txt README.rdoc Rakefile ext lib
./davenport-1.0.2.pre/ext:
davenport_ruby
./davenport-1.0.2.pre/ext/davenport_ruby:
davenport_ruby.c extconf.rb
./davenport-1.0.2.pre/lib:
davenport.rb
~/davenport-ruby/dltem[i1]$
当 RubyGems 安装 gem 时,它会检测 gem 规范中的 s.extensions << 'ext/davenport_ruby/extconf.rb'
并使用 ruby
执行该文件吗?生成的 make 文件是否 运行 make
?
什么可以使 ruby test.rb
变为 运行 而不会出现错误?
This gist
包含 libdavenport.so.0 和 davenport_ruby.so 中唯一全局符号的比较,以及 gem environment
和 ruby -e 'puts $:.join("\n")'
命令的输出。
ldd
about the not found (LoadError)
problem suggests using ldd
to verify the linking. (There is a related question 没有答案,但在评论中有类似的建议。)
事实上,扩展库虽然是内置的,但不会 link 到已安装的 libdavenport.so.0
:
~/dvt$ bundle install
Fetching gem metadata from https://rubygems.org/.
Using bundler 2.0.2
Fetching davenport 1.0.2.pre
Installing davenport 1.0.2.pre with native extensions
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
~/dvt$ ldd ~/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/davenport-1.0.2.pre/lib/davenport_ruby/davenport_ruby.so
linux-vdso.so.1 (0x00007fff2d3e3000)
libdavenport.so.0 => not found
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9a5be42000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9a5baa3000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9a5c349000)
~/dvt$
ldconfig
This very old question 在 AskUbuntu 上建议使用 ldconfig
命令。由于 libdavenport.so.0
安装在 /usr/local/lib
中,命令是 ldconfig /usr/local/lib
。然而 运行 它需要一个不同的登录名来获得 root 权限。切换回正在安装 Ruby 程序的 deploy
帐户:
~/dvt$ ruby test.rb
Hola
[1, 3, 2, 4]
~/dvt$
瞧。它现在正在工作。问题变成了如何让它与 deploy/install 以及没有 root 权限的用户一起工作。 (安装库 libdavenport
也需要 root 权限,尽管它是从源代码编译和安装的。)
libdavenport.so.0: cannot open shared object file: No such file or\
directory - /home/deploy/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0\
/gems/davenport-1.0.2.pre/lib/davenport_ruby/davenport_ruby.so
此错误意味着本机扩展 davenport_ruby.so
无法加载 Davenport 的共享库 libdavenport.so.0
。您需要使用 ldconfig 或通过将其路径添加到 LD_LIBRARY_PATH
.
来确保共享库位于您的加载路径中
旧的错误答案:
Ruby C 扩展必须针对您 运行 安装它们的平台进行编译。如果您只是下载一些使用扩展的 Ruby 代码,它不会开箱即用。
您是使用 gem
还是 bundle
构建扩展的?您是否 运行 在 Ubuntu 机器上尝试 运行 脚本?
gem 不应包含 .so
。当您安装 gem 时,它应该构建 .so
并将其放在 Ruby 的加载路径中的某个位置,以便脚本可以需要它。
假设您实际安装了 gem 并成功构建了 .so
,我可以想到两个可能的问题
- 您使用错误的工具或选项安装了 gem,因此将
.so
放在了错误的位置
- 你 运行宁 Ruby 的方式不对(你使用的是 rbenv 还是 rvm?)所以它在错误的地方寻找
.so
运行 gem environment
和 ruby -e 'p $:'
将您的 gem 安装目录与 Ruby 的加载路径进行比较。
运行 ldconfig /usr/local/lib
root 原来是答案。它使加载程序能够在 运行 时间找到已安装的 libdavenport.so.0
库。
对于后续问题,答案是 make install
可能无法消除某些系统上 运行 ldconfig
的需要。有一个针对另一个图书馆的旧问题,该图书馆仍然开放,位于
esnet/iperf。他们想不通。如果他们这样做了,他们就不会更新问题。一个较新的问题反对
libcheck/check 也有类似的挣扎。
libtool
的当前 Gnu 文档已在其
implementation issues、
The install Makefile target should warn the package installer to set
the proper environment variables (LD_LIBRARY_PATH or equivalent), or
run ldconfig.
本例中的 "solution" 是 Davenport 库的文档解决方案,
对 README 的更新
this PR.
关于库链接和加载有一个很好的简短解释
Cprogramming.com(这是广告'支持但并不痛苦;这篇文章获得了参考)。
Ruby 扩展 davenport-ruby 到 C 库 davenport 将无法在 Ubuntu 和 Debian 上正确加载。它在开发机器 (MacOS) 上工作正常,如冒烟测试 Ruby 项目的自述文件所示,dvt
RubyGems 加载器(通过捆绑器)按如下方式编译和安装扩展:
~/dvt$ rm -rf ~/.bundle
~/dvt$ bundle install
Fetching gem metadata from https://rubygems.org/.
Using bundler 2.0.2
Fetching davenport 1.0.2.pre
Installing davenport 1.0.2.pre with native extensions
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
~/dvt$ bundle info davenport
* davenport (1.0.2.pre)
Summary: Ruby binding for the Davenport library
Homepage: https://github.com/wbreeze/davenport-ruby
Path: /home/deploy/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0\
/gems/davenport-1.0.2.pre
~/dvt$ ls /home/deploy/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0\
/gems/davenport-1.0.2.pre/lib/davenport_ruby/
davenport_ruby.so
~/dvt$
但是尝试 运行 程序会产生:
deploy@localhost:~/dvt$ ruby test.rb
Traceback (most recent call last):
6: from test.rb:1:in `<main>'
5: from /home/deploy/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems\
/core_ext/kernel_require.rb:34:in `require'
...
1: from /home/deploy/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems\
/core_ext/kernel_require.rb:54:in `require':\
libdavenport.so.0: cannot open shared object file: No such file or\
directory - /home/deploy/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0\
/gems/davenport-1.0.2.pre/lib/davenport_ruby/davenport_ruby.so\
(LoadError)
库文件 libdavenport.so.0
存在于 /usr/local/lib
中。使用 ruby -I /usr/local/lib test.rb
制作加载路径的那一部分会产生相同的结果。
库文件 davenport_ruby.so
存在于 /home/deploy/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/davenport-1.0.2.pre/lib/davenport_ruby
中,如下所示:
/home/deploy/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require': libdavenport.so.0: cannot open shared\
object file: No such file or directory - /home/deploy/.rbenv/versions/2.6.3\
/lib/ruby/gems/2.6.0/gems/davenport-1.0.2.pre/lib/davenport_ruby\
/davenport_ruby.so (LoadError)
~/dvt$ ls -l ~/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/\
davenport-1.0.2.pre/lib/davenport_ruby/
total 72
-rwxr-xr-x 1 deploy deploy 69640 Jul 25 17:02 davenport_ruby.so
~/dvt$
Ruby davenport 扩展的已发布 1.0.2.pre
版本来自 this PR,其中 link 显示了所有代码位(以及相当多的实验)。是扩展部分的某些细节还是部分 gem 不太正确?
davenport_ruby.so
.so
文件是安装gem时编译的共享库文件。它不存在于 gem:
~/davenport-ruby/dltem[i1]$ gem unpack davenport-1.0.2.pre.gem
Unpacked gem: '/Users/dcl/davenport-ruby/dltem/davenport-1.0.2.pre'
~/davenport-ruby/dltem[i1]$ ls -R
davenport-1.0.2.pre davenport-1.0.2.pre.gem
./davenport-1.0.2.pre:
History.txt README.rdoc Rakefile ext lib
./davenport-1.0.2.pre/ext:
davenport_ruby
./davenport-1.0.2.pre/ext/davenport_ruby:
davenport_ruby.c extconf.rb
./davenport-1.0.2.pre/lib:
davenport.rb
~/davenport-ruby/dltem[i1]$
当 RubyGems 安装 gem 时,它会检测 gem 规范中的 s.extensions << 'ext/davenport_ruby/extconf.rb'
并使用 ruby
执行该文件吗?生成的 make 文件是否 运行 make
?
什么可以使 ruby test.rb
变为 运行 而不会出现错误?
This gist
包含 libdavenport.so.0 和 davenport_ruby.so 中唯一全局符号的比较,以及 gem environment
和 ruby -e 'puts $:.join("\n")'
命令的输出。
ldd
not found (LoadError)
problem suggests using ldd
to verify the linking. (There is a related question 没有答案,但在评论中有类似的建议。)
事实上,扩展库虽然是内置的,但不会 link 到已安装的 libdavenport.so.0
:
~/dvt$ bundle install
Fetching gem metadata from https://rubygems.org/.
Using bundler 2.0.2
Fetching davenport 1.0.2.pre
Installing davenport 1.0.2.pre with native extensions
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
~/dvt$ ldd ~/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/davenport-1.0.2.pre/lib/davenport_ruby/davenport_ruby.so
linux-vdso.so.1 (0x00007fff2d3e3000)
libdavenport.so.0 => not found
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9a5be42000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9a5baa3000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9a5c349000)
~/dvt$
ldconfig
This very old question 在 AskUbuntu 上建议使用 ldconfig
命令。由于 libdavenport.so.0
安装在 /usr/local/lib
中,命令是 ldconfig /usr/local/lib
。然而 运行 它需要一个不同的登录名来获得 root 权限。切换回正在安装 Ruby 程序的 deploy
帐户:
~/dvt$ ruby test.rb
Hola
[1, 3, 2, 4]
~/dvt$
瞧。它现在正在工作。问题变成了如何让它与 deploy/install 以及没有 root 权限的用户一起工作。 (安装库 libdavenport
也需要 root 权限,尽管它是从源代码编译和安装的。)
libdavenport.so.0: cannot open shared object file: No such file or\
directory - /home/deploy/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0\
/gems/davenport-1.0.2.pre/lib/davenport_ruby/davenport_ruby.so
此错误意味着本机扩展 davenport_ruby.so
无法加载 Davenport 的共享库 libdavenport.so.0
。您需要使用 ldconfig 或通过将其路径添加到 LD_LIBRARY_PATH
.
旧的错误答案:
Ruby C 扩展必须针对您 运行 安装它们的平台进行编译。如果您只是下载一些使用扩展的 Ruby 代码,它不会开箱即用。
您是使用 gem
还是 bundle
构建扩展的?您是否 运行 在 Ubuntu 机器上尝试 运行 脚本?
gem 不应包含 .so
。当您安装 gem 时,它应该构建 .so
并将其放在 Ruby 的加载路径中的某个位置,以便脚本可以需要它。
假设您实际安装了 gem 并成功构建了 .so
,我可以想到两个可能的问题
- 您使用错误的工具或选项安装了 gem,因此将
.so
放在了错误的位置 - 你 运行宁 Ruby 的方式不对(你使用的是 rbenv 还是 rvm?)所以它在错误的地方寻找
.so
运行 gem environment
和 ruby -e 'p $:'
将您的 gem 安装目录与 Ruby 的加载路径进行比较。
运行 ldconfig /usr/local/lib
root 原来是答案。它使加载程序能够在 运行 时间找到已安装的 libdavenport.so.0
库。
对于后续问题,答案是 make install
可能无法消除某些系统上 运行 ldconfig
的需要。有一个针对另一个图书馆的旧问题,该图书馆仍然开放,位于
esnet/iperf。他们想不通。如果他们这样做了,他们就不会更新问题。一个较新的问题反对
libcheck/check 也有类似的挣扎。
libtool
的当前 Gnu 文档已在其
implementation issues、
The install Makefile target should warn the package installer to set the proper environment variables (LD_LIBRARY_PATH or equivalent), or run ldconfig.
本例中的 "solution" 是 Davenport 库的文档解决方案, 对 README 的更新 this PR.
关于库链接和加载有一个很好的简短解释 Cprogramming.com(这是广告'支持但并不痛苦;这篇文章获得了参考)。