Skip to content

Commit 4a7b1d1

Browse files
authored
[release-1.11] Prevent pre-compilation package from triggering its own extensions (#56666) (#56676)
It is possible for an extension `ExtAB` to be loadable by one of its triggers, e.g. if `A` loads `B`. However, this loading is not supposed to happen during pre-compilation of `A`. Getting this wrong means disagreeing with the scheduled pre-compile jobs (`A` is not scheduled to depend on or generate a cache file for `ExtAB` but accidentally attempts both) and leads to confusing errors about missing cache files. We used to cover up this bad behavior w/ an erroneous cycle warning (fixed by #55910), but now we need to be sure this works.
1 parent 5ef1884 commit 4a7b1d1

File tree

8 files changed

+87
-1
lines changed

8 files changed

+87
-1
lines changed

Diff for: base/loading.jl

+4-1
Original file line numberDiff line numberDiff line change
@@ -1392,6 +1392,7 @@ function run_module_init(mod::Module, i::Int=1)
13921392
end
13931393

13941394
function run_package_callbacks(modkey::PkgId)
1395+
(modkey == precompilation_target) && return nothing
13951396
run_extension_callbacks(modkey)
13961397
assert_havelock(require_lock)
13971398
unlock(require_lock)
@@ -1521,7 +1522,7 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}
15211522
uuid_trigger = UUID(totaldeps[trigger]::String)
15221523
trigger_id = PkgId(uuid_trigger, trigger)
15231524
push!(trigger_ids, trigger_id)
1524-
if !haskey(Base.loaded_modules, trigger_id) || haskey(package_locks, trigger_id)
1525+
if !haskey(Base.loaded_modules, trigger_id) || haskey(package_locks, trigger_id) || (trigger_id == precompilation_target)
15251526
trigger1 = get!(Vector{ExtensionId}, EXT_DORMITORY, trigger_id)
15261527
push!(trigger1, gid)
15271528
else
@@ -1534,6 +1535,7 @@ end
15341535
loading_extension::Bool = false
15351536
loadable_extensions::Union{Nothing,Vector{PkgId}} = nothing
15361537
precompiling_extension::Bool = false
1538+
precompilation_target::Union{Nothing,PkgId} = nothing
15371539
function run_extension_callbacks(extid::ExtensionId)
15381540
assert_havelock(require_lock)
15391541
succeeded = try
@@ -2967,6 +2969,7 @@ function create_expr_cache(pkg::PkgId, input::String, output::String, output_o::
29672969
Base.track_nested_precomp($(_pkg_str(vcat(Base.precompilation_stack, pkg))))
29682970
Base.loadable_extensions = $(_pkg_str(loadable_exts))
29692971
Base.precompiling_extension = $(loading_extension)
2972+
Base.precompilation_target = $(_pkg_str(pkg))
29702973
Base.include_package_for_output($(_pkg_str(pkg)), $(repr(abspath(input))), $(repr(depot_path)), $(repr(dl_load_path)),
29712974
$(repr(load_path)), $(_pkg_str(concrete_deps)), $(repr(source_path(nothing))))
29722975
""")

Diff for: test/loading.jl

+34
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,40 @@ end
12091209
@test occursin("Hello x-package ext-to-ext!", String(read(cmd)))
12101210
end
12111211

1212+
# Extensions for "parent" dependencies
1213+
# (i.e. an `ExtAB` where A depends on / loads B, but B provides the extension)
1214+
1215+
mktempdir() do depot # Parallel pre-compilation
1216+
code = """
1217+
Base.disable_parallel_precompile = false
1218+
using Parent
1219+
Base.get_extension(getfield(Parent, :DepWithParentExt), :ParentExt) isa Module || error("expected extension to load")
1220+
Parent.greet()
1221+
"""
1222+
proj = joinpath(@__DIR__, "project", "Extensions", "Parent.jl")
1223+
cmd = `$(Base.julia_cmd()) --startup-file=no -e $code`
1224+
cmd = addenv(cmd,
1225+
"JULIA_LOAD_PATH" => proj,
1226+
"JULIA_DEPOT_PATH" => depot * Base.Filesystem.pathsep(),
1227+
)
1228+
@test occursin("Hello parent!", String(read(cmd)))
1229+
end
1230+
mktempdir() do depot # Serial pre-compilation
1231+
code = """
1232+
Base.disable_parallel_precompile = true
1233+
using Parent
1234+
Base.get_extension(getfield(Parent, :DepWithParentExt), :ParentExt) isa Module || error("expected extension to load")
1235+
Parent.greet()
1236+
"""
1237+
proj = joinpath(@__DIR__, "project", "Extensions", "Parent.jl")
1238+
cmd = `$(Base.julia_cmd()) --startup-file=no -e $code`
1239+
cmd = addenv(cmd,
1240+
"JULIA_LOAD_PATH" => proj,
1241+
"JULIA_DEPOT_PATH" => depot * Base.Filesystem.pathsep(),
1242+
)
1243+
@test occursin("Hello parent!", String(read(cmd)))
1244+
end
1245+
12121246
finally
12131247
try
12141248
rm(depot_path, force=true, recursive=true)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name = "DepWithParentExt"
2+
uuid = "8a35c396-5ffc-40d2-b7ec-e8ed2248da32"
3+
version = "0.1.0"
4+
5+
[weakdeps]
6+
Parent = "58cecb9c-f68a-426e-b92a-89d456ae7acc"
7+
8+
[extensions]
9+
ParentExt = "Parent"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module ParentExt
2+
3+
using Parent
4+
using DepWithParentExt
5+
6+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module DepWithParentExt
2+
3+
greet() = print("Hello dep w/ ext for parent dep!")
4+
5+
end # module DepWithParentExt

Diff for: test/project/Extensions/Parent.jl/Manifest.toml

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# This file is machine-generated - editing it directly is not advised
2+
3+
julia_version = "1.11.1"
4+
manifest_format = "2.0"
5+
project_hash = "5d72c155f50f076d28b74de819d417878ffb0965"
6+
7+
[[deps.DepWithParentExt]]
8+
path = "../DepWithParentExt.jl"
9+
uuid = "8a35c396-5ffc-40d2-b7ec-e8ed2248da32"
10+
version = "0.1.0"
11+
12+
[deps.DepWithParentExt.extensions]
13+
ParentExt = "Parent"
14+
15+
[deps.DepWithParentExt.weakdeps]
16+
Parent = "58cecb9c-f68a-426e-b92a-89d456ae7acc"

Diff for: test/project/Extensions/Parent.jl/Project.toml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
name = "Parent"
2+
uuid = "58cecb9c-f68a-426e-b92a-89d456ae7acc"
3+
version = "0.1.0"
4+
5+
[deps]
6+
DepWithParentExt = "8a35c396-5ffc-40d2-b7ec-e8ed2248da32"

Diff for: test/project/Extensions/Parent.jl/src/Parent.jl

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Parent
2+
3+
using DepWithParentExt
4+
5+
greet() = print("Hello parent!")
6+
7+
end # module Parent

0 commit comments

Comments
 (0)