Skip to content

include_dependency files that are in a different depot from the package are not found during loading #52161

@KristofferC

Description

@KristofferC

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions