@@ -733,8 +733,9 @@ function manifest_uuid_path(env::String, pkg::PkgId)::Union{Nothing,String,Missi
733733 proj = implicit_manifest_uuid_path (env, pkg)
734734 proj === nothing || return proj
735735 # if not found
736- parentid = get (EXT_PRIMED, pkg, nothing )
737- if parentid != = nothing
736+ triggers = get (EXT_PRIMED, pkg, nothing )
737+ if triggers != = nothing
738+ parentid = triggers[1 ]
738739 _, parent_project_file = entry_point_and_project_file (env, parentid. name)
739740 if parent_project_file != = nothing
740741 parentproj = project_file_name_uuid (parent_project_file, parentid. name)
@@ -1387,9 +1388,7 @@ function run_module_init(mod::Module, i::Int=1)
13871388end
13881389
13891390function run_package_callbacks (modkey:: PkgId )
1390- if ! precompiling_extension
1391- run_extension_callbacks (modkey)
1392- end
1391+ run_extension_callbacks (modkey)
13931392 assert_havelock (require_lock)
13941393 unlock (require_lock)
13951394 try
@@ -1418,7 +1417,7 @@ mutable struct ExtensionId
14181417 ntriggers:: Int # how many more packages must be defined until this is loaded
14191418end
14201419
1421- const EXT_PRIMED = Dict {PkgId, PkgId} () # Extension -> Parent
1420+ const EXT_PRIMED = Dict {PkgId,Vector{ PkgId}} () # Extension -> Parent + Triggers (parent is always first)
14221421const EXT_DORMITORY = Dict {PkgId,Vector{ExtensionId}} () # Trigger -> Extensions that can be triggered by it
14231422const EXT_DORMITORY_FAILED = ExtensionId[]
14241423
@@ -1509,14 +1508,15 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}
15091508 if haskey (EXT_PRIMED, id) || haskey (Base. loaded_modules, id)
15101509 continue # extension is already primed or loaded, don't add it again
15111510 end
1512- EXT_PRIMED[id] = parent
1511+ EXT_PRIMED[id] = trigger_ids = PkgId[ parent]
15131512 gid = ExtensionId (id, parent, 1 + length (triggers), 1 + length (triggers))
15141513 trigger1 = get! (Vector{ExtensionId}, EXT_DORMITORY, parent)
15151514 push! (trigger1, gid)
15161515 for trigger in triggers
15171516 # TODO : Better error message if this lookup fails?
15181517 uuid_trigger = UUID (totaldeps[trigger]:: String )
15191518 trigger_id = PkgId (uuid_trigger, trigger)
1519+ push! (trigger_ids, trigger_id)
15201520 if ! haskey (explicit_loaded_modules, trigger_id) || haskey (package_locks, trigger_id)
15211521 trigger1 = get! (Vector{ExtensionId}, EXT_DORMITORY, trigger_id)
15221522 push! (trigger1, gid)
@@ -1528,6 +1528,7 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}
15281528end
15291529
15301530loading_extension:: Bool = false
1531+ loadable_extensions:: Union{Nothing,Vector{PkgId}} = nothing
15311532precompiling_extension:: Bool = false
15321533function run_extension_callbacks (extid:: ExtensionId )
15331534 assert_havelock (require_lock)
@@ -1558,7 +1559,7 @@ function run_extension_callbacks(pkgid::PkgId)
15581559 for extid in extids
15591560 @assert extid. ntriggers > 0
15601561 extid. ntriggers -= 1
1561- if extid. ntriggers == 0
1562+ if extid. ntriggers == 0 && (loadable_extensions === nothing || extid . id in loadable_extensions)
15621563 push! (extids_to_load, extid)
15631564 end
15641565 end
@@ -2542,7 +2543,17 @@ function _require(pkg::PkgId, env=nothing)
25422543 # double-check the search now that we have lock
25432544 m = _require_search_from_serialized (pkg, path, UInt128 (0 ), true )
25442545 m isa Module && return m
2545- return compilecache (pkg, path; reasons)
2546+ triggers = get (EXT_PRIMED, pkg, nothing )
2547+ loadable_exts = nothing
2548+ if triggers != = nothing # extension
2549+ loadable_exts = PkgId[]
2550+ for (ext′, triggers′) in EXT_PRIMED
2551+ if triggers′ ⊊ triggers
2552+ push! (loadable_exts, ext′)
2553+ end
2554+ end
2555+ end
2556+ return compilecache (pkg, path; reasons, loadable_exts)
25462557 end
25472558 loaded isa Module && return loaded
25482559 if isnothing (loaded) # maybe_cachefile_lock returns nothing if it had to wait for another process
@@ -2865,19 +2876,26 @@ function check_package_module_loaded(pkg::PkgId)
28652876 return nothing
28662877end
28672878
2879+ # protects against PkgId and UUID being imported and losing Base prefix
2880+ _pkg_str (_pkg:: PkgId ) = (_pkg. uuid === nothing ) ? " Base.PkgId($(repr (_pkg. name)) )" : " Base.PkgId(Base.UUID(\" $(_pkg. uuid) \" ), $(repr (_pkg. name)) )"
2881+ _pkg_str (_pkg:: Vector ) = sprint (show, eltype (_pkg); context = :module => nothing ) * " [" * join (map (_pkg_str, _pkg), " ," ) * " ]"
2882+ _pkg_str (_pkg:: Pair{PkgId} ) = _pkg_str (_pkg. first) * " => " * repr (_pkg. second)
2883+ _pkg_str (_pkg:: Nothing ) = " nothing"
2884+
28682885const PRECOMPILE_TRACE_COMPILE = Ref {String} ()
28692886function create_expr_cache (pkg:: PkgId , input:: String , output:: String , output_o:: Union{Nothing, String} ,
28702887 concrete_deps:: typeof (_concrete_dependencies), flags:: Cmd = ` ` , cacheflags:: CacheFlags = CacheFlags (),
2871- internal_stderr:: IO = stderr , internal_stdout:: IO = stdout , isext :: Bool = false )
2888+ internal_stderr:: IO = stderr , internal_stdout:: IO = stdout , loadable_exts :: Union{Vector{PkgId},Nothing} = nothing )
28722889 @nospecialize internal_stderr internal_stdout
28732890 rm (output, force= true ) # Remove file if it exists
28742891 output_o === nothing || rm (output_o, force= true )
28752892 depot_path = map (abspath, DEPOT_PATH )
28762893 dl_load_path = map (abspath, DL_LOAD_PATH)
28772894 load_path = map (abspath, Base. load_path ())
28782895 # if pkg is a stdlib, append its parent Project.toml to the load path
2879- parentid = get (EXT_PRIMED, pkg, nothing )
2880- if parentid != = nothing
2896+ triggers = get (EXT_PRIMED, pkg, nothing )
2897+ if triggers != = nothing
2898+ parentid = triggers[1 ]
28812899 for env in load_path
28822900 project_file = env_project_file (env)
28832901 if project_file === true
@@ -2895,22 +2913,6 @@ function create_expr_cache(pkg::PkgId, input::String, output::String, output_o::
28952913 any (path -> path_sep in path, load_path) &&
28962914 error (" LOAD_PATH entries cannot contain $(repr (path_sep)) " )
28972915
2898- deps_strs = String[]
2899- # protects against PkgId and UUID being imported and losing Base prefix
2900- function pkg_str (_pkg:: PkgId )
2901- if _pkg. uuid === nothing
2902- " Base.PkgId($(repr (_pkg. name)) )"
2903- else
2904- " Base.PkgId(Base.UUID(\" $(_pkg. uuid) \" ), $(repr (_pkg. name)) )"
2905- end
2906- end
2907- for (pkg, build_id) in concrete_deps
2908- push! (deps_strs, " $(pkg_str (pkg)) => $(repr (build_id)) " )
2909- end
2910- deps_eltype = sprint (show, eltype (concrete_deps); context = :module => nothing )
2911- deps = deps_eltype * " [" * join (deps_strs, " ," ) * " ]"
2912- precomp_stack = " Base.PkgId[$(join (map (pkg_str, vcat (Base. precompilation_stack, pkg)), " , " )) ]"
2913-
29142916 if output_o === nothing
29152917 # remove options that make no difference given the other cache options
29162918 cacheflags = CacheFlags (cacheflags, opt_level= 0 )
@@ -2941,10 +2943,11 @@ function create_expr_cache(pkg::PkgId, input::String, output::String, output_o::
29412943 # write data over stdin to avoid the (unlikely) case of exceeding max command line size
29422944 write (io. in, """
29432945 empty!(Base.EXT_DORMITORY) # If we have a custom sysimage with `EXT_DORMITORY` prepopulated
2944- Base.track_nested_precomp($precomp_stack )
2945- Base.precompiling_extension = $(loading_extension | isext)
2946- Base.include_package_for_output($(pkg_str (pkg)) , $(repr (abspath (input))) , $(repr (depot_path)) , $(repr (dl_load_path)) ,
2947- $(repr (load_path)) , $deps , $(repr (source_path (nothing ))) )
2946+ Base.track_nested_precomp($(_pkg_str (vcat (Base. precompilation_stack, pkg))) )
2947+ Base.loadable_extensions = $(_pkg_str (loadable_exts))
2948+ Base.precompiling_extension = $(loading_extension)
2949+ Base.include_package_for_output($(_pkg_str (pkg)) , $(repr (abspath (input))) , $(repr (depot_path)) , $(repr (dl_load_path)) ,
2950+ $(repr (load_path)) , $(_pkg_str (concrete_deps)) , $(repr (source_path (nothing ))) )
29482951 """ )
29492952 close (io. in)
29502953 return io
@@ -2999,18 +3002,18 @@ This can be used to reduce package load times. Cache files are stored in
29993002`DEPOT_PATH[1]/compiled`. See [Module initialization and precompilation](@ref)
30003003for important notes.
30013004"""
3002- function compilecache (pkg:: PkgId , internal_stderr:: IO = stderr , internal_stdout:: IO = stdout ; flags:: Cmd = ` ` , reasons:: Union{Dict{String,Int},Nothing} = Dict {String,Int} (), isext :: Bool = false )
3005+ function compilecache (pkg:: PkgId , internal_stderr:: IO = stderr , internal_stdout:: IO = stdout ; flags:: Cmd = ` ` , reasons:: Union{Dict{String,Int},Nothing} = Dict {String,Int} (), loadable_exts :: Union{Vector{PkgId},Nothing} = nothing )
30033006 @nospecialize internal_stderr internal_stdout
30043007 path = locate_package (pkg)
30053008 path === nothing && throw (ArgumentError (" $(repr (" text/plain" , pkg)) not found during precompilation" ))
3006- return compilecache (pkg, path, internal_stderr, internal_stdout; flags, reasons, isext )
3009+ return compilecache (pkg, path, internal_stderr, internal_stdout; flags, reasons, loadable_exts )
30073010end
30083011
30093012const MAX_NUM_PRECOMPILE_FILES = Ref (10 )
30103013
30113014function compilecache (pkg:: PkgId , path:: String , internal_stderr:: IO = stderr , internal_stdout:: IO = stdout ,
30123015 keep_loaded_modules:: Bool = true ; flags:: Cmd = ` ` , cacheflags:: CacheFlags = CacheFlags (),
3013- reasons:: Union{Dict{String,Int},Nothing} = Dict {String,Int} (), isext :: Bool = false )
3016+ reasons:: Union{Dict{String,Int},Nothing} = Dict {String,Int} (), loadable_exts :: Union{Vector{PkgId},Nothing} = nothing )
30143017
30153018 @nospecialize internal_stderr internal_stdout
30163019 # decide where to put the resulting cache file
@@ -3050,7 +3053,7 @@ function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, in
30503053 close (tmpio_o)
30513054 close (tmpio_so)
30523055 end
3053- p = create_expr_cache (pkg, path, tmppath, tmppath_o, concrete_deps, flags, cacheflags, internal_stderr, internal_stdout, isext )
3056+ p = create_expr_cache (pkg, path, tmppath, tmppath_o, concrete_deps, flags, cacheflags, internal_stderr, internal_stdout, loadable_exts )
30543057
30553058 if success (p)
30563059 if cache_objects
0 commit comments