Julia什么时候才能出好用的编译exe包?(或者已经有了?)

随便编一个小程序,虽然运行快,但编译要时间,又不能编译成exe,只要退出Julia,再用还得重新编译,太耗时了。用PackageCompiler不能直接编译,得改程序,还要注意路径。建议出专门的编译exe扩展包,分需要依赖库和不需要依赖库两种方式编译,前者体积大,但是可以独立运行,后者体积小,但必须在安装Julia机子上才能运行。

令人哭笑不得的还有这种方式:用Python对其进行包装,然后将其转换为EXE:利用PyInstaller将Julia文件转换为EXE文件-腾讯云开发者社区-腾讯云

目前来看还是只有 PackageCompiler 最靠谱,虽然用起来非常麻烦。

但这里其实有两个问题混在一起了:

  1. 降低 julia 的启动延迟
  2. 打包 julia 应用

1 的坑是最大的,只能等编译器的改进、更多的预编译、更多的(预编译)缓存。
但如果放弃一些运行时的性能,少做预编译/优化应该能降低一些启动延迟。可以改改 --optimize= 试试

2 会稍微好解决一些。像 PackageCompiler 用起来麻烦,可以另开一个包,提供用户友好的接口,这样对于一些简单的脚本就不用新建项目了。
另外 python 的打包有一种也是直接打包一个 python 的解释器,运行时解压出来然后运行脚本。
julia 也可以仿照这种办法,但这只解决打包的问题,对于启动延迟并没有太多帮助。


最后回答一下标题"是么时候"能有好用的包。
我去英文社区搜了一下 exe / build exe 2022 年的帖子基本就搜不到。说明有需求的人不多,那社区做这个的动力也就不大。对应的讨论编译延迟的帖子感觉是月月都有。

所以感觉短期内很难有好用的包。
实在用着不爽,可以自己动手丰衣足食。也为社区做一些贡献。
毕竟有需求才有做改进的动力。

1 个赞

好吧,我用PackageCompiler把常用的几个包预编译了一下并加入内核,速度可以接受。但是又出问题了,我把PyPlot编译进内核:

using PackageCompiler, DataFrames, PyPlot
create_sysimage(["DataFrames","PyPlot"],sysimage_path="sys_Data_PyPlot.so")

然后设置启动时调用这个内核:

Julia --sysimage "sys_Data_PyPlot.so"

但是进入后出问题了:

julia> using PyPlot

这步很快

julia> plot([1,2],[3,4])

┌ Warning: `vendor()` is deprecated, use `BLAS.get_config()` and inspect the output instead
│   caller = npyinitialize() at numpy.jl:67
└ @ PyCall C:\Users\linlin\.julia\packages\PyCall\L0fLP\src\numpy.jl:67
1-element Vector{PyCall.PyObject}:
 PyObject <matplotlib.lines.Line2D object at 0x0000000056CFE4F0>

但是不出图像,要plt.show()才显示,而且不再显示提示符。

如果用Julia普通进入:

julia> using PyPlot

julia> plot([1,2],[3,4])
┌ Warning: `vendor()` is deprecated, use `BLAS.get_config()` and inspect the output instead
│   caller = npyinitialize() at numpy.jl:67
└ @ PyCall C:\Users\linlin\.julia\packages\PyCall\L0fLP\src\numpy.jl:67
1-element Vector{PyCall.PyObject}:
 PyObject <matplotlib.lines.Line2D object at 0x0000000062F9D6A0>

可以正常显示图像,这是为什么?

1 个赞

我遇到过类似这个问题,猜测是预编译和Python Matplotlib的后端调用放在一起时某些地方出了问题,但是我并没有仔细分析。
PackageCompiler not working with PyPlot · Issue #31 · henry2004y/Vlasiator.jl (github.com)

具体到你说需要plt.show()才能出图,刚好我最近稍微研究了一下为什么一般命令行下面直接用Python都需要这条命令显示图像,而在像Jupyter Notebook和IPython下面不需要。除了Matplotlib中本身对应的两个方法plt.ion(), plt.ioff()以外,还需要一个叫event loop的东西,并且针对不同的后端还会不太一样:https://github.com/JuliaPy/PyPlot.jl/blob/c4b0c566d1da3c08342b3f7d8d3aa14709c698bb/src/init.jl#L215
注意这个event loop是在interactive mode下面(即REPL中)import package阶段创建的,我怀疑就是这里有问题。

如果你感兴趣具体是为什么,可以去PyPlot.jl下面提Issue。

最近有一个新注册的包StaticTools.jl提供了将部分Julia代码编译成可执行文件的功能。这个包目前仅支持Julia 1.8 beta版本。它依赖于 StaticCompiler.jl,是另一个限制更多的包。StaticCompiler.jl原作者给了很详细的例子
Successful Static Compilation of Julia Code for use in Production - General Usage - JuliaLang

所以离这个目标已经越来越近了。然而目前从可见的例子来看,能编译成二进制文件的代码基本上写的和C差不多了。从语言的角度,这倒是一个很好的机会来理解Julia和C之间的差别;然而从实用的角度来说还远远不够。

期待各位能有朝一日为实现这一目标添砖加瓦。

2 个赞