Julia packages with Singularity

I just encountered the same problems, and I believe I have found a workable solution.

First of all, to the command to do the procompilation during build is Base.compilecache, which is a bit particular in that it requires a package identifier as argument, so I found that e.g.

Base.compilecache(Base.identify_package("FileIO"))

works to precompile.

That being said, for optimal performance the precompilation should probably happen on the system where the container is running, not on the system the image was build on (think AMD vs Intel, register length, …)
So I found that setting the DEPOT_PATH as follows made it work

%environment
    export JULIA_DEPOT_PATH=$PWD/precompile:/opt/.julia
    export PATH=/opt/julia/bin:$PATH

%post
    export JULIA_DEPOT_PATH=/opt/.julia
    export PATH=/opt/julia/bin:$PATH

This causes all package added during build to go to /opt/julia, but the runtime environment variable is prepended with the folder precompile in the current working directory. This directory is writable, as it is a default bind path. , and will be used first because it was prepended. In addition the packages from build can still be found by julia.
Obviously, any other default or custom bind path would work in the same fashion.
This way, packages can be precompiled, but not added, because the core manifest ist still read-only.

I suppose the alternative would be to set up a persistant overlay, but given that this overlay seems to live in some separate bit of storage on the host I don’t see much of a difference. It might be superior if the code being run needs to change files all over.
However, given that it needs sudo access (for using a directory as overlay), or an extra depdency in dd for the ext3 storage I think its too complicated for me.

The possibly bad side effect is that files now clutter the host, but I think this is actually good, as it means that the necessary precompile files live with the image on the host for repeated runs, and I am probably going to .gitignore them if need be.

Edit:
I just found out that mixing these things is not a great idea. If you precompile one package, this also precompiles all its dependencies (obviously). However, if some other package uses some of the same dependencies, but has not been pre-compiled during build, it will fail during container run. The problem appears to be of permissions, as building happens as root, and as such non-root can’t access the precompilation cache.

2 Likes