Julia 应用程序的编译版本在运行时出现 MethodError,否则运行良好
MethodError at runtime for compiled version of a Julia application that otherwise runs fine
我有一个运行良好的 Julia 应用程序,但我想制作一个已编译且更易于分发的版本。据我了解,这是 PackageCompiler
.
的工作
我能够构建可执行文件,并且在询问它 --help
时它运行良好,但是当我想要它做一些实际工作(处理数据)时,在一些初始信息输出之后,它崩溃并显示以下错误消息:
fatal: error thrown and no exception handler available.
MethodError(f=typeof(Base.convert)(), args=(Int32, nothing), world=0x00000000000065d9)
rec_backtrace at /home/bli/src/julia/src/stackwalk.c:94
record_backtrace at /home/bli/src/julia/src/task.c:219 [inlined]
jl_throw at /home/bli/src/julia/src/task.c:429
jl_method_error_bare at /home/bli/src/julia/src/gf.c:1606
jl_method_error at /home/bli/src/julia/src/gf.c:1624
jl_apply_generic at /home/bli/src/julia/src/gf.c:2161
julia_main at /home/bli/src/qaf_demux/Julia/QafDemux/bin/qaf_demux_to_compile.jl:12
julia_main at /home/bli/src/qaf_demux/Julia/QafDemux/deps/builddir/qaf_demux.so (unknown line)
main at ./deps/builddir/qaf_demux (unknown line)
__libc_start_main at /build/glibc-LK5gWL/glibc-2.23/csu/../csu/libc-start.c:291
_start at ./deps/builddir/qaf_demux (unknown line)
这个MethodError
是什么意思?我可以从回溯中得到什么有用的信息?
这是用于编译它的 deps/build.jl
脚本:
import Pkg
Pkg.add("ArgParse")
Pkg.add("IterTools")
Pkg.add("FASTX")
Pkg.add("CodecZlib")
Pkg.add("REPL")
Pkg.add("PackageCompiler")
using PackageCompiler
build_executable(joinpath(@__DIR__, "../bin/qaf_demux_to_compile.jl"), "qaf_demux", snoopfile=joinpath(@__DIR__, "../bin/snoop.jl"))
snoop.jl
使用一些测试命令行调用我的 QafDemux
包的主要功能(对应于用于测试已编译可执行文件的命令行):
#!/usr/bin/env julia
push!(LOAD_PATH, abspath(joinpath(@__DIR__, "../src/")))
import QafDemux
const qd = QafDemux
test_args = "-i ../../test_data/TCR_ampli_R1_50k.fastq.gz -o test_run -b GCAGAGATAAGC GCAGAGATGCAC GCAGAGACTCAG GCAGAGAGGAAT GCAGAGACGAGG GCAGAGAAGGAG GCAGAGATGTTG GCAGAGACAACT GCAGAGAGGCTA GCAGAGAGAATG GCAGAGACCAAC GCAGAGAGAGAC -s 3 -m 2 -p 0.1"
qd.main(split(test_args))
qaf_demux_to_compile.jl
,根据PackageCompiler
说明,如下:
#!/usr/bin/env julia
push!(LOAD_PATH, abspath(joinpath(@__DIR__, "../src/")))
import QafDemux
const qd = QafDemux
Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
qd.main()
end
未编译版本,运行良好,几乎相同:
#!/usr/bin/env julia
push!(LOAD_PATH, abspath(joinpath(@__DIR__, "../src/")))
import QafDemux
const qd = QafDemux
qd.main()
(在 https://discourse.julialang.org/t/understanding-runtime-errors-with-packagecompiler-built-executables/29120/2 调查的较早阶段交叉发布)
编辑:工作解决方案
根据@Anshul Singvi的建议,我修改了我的QafDemux
模块的主要功能,现在它return是一个整数,并且使用是这样的也是传递给PackageCompiler.build_executable
.
的代码中julia_main
函数的return值
bin/qaf_demux_to_compile.jl
:
#!/usr/bin/env julia
push!(LOAD_PATH, abspath(joinpath(@__DIR__, "../src/")))
import QafDemux
const qd = QafDemux
Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
return qd.main()
end
(我还必须更改 main 函数,以便它接受可选的命令行,否则 snoopfile 实际上是错误的)。
查看堆栈跟踪,您可以看到 Julia 正在尝试将 nothing
转换为 Int32
,在行中:
MethodError(f=typeof(Base.convert)(), args=(Int32, nothing), world=0x00000000000065d9)
这是因为您的 julia_main
函数没有明确地 return 任何东西,而且 qd.main
似乎也没有 return 任何东西。在没有明确的 return 值的情况下,Julia 默认 return 什么都不做。
但是,在您的方法的类型约定中,指定 julia_main
必须 return 一个 Cint
,这在您的系统上似乎成为 Int32
。因此,Julia 试图将 julia_main
(隐含地)return 转换为 Int32
——这是不可能的!
要解决此问题,您只需确保 return 是一个整数。更好的做法是:
Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
try
qd.main()
catch e
print(stderr, e) # print the error to standard error
return 1 # in command line tools, a return value of 1 means error
finally
return 0 # similarly, a return value of 0 means that the program ran properly
end
end
我有一个运行良好的 Julia 应用程序,但我想制作一个已编译且更易于分发的版本。据我了解,这是 PackageCompiler
.
我能够构建可执行文件,并且在询问它 --help
时它运行良好,但是当我想要它做一些实际工作(处理数据)时,在一些初始信息输出之后,它崩溃并显示以下错误消息:
fatal: error thrown and no exception handler available.
MethodError(f=typeof(Base.convert)(), args=(Int32, nothing), world=0x00000000000065d9)
rec_backtrace at /home/bli/src/julia/src/stackwalk.c:94
record_backtrace at /home/bli/src/julia/src/task.c:219 [inlined]
jl_throw at /home/bli/src/julia/src/task.c:429
jl_method_error_bare at /home/bli/src/julia/src/gf.c:1606
jl_method_error at /home/bli/src/julia/src/gf.c:1624
jl_apply_generic at /home/bli/src/julia/src/gf.c:2161
julia_main at /home/bli/src/qaf_demux/Julia/QafDemux/bin/qaf_demux_to_compile.jl:12
julia_main at /home/bli/src/qaf_demux/Julia/QafDemux/deps/builddir/qaf_demux.so (unknown line)
main at ./deps/builddir/qaf_demux (unknown line)
__libc_start_main at /build/glibc-LK5gWL/glibc-2.23/csu/../csu/libc-start.c:291
_start at ./deps/builddir/qaf_demux (unknown line)
这个MethodError
是什么意思?我可以从回溯中得到什么有用的信息?
这是用于编译它的 deps/build.jl
脚本:
import Pkg
Pkg.add("ArgParse")
Pkg.add("IterTools")
Pkg.add("FASTX")
Pkg.add("CodecZlib")
Pkg.add("REPL")
Pkg.add("PackageCompiler")
using PackageCompiler
build_executable(joinpath(@__DIR__, "../bin/qaf_demux_to_compile.jl"), "qaf_demux", snoopfile=joinpath(@__DIR__, "../bin/snoop.jl"))
snoop.jl
使用一些测试命令行调用我的 QafDemux
包的主要功能(对应于用于测试已编译可执行文件的命令行):
#!/usr/bin/env julia
push!(LOAD_PATH, abspath(joinpath(@__DIR__, "../src/")))
import QafDemux
const qd = QafDemux
test_args = "-i ../../test_data/TCR_ampli_R1_50k.fastq.gz -o test_run -b GCAGAGATAAGC GCAGAGATGCAC GCAGAGACTCAG GCAGAGAGGAAT GCAGAGACGAGG GCAGAGAAGGAG GCAGAGATGTTG GCAGAGACAACT GCAGAGAGGCTA GCAGAGAGAATG GCAGAGACCAAC GCAGAGAGAGAC -s 3 -m 2 -p 0.1"
qd.main(split(test_args))
qaf_demux_to_compile.jl
,根据PackageCompiler
说明,如下:
#!/usr/bin/env julia
push!(LOAD_PATH, abspath(joinpath(@__DIR__, "../src/")))
import QafDemux
const qd = QafDemux
Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
qd.main()
end
未编译版本,运行良好,几乎相同:
#!/usr/bin/env julia
push!(LOAD_PATH, abspath(joinpath(@__DIR__, "../src/")))
import QafDemux
const qd = QafDemux
qd.main()
(在 https://discourse.julialang.org/t/understanding-runtime-errors-with-packagecompiler-built-executables/29120/2 调查的较早阶段交叉发布)
编辑:工作解决方案
根据@Anshul Singvi的建议,我修改了我的QafDemux
模块的主要功能,现在它return是一个整数,并且使用是这样的也是传递给PackageCompiler.build_executable
.
julia_main
函数的return值
bin/qaf_demux_to_compile.jl
:
#!/usr/bin/env julia
push!(LOAD_PATH, abspath(joinpath(@__DIR__, "../src/")))
import QafDemux
const qd = QafDemux
Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
return qd.main()
end
(我还必须更改 main 函数,以便它接受可选的命令行,否则 snoopfile 实际上是错误的)。
查看堆栈跟踪,您可以看到 Julia 正在尝试将 nothing
转换为 Int32
,在行中:
MethodError(f=typeof(Base.convert)(), args=(Int32, nothing), world=0x00000000000065d9)
这是因为您的 julia_main
函数没有明确地 return 任何东西,而且 qd.main
似乎也没有 return 任何东西。在没有明确的 return 值的情况下,Julia 默认 return 什么都不做。
但是,在您的方法的类型约定中,指定 julia_main
必须 return 一个 Cint
,这在您的系统上似乎成为 Int32
。因此,Julia 试图将 julia_main
(隐含地)return 转换为 Int32
——这是不可能的!
要解决此问题,您只需确保 return 是一个整数。更好的做法是:
Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
try
qd.main()
catch e
print(stderr, e) # print the error to standard error
return 1 # in command line tools, a return value of 1 means error
finally
return 0 # similarly, a return value of 0 means that the program ran properly
end
end