Skip to content

Commit 9800437

Browse files
committed
check if cachefile dependencies can be fulfilled
1 parent 96b28d6 commit 9800437

File tree

2 files changed

+65
-14
lines changed

2 files changed

+65
-14
lines changed

base/loading.jl

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,16 @@ function parse_cache_header(f::IO)
699699
push!(files, (String(read(f, n)), ntoh(read(f, Float64))))
700700
end
701701
@assert totbytes == 4 "header of cache file appears to be corrupt"
702-
return modules, files
702+
# read the list of modules that are required to be present during loading
703+
required_modules = Dict{Symbol, UInt64}()
704+
while true
705+
n = ntoh(read(f, Int32))
706+
n == 0 && break
707+
sym = Symbol(read(f, n)) # module symbol
708+
uuid = ntoh(read(f, UInt64)) # module UUID
709+
required_modules[sym] = uuid
710+
end
711+
return modules, files, required_modules
703712
end
704713

705714
function parse_cache_header(cachefile::String)
@@ -713,15 +722,7 @@ function parse_cache_header(cachefile::String)
713722
end
714723

715724
function cache_dependencies(f::IO)
716-
defs, files = parse_cache_header(f)
717-
modules = []
718-
while true
719-
n = ntoh(read(f, Int32))
720-
n == 0 && break
721-
sym = Symbol(read(f, n)) # module symbol
722-
uuid = ntoh(read(f, UInt64)) # module UUID (mostly just a timestamp)
723-
push!(modules, (sym, uuid))
724-
end
725+
defs, files, modules = parse_cache_header(f)
725726
return modules, files
726727
end
727728

@@ -742,7 +743,22 @@ function stale_cachefile(modpath::String, cachefile::String)
742743
DEBUG_LOADING[] && info("JL_DEBUG_LOADING: Rejecting cache file $cachefile due to it containing an invalid cache header.")
743744
return true # invalid cache file
744745
end
745-
modules, files = parse_cache_header(io)
746+
modules, files, required_modules = parse_cache_header(io)
747+
748+
# Check if transitive dependencies can be fullfilled
749+
for mod in keys(required_modules)
750+
if mod == :Main || mod == :Core || mod == :Base
751+
continue
752+
# Module is already loaded
753+
elseif isdefined(Main, mod)
754+
continue
755+
end
756+
name = string(mod)
757+
path = find_in_node_path(name, nothing, 1)
758+
if path === nothing
759+
return true # Won't be able to fullfill dependency
760+
end
761+
end
746762

747763
# check if this file is going to provide one of our concrete dependencies
748764
# or if it provides a version that conflicts with our concrete dependencies

test/compile.jl

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,13 @@ try
184184
@test stringmime("text/plain", Base.Docs.doc(Foo.foo)) == "foo function\n"
185185
@test stringmime("text/plain", Base.Docs.doc(Foo.Bar.bar)) == "bar function\n"
186186

187-
modules, deps = Base.parse_cache_header(cachefile)
187+
modules, deps, required_modules = Base.parse_cache_header(cachefile)
188188
@test modules == Dict(Foo_module => Base.module_uuid(Foo))
189189
@test map(x -> x[1], sort(deps)) == [Foo_file, joinpath(dir, "bar.jl"), joinpath(dir, "foo.jl")]
190190

191191
modules, deps1 = Base.cache_dependencies(cachefile)
192-
@test sort(modules) == Any[(s, Base.module_uuid(getfield(Foo, s))) for s in
193-
[:Base, :Core, Foo2_module, FooBase_module, :Main]]
192+
@test modules == Dict(s => Base.module_uuid(getfield(Foo, s)) for s in
193+
[:Base, :Core, Foo2_module, FooBase_module, :Main])
194194
@test deps == deps1
195195

196196
@test current_task()(0x01, 0x4000, 0x30031234) == 2
@@ -325,6 +325,41 @@ try
325325
isa(exc, ErrorException) || rethrow(exc)
326326
!isempty(search(exc.msg, "ERROR: LoadError: break me")) && rethrow(exc)
327327
end
328+
329+
# Test transitive dependency for #21266
330+
FooBarT_file = joinpath(dir, "FooBarT.jl")
331+
write(FooBarT_file,
332+
"""
333+
__precompile__(true)
334+
module FooBarT
335+
end
336+
""")
337+
FooBarT1_file = joinpath(dir, "FooBarT1.jl")
338+
write(FooBarT1_file,
339+
"""
340+
__precompile__(true)
341+
module FooBarT1
342+
using FooBarT
343+
end
344+
""")
345+
FooBarT2_file = joinpath(dir, "FooBarT2.jl")
346+
write(FooBarT2_file,
347+
"""
348+
__precompile__(true)
349+
module FooBarT2
350+
using FooBarT1
351+
end
352+
""")
353+
Base.compilecache("FooBarT2")
354+
write(FooBarT1_file,
355+
"""
356+
__precompile__(true)
357+
module FooBarT1
358+
end
359+
""")
360+
rm(FooBarT_file)
361+
@test Base.stale_cachefile(FooBarT2_file, joinpath(dir2, "FooBarT2.ji"))
362+
Base.require(:FooBarT2)
328363
finally
329364
splice!(Base.LOAD_CACHE_PATH, 1:2)
330365
splice!(LOAD_PATH, 1)

0 commit comments

Comments
 (0)