Skip to content

Commit

Permalink
check if cachefile dependencies can be fulfilled (#21492)
Browse files Browse the repository at this point in the history
  • Loading branch information
vchuravy authored and tkelman committed Apr 24, 2017
1 parent e0c497b commit 36bb61a
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 14 deletions.
38 changes: 27 additions & 11 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,16 @@ function parse_cache_header(f::IO)
push!(files, (String(read(f, n)), ntoh(read(f, Float64))))
end
@assert totbytes == 4 "header of cache file appears to be corrupt"
return modules, files
# read the list of modules that are required to be present during loading
required_modules = Dict{Symbol,UInt64}()
while true
n = ntoh(read(f, Int32))
n == 0 && break
sym = Symbol(read(f, n)) # module symbol
uuid = ntoh(read(f, UInt64)) # module UUID
required_modules[sym] = uuid
end
return modules, files, required_modules
end

function parse_cache_header(cachefile::String)
Expand All @@ -713,15 +722,7 @@ function parse_cache_header(cachefile::String)
end

function cache_dependencies(f::IO)
defs, files = parse_cache_header(f)
modules = []
while true
n = ntoh(read(f, Int32))
n == 0 && break
sym = Symbol(read(f, n)) # module symbol
uuid = ntoh(read(f, UInt64)) # module UUID (mostly just a timestamp)
push!(modules, (sym, uuid))
end
defs, files, modules = parse_cache_header(f)
return modules, files
end

Expand All @@ -742,7 +743,22 @@ function stale_cachefile(modpath::String, cachefile::String)
DEBUG_LOADING[] && info("JL_DEBUG_LOADING: Rejecting cache file $cachefile due to it containing an invalid cache header.")
return true # invalid cache file
end
modules, files = parse_cache_header(io)
modules, files, required_modules = parse_cache_header(io)

# Check if transitive dependencies can be fullfilled
for mod in keys(required_modules)
if mod == :Main || mod == :Core || mod == :Base
continue
# Module is already loaded
elseif isdefined(Main, mod)
continue
end
name = string(mod)
path = find_in_node_path(name, nothing, 1)
if path === nothing
return true # Won't be able to fullfill dependency
end
end

# check if this file is going to provide one of our concrete dependencies
# or if it provides a version that conflicts with our concrete dependencies
Expand Down
41 changes: 38 additions & 3 deletions test/compile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,13 @@ try
@test stringmime("text/plain", Base.Docs.doc(Foo.foo)) == "foo function\n"
@test stringmime("text/plain", Base.Docs.doc(Foo.Bar.bar)) == "bar function\n"

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

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

@test current_task()(0x01, 0x4000, 0x30031234) == 2
Expand Down Expand Up @@ -325,6 +325,41 @@ try
isa(exc, ErrorException) || rethrow(exc)
!isempty(search(exc.msg, "ERROR: LoadError: break me")) && rethrow(exc)
end

# Test transitive dependency for #21266
FooBarT_file = joinpath(dir, "FooBarT.jl")
write(FooBarT_file,
"""
__precompile__(true)
module FooBarT
end
""")
FooBarT1_file = joinpath(dir, "FooBarT1.jl")
write(FooBarT1_file,
"""
__precompile__(true)
module FooBarT1
using FooBarT
end
""")
FooBarT2_file = joinpath(dir, "FooBarT2.jl")
write(FooBarT2_file,
"""
__precompile__(true)
module FooBarT2
using FooBarT1
end
""")
Base.compilecache("FooBarT2")
write(FooBarT1_file,
"""
__precompile__(true)
module FooBarT1
end
""")
rm(FooBarT_file)
@test Base.stale_cachefile(FooBarT2_file, joinpath(dir2, "FooBarT2.ji"))
@test Base.require(:FooBarT2) === nothing
finally
splice!(Base.LOAD_CACHE_PATH, 1:2)
splice!(LOAD_PATH, 1)
Expand Down

0 comments on commit 36bb61a

Please sign in to comment.