我正在尝试用OCRA打包以下Ruby脚本(我在Windows 10,Ruby 2.6上(:
require 'sqlite3'
puts SQLite3::VERSION
在cmd中运行它可以正常工作:
C:UsersmondayDocumentsprojectssqlite3_test>script.rb
1.4.2
当我按以下方式打包script.rb
:
ocra --gem-full=sqlite3 --dll sqlite3.dll script.rb --output script.exe --verbose
我已经根据 SO 和 GitHub 上的各种建议将sqlite3.dll
和sqlite3.def
添加到我的PATH
和C:Ruby26-x64bin
中。
这是我运行生成的script.exe
时弹出的错误:
C:UsersmondayDocumentsprojectssqlite3_test>script.exe
Traceback (most recent call last):
2: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/src/script.rb:1:in `<main>'
1: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- sqlite3 (LoadError)
6: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/src/script.rb:1:in `<main>'
5: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:34:in `require'
4: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:130:in `rescue in require'
3: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:130:in `require'
2: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3.rb:4:in `<top (required)>'
1: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- sqlite3/2.6/sqlite3_native (LoadError)
7: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/src/script.rb:1:in `<main>'
6: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:34:in `require'
5: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:130:in `rescue in require'
4: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:130:in `require'
3: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3.rb:2:in `<top (required)>'
2: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3.rb:6:in `rescue in <top (required)>'
1: from C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require': 126: The specified module could not be found. - C:/Users/monday/AppData/Local/Temp/ocr7747.tmp/lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/sqlite3_native.so (LoadError)
我确定临时文件夹中存在lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/sqlite3_native.so
,从 OCRA 的输出来看:
...
m lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib
a lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3.rb
m lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3
a lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/constants.rb
a lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb
a lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/errors.rb
a lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/pragmas.rb
a lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb
a lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/sqlite3_native.so <<< HERE!
a lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/statement.rb
a lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/translator.rb
a lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/value.rb
a lib/ruby/gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/version.rb
...
我错过了什么?
经过一些研究,我发现错误消息The specified module could not be found.
意味着该程序可能缺少所需的DLL。现在sqlite3_native.so
存在,我假定是该程序缺少DLL。 在其上运行dumpbin
给出了以下结果:
C:Program Files (x86)Microsoft Visual Studio2019Community>dumpbin /dependents C:Ruby26-x64librubygems2.6.0gemssqlite3-1.4.2libsqlite3sqlite3_native.so
Microsoft (R) COFF/PE Dumper Version 14.22.27905.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:Ruby26-x64librubygems2.6.0gemssqlite3-1.4.2libsqlite3sqlite3_native.so
File Type: DLL
Image has the following dependencies:
x64-msvcrt-ruby260.dll
KERNEL32.dll
msvcrt.dll
libsqlite3-0.dll
...
显然,OCRA从未检测到libsqlite3-0.dll
,因此从未移动到临时文件夹的bin/
目录中。快速搜索显示libsqlite3-0.dll
确实存在于我的机器上C:Ruby26-x64msys64mingw64bin
.我将其移至C:Ruby26-x64bin
,并使用以下选项运行OCRA:
ocra --dll libsqlite3-0.dll script.rb --output script.exe
后来,我意识到 OCRA 现在能够自行检测此 DLL:
=== Adding ruby executable ruby.exe
=== Adding detected DLL C:/Ruby26-x64/bin/ruby_builtin_dlls/libgmp-10.dll
=== Adding detected DLL C:/Ruby26-x64/bin/ruby_builtin_dlls/libffi-6.dll
=== Adding detected DLL C:/Ruby26-x64/bin/libsqlite3-0.dll <<<< HERE!
=== Adding detected DLL C:/Ruby26-x64/bin/ruby_builtin_dlls/libgcc_s_seh-1.dll
=== Adding detected DLL C:/Ruby26-x64/bin/ruby_builtin_dlls/libwinpthread-1.dll
=== Adding detected DLL C:/Ruby26-x64/bin/ruby_builtin_dlls/zlib1.dll
=== Adding detected DLL C:/Ruby26-x64/bin/ruby_builtin_dlls/libssl-1_1-x64.dll
=== Adding detected DLL C:/Ruby26-x64/bin/ruby_builtin_dlls/libcrypto-1_1-x64.dll
=== Adding external manifest C:/Ruby26-x64/bin/ruby_builtin_dlls/ruby_builtin_dlls.manifest
所以,最后:
ocra script.rb --output script.exe
工作正常,无需sqlite3.dll
.
这似乎是一个相当通用的解决方案,因为我能够通过将所需的 DLL 添加到 Ruby 安装的bin/
文件夹中,使 puma 从 OCRA 打包的脚本中运行。