@@ -507,6 +507,8 @@ package root.
507507To get the root directory of the package that implements the current module
508508the form `pkgdir(@__MODULE__)` can be used.
509509
510+ If an extension module is given, the root of the parent package is returned.
511+
510512```julia-repl
511513julia> pkgdir(Foo)
512514"/path/to/Foo.jl"
@@ -524,7 +526,19 @@ function pkgdir(m::Module, paths::String...)
524526 rootmodule = moduleroot (m)
525527 path = pathof (rootmodule)
526528 path === nothing && return nothing
527- return joinpath (dirname (dirname (path)), paths... )
529+ original = path
530+ path, base = splitdir (dirname (path))
531+ if base == " src"
532+ # package source in `../src/Foo.jl`
533+ elseif base == " ext"
534+ # extension source in `../ext/FooExt.jl`
535+ elseif basename (path) == " ext"
536+ # extension source in `../ext/FooExt/FooExt.jl`
537+ path = dirname (path)
538+ else
539+ error (" Unexpected path structure for module source: $original " )
540+ end
541+ return joinpath (path, paths... )
528542end
529543
530544function get_pkgversion_from_path (path)
@@ -1152,7 +1166,7 @@ const TIMING_IMPORTS = Threads.Atomic{Int}(0)
11521166# these return either the array of modules loaded from the path / content given
11531167# or an Exception that describes why it couldn't be loaded
11541168# and it reconnects the Base.Docs.META
1155- function _include_from_serialized (pkg:: PkgId , path:: String , ocachepath:: Union{Nothing, String} , depmods:: Vector{Any} , ignore_native:: Union{Nothing,Bool} = nothing )
1169+ function _include_from_serialized (pkg:: PkgId , path:: String , ocachepath:: Union{Nothing, String} , depmods:: Vector{Any} , ignore_native:: Union{Nothing,Bool} = nothing ; register :: Bool = true )
11561170 if isnothing (ignore_native)
11571171 if JLOptions (). code_coverage == 0 && JLOptions (). malloc_log == 0
11581172 ignore_native = false
@@ -1201,23 +1215,11 @@ function _include_from_serialized(pkg::PkgId, path::String, ocachepath::Union{No
12011215 for M in restored
12021216 M = M:: Module
12031217 if parentmodule (M) === M && PkgId (M) == pkg
1218+ register && register_root_module (M)
12041219 if timing_imports
1205- elapsed = round (( time_ns () - t_before) / 1e6 , digits = 1 )
1220+ elapsed_time = time_ns () - t_before
12061221 comp_time, recomp_time = cumulative_compile_time_ns () .- t_comp_before
1207- print (lpad (elapsed, 9 ), " ms " )
1208- parentid = get (EXT_PRIMED, pkg, nothing )
1209- if parentid != = nothing
1210- print (parentid. name, " → " )
1211- end
1212- print (pkg. name)
1213- if comp_time > 0
1214- printstyled (" " , Ryu. writefixed (Float64 (100 * comp_time / (elapsed * 1e6 )), 2 ), " % compilation time" , color = Base. info_color ())
1215- end
1216- if recomp_time > 0
1217- perc = Float64 (100 * recomp_time / comp_time)
1218- printstyled (" (" , perc < 1 ? " <1" : Ryu. writefixed (perc, 0 ), " % recompilation)" , color = Base. warn_color ())
1219- end
1220- println ()
1222+ print_time_imports_report (M, elapsed_time, comp_time, recomp_time)
12211223 end
12221224 return M
12231225 end
@@ -1229,6 +1231,73 @@ function _include_from_serialized(pkg::PkgId, path::String, ocachepath::Union{No
12291231 end
12301232end
12311233
1234+ # printing functions for @time_imports
1235+ # note that the time inputs are UInt64 on all platforms. Give default values here so that we don't have
1236+ # confusing UInt64 types in generate_precompile.jl
1237+ function print_time_imports_report (
1238+ mod:: Module ,
1239+ elapsed_time:: UInt64 = UInt64 (1 ),
1240+ comp_time:: UInt64 = UInt64 (1 ),
1241+ recomp_time:: UInt64 = UInt64 (1 )
1242+ )
1243+ print (lpad (round (elapsed_time / 1e6 , digits= 1 ), 9 ), " ms " )
1244+ ext_parent = extension_parent_name (mod)
1245+ if ext_parent != = nothing
1246+ print (ext_parent:: String , " → " )
1247+ end
1248+ print (string (mod))
1249+ if comp_time > 0
1250+ perc = Ryu. writefixed (Float64 (100 * comp_time / (elapsed_time)), 2 )
1251+ printstyled (" $perc % compilation time" , color = Base. info_color ())
1252+ end
1253+ if recomp_time > 0
1254+ perc = Float64 (100 * recomp_time / comp_time)
1255+ perc_show = perc < 1 ? " <1" : Ryu. writefixed (perc, 0 )
1256+ printstyled (" ($perc_show % recompilation)" , color = Base. warn_color ())
1257+ end
1258+ println ()
1259+ end
1260+ function print_time_imports_report_init (
1261+ mod:: Module , i:: Int = 1 ,
1262+ elapsed_time:: UInt64 = UInt64 (1 ),
1263+ comp_time:: UInt64 = UInt64 (1 ),
1264+ recomp_time:: UInt64 = UInt64 (1 )
1265+ )
1266+ connector = i > 1 ? " ├" : " ┌"
1267+ printstyled (" $connector " , color = :light_black )
1268+ print (" $(round (elapsed_time / 1e6 , digits= 1 )) ms $mod .__init__() " )
1269+ if comp_time > 0
1270+ perc = Ryu. writefixed (Float64 (100 * (comp_time) / elapsed_time), 2 )
1271+ printstyled (" $perc % compilation time" , color = Base. info_color ())
1272+ end
1273+ if recomp_time > 0
1274+ perc = Float64 (100 * recomp_time / comp_time)
1275+ printstyled (" ($(perc < 1 ? " <1" : Ryu. writefixed (perc, 0 )) % recompilation)" , color = Base. warn_color ())
1276+ end
1277+ println ()
1278+ end
1279+
1280+ # if M is an extension, return the string name of the parent. Otherwise return nothing
1281+ function extension_parent_name (M:: Module )
1282+ rootmodule = moduleroot (M)
1283+ src_path = pathof (rootmodule)
1284+ src_path === nothing && return nothing
1285+ pkgdir_parts = splitpath (src_path)
1286+ ext_pos = findlast (== (" ext" ), pkgdir_parts)
1287+ if ext_pos != = nothing && ext_pos >= length (pkgdir_parts) - 2
1288+ parent_package_root = joinpath (pkgdir_parts[1 : ext_pos- 1 ]. .. )
1289+ parent_package_project_file = locate_project_file (parent_package_root)
1290+ if parent_package_project_file isa String
1291+ d = parsed_toml (parent_package_project_file)
1292+ name = get (d, " name" , nothing )
1293+ if name != = nothing
1294+ return name
1295+ end
1296+ end
1297+ end
1298+ return nothing
1299+ end
1300+
12321301function register_restored_modules (sv:: SimpleVector , pkg:: PkgId , path:: String )
12331302 # This function is also used by PkgCacheInspector.jl
12341303 restored = sv[1 ]:: Vector{Any}
@@ -1265,31 +1334,18 @@ function run_module_init(mod::Module, i::Int=1)
12651334 # `i` informs ordering for the `@time_imports` report formatting
12661335 if TIMING_IMPORTS[] == 0
12671336 ccall (:jl_init_restored_module , Cvoid, (Any,), mod)
1268- else
1269- if isdefined (mod, :__init__ )
1270- connector = i > 1 ? " ├" : " ┌"
1271- printstyled (" $connector " , color = :light_black )
1272-
1273- elapsedtime = time_ns ()
1274- cumulative_compile_timing (true )
1275- compile_elapsedtimes = cumulative_compile_time_ns ()
1337+ elseif isdefined (mod, :__init__ )
1338+ elapsed_time = time_ns ()
1339+ cumulative_compile_timing (true )
1340+ compile_elapsedtimes = cumulative_compile_time_ns ()
12761341
1277- ccall (:jl_init_restored_module , Cvoid, (Any,), mod)
1342+ ccall (:jl_init_restored_module , Cvoid, (Any,), mod)
12781343
1279- elapsedtime = ( time_ns () - elapsedtime) / 1e6
1280- cumulative_compile_timing (false );
1281- comp_time, recomp_time = ( cumulative_compile_time_ns () .- compile_elapsedtimes) ./ 1e6
1344+ elapsed_time = time_ns () - elapsed_time
1345+ cumulative_compile_timing (false );
1346+ comp_time, recomp_time = cumulative_compile_time_ns () .- compile_elapsedtimes
12821347
1283- print (" $(round (elapsedtime, digits= 1 )) ms $mod .__init__() " )
1284- if comp_time > 0
1285- printstyled (Ryu. writefixed (Float64 (100 * comp_time / elapsedtime), 2 ), " % compilation time" , color = Base. info_color ())
1286- end
1287- if recomp_time > 0
1288- perc = Float64 (100 * recomp_time / comp_time)
1289- printstyled (" ($(perc < 1 ? " <1" : Ryu. writefixed (perc, 0 )) % recompilation)" , color = Base. warn_color ())
1290- end
1291- println ()
1292- end
1348+ print_time_imports_report_init (mod, i, elapsed_time, comp_time, recomp_time)
12931349 end
12941350end
12951351
@@ -1403,7 +1459,7 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}
14031459 triggers = triggers:: Union{String, Vector{String}}
14041460 triggers isa String && (triggers = [triggers])
14051461 id = PkgId (uuid5 (parent. uuid:: UUID , ext), ext)
1406- if id in keys (EXT_PRIMED) || haskey (Base. loaded_modules, id)
1462+ if haskey (EXT_PRIMED, id ) || haskey (Base. loaded_modules, id)
14071463 continue # extension is already primed or loaded, don't add it again
14081464 end
14091465 EXT_PRIMED[id] = parent
@@ -1833,8 +1889,7 @@ function _tryrequire_from_serialized(pkg::PkgId, path::String, ocachepath::Union
18331889 depmods[i] = dep
18341890 end
18351891 # then load the file
1836- loaded = _include_from_serialized (pkg, path, ocachepath, depmods, ignore_native)
1837- loaded isa Module && register_root_module (loaded)
1892+ loaded = _include_from_serialized (pkg, path, ocachepath, depmods, ignore_native; register = true )
18381893 return loaded
18391894end
18401895
@@ -1901,8 +1956,7 @@ end
19011956 if dep === nothing
19021957 try
19031958 set_pkgorigin_version_path (modkey, modpath)
1904- dep = _include_from_serialized (modkey, modcachepath, modocachepath, modstaledeps)
1905- dep isa Module && stalecheck && register_root_module (dep)
1959+ dep = _include_from_serialized (modkey, modcachepath, modocachepath, modstaledeps; register = stalecheck)
19061960 finally
19071961 end_loading (modkey, dep)
19081962 end
@@ -1918,9 +1972,8 @@ end
19181972 end
19191973 restored = get (loaded_precompiles, pkg => newbuild_id, nothing )
19201974 if ! isa (restored, Module)
1921- restored = _include_from_serialized (pkg, path_to_try, ocachefile, staledeps)
1975+ restored = _include_from_serialized (pkg, path_to_try, ocachefile, staledeps; register = stalecheck )
19221976 end
1923- isa (restored, Module) && stalecheck && register_root_module (restored)
19241977 isa (restored, Module) && return restored
19251978 @debug " Deserialization checks failed while attempting to load cache from $path_to_try " exception= restored
19261979 @label check_next_path
0 commit comments