-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Description
This is a MWE from a regression in an internal package. The end goal in that package is to cache some arbitrary piece of code using Julia's precompile system so that code can be loaded again quickly.
To show the issue, let's create a precompiled module (here in a single file) that we want to be invalidated based on some other file changing. This file could potentially be in a package depot (where it probably won't be changed) but we might also have that dependency file be in a devved package where it could be changed and we then want to recompile the module:
# Foo.jl
module Foo
using Example
readmefile = joinpath(pkgdir(Example), "README.md")
@show readmefile
include_dependency(readmefile)
end
Now, let's say we do not want to pollute our standard depot with cache files from this module (and for some reason we also want to store this module file somewhere else) so we do:
new_depot = joinpath(tempdir(), "depot")
mkpath(new_depot)
pushfirst!(DEPOT_PATH, new_depot)
pushfirst!(LOAD_PATH, new_depot)
foofile = joinpath(new_depot, "Foo.jl")
if !isfile(foofile)
cp("Foo.jl", foofile)
end
using Foo
Upon running this we can see the path to the dependency file we injected:
julia> using Foo
┌ Info: Precompiling Foo [top-level]
└ @ Base loading.jl:2442
readmefile = "/Users/kristoffercarlsson/.julia/packages/Example/aqsx3/README.md"```
However, when looking what is actually stored in the precompile file, the path to the README file is different:
cachefile = joinpath(DEPOT_PATH[1], "compiled", "v1.11", "Foo.ji")
io = open(cachefile, "r")
Base.isvalid_cache_header(io)
modules, (includes, _, requires), _ = Base.parse_cache_header(io, cachefile)
includes
julia> includes
2-element Vector{Base.CacheHeaderIncludes}:
Base.CacheHeaderIncludes( [top-level], "/var/folders/tp/2p4x9ygx48sgsdl1ccg1mp_40000gn/T/depot/Foo.jl", 0x0000000000000084, 0xd614849c, -1.0, String[])
Base.CacheHeaderIncludes( [top-level], "/var/folders/tp/2p4x9ygx48sgsdl1ccg1mp_40000gn/T/depot/packages/Example/aqsx3/README.md", 0x0000000000000000, 0x00000000, 1.6745681561065354e9, String[])
The README.md file is stored with the location /var/folders/tp/2p4x9ygx48sgsdl1ccg1mp_40000gn/T/depot/packages/Example/aqsx3/README.md"
which is not the same as what we actually used in the include_dependency
call.
The issue with that is that when we load this module again, it will not find this file and recompile it:
julia> using Foo
┌ Debug: Rejecting stale cache file /var/folders/tp/2p4x9ygx48sgsdl1ccg1mp_40000gn/T/depot/compiled/v1.11/Foo.ji because file /var/folders/tp/2p4x9ygx48sgsdl1ccg1mp_40000gn/T/depot/packages/Example/aqsx3/README.md does not exist
└ @ Base loading.jl:3289
Info: Precompiling Foo [top-level
My guess to what is happening is that after #49866 the precompile system checks all file that are in a depot path and "reifies" them to be the same as that of the package getting loaded. But this fails in cases like this.
It would be good to have some solution to this because this use case is quite useful.
cc @fatteneder