@@ -1350,7 +1350,9 @@ function run_module_init(mod::Module, i::Int=1)
1350
1350
end
1351
1351
1352
1352
function run_package_callbacks (modkey:: PkgId )
1353
- run_extension_callbacks (modkey)
1353
+ if ! precompiling_extension
1354
+ run_extension_callbacks (modkey)
1355
+ end
1354
1356
assert_havelock (require_lock)
1355
1357
unlock (require_lock)
1356
1358
try
@@ -1405,13 +1407,12 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi
1405
1407
proj_pkg = project_file_name_uuid (implicit_project_file, pkg. name)
1406
1408
if pkg == proj_pkg
1407
1409
d_proj = parsed_toml (implicit_project_file)
1408
- weakdeps = get (d_proj, " weakdeps" , nothing ):: Union{Nothing, Vector{String}, Dict{String,Any}}
1409
1410
extensions = get (d_proj, " extensions" , nothing ):: Union{Nothing, Dict{String, Any}}
1410
1411
extensions === nothing && return
1411
- weakdeps === nothing && return
1412
- if weakdeps isa Dict{String, Any}
1413
- return _insert_extension_triggers (pkg, extensions, weakdeps )
1414
- end
1412
+ weakdeps = get (Dict{String, Any}, d_proj, " weakdeps " ) :: Dict{String,Any}
1413
+ deps = get ( Dict{String, Any}, d_proj, " deps " ) :: Dict{String, Any}
1414
+ total_deps = merge (weakdeps, deps )
1415
+ return _insert_extension_triggers (pkg, extensions, total_deps)
1415
1416
end
1416
1417
1417
1418
# Now look in manifest
@@ -1426,35 +1427,43 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi
1426
1427
uuid = get (entry, " uuid" , nothing ):: Union{String, Nothing}
1427
1428
uuid === nothing && continue
1428
1429
if UUID (uuid) == pkg. uuid
1429
- weakdeps = get (entry, " weakdeps" , nothing ):: Union{Nothing, Vector{String}, Dict{String,Any}}
1430
1430
extensions = get (entry, " extensions" , nothing ):: Union{Nothing, Dict{String, Any}}
1431
1431
extensions === nothing && return
1432
- weakdeps === nothing && return
1433
- if weakdeps isa Dict{String, Any}
1434
- return _insert_extension_triggers (pkg, extensions, weakdeps)
1432
+ weakdeps = get (Dict{String, Any}, entry, " weakdeps" ):: Union{Vector{String}, Dict{String,Any}}
1433
+ deps = get (Dict{String, Any}, entry, " deps" ):: Union{Vector{String}, Dict{String,Any}}
1434
+
1435
+ function expand_deps_list (deps′:: Vector{String} )
1436
+ deps′_expanded = Dict {String, Any} ()
1437
+ for (dep_name, entries) in d
1438
+ dep_name in deps′ || continue
1439
+ entries:: Vector{Any}
1440
+ if length (entries) != 1
1441
+ error (" expected a single entry for $(repr (dep_name)) in $(repr (project_file)) " )
1442
+ end
1443
+ entry = first (entries):: Dict{String, Any}
1444
+ uuid = entry[" uuid" ]:: String
1445
+ deps′_expanded[dep_name] = uuid
1446
+ end
1447
+ return deps′_expanded
1435
1448
end
1436
1449
1437
- d_weakdeps = Dict {String, Any} ()
1438
- for (dep_name, entries) in d
1439
- dep_name in weakdeps || continue
1440
- entries:: Vector{Any}
1441
- if length (entries) != 1
1442
- error (" expected a single entry for $(repr (dep_name)) in $(repr (project_file)) " )
1443
- end
1444
- entry = first (entries):: Dict{String, Any}
1445
- uuid = entry[" uuid" ]:: String
1446
- d_weakdeps[dep_name] = uuid
1450
+ if weakdeps isa Vector{String}
1451
+ weakdeps = expand_deps_list (weakdeps)
1452
+ end
1453
+ if deps isa Vector{String}
1454
+ deps = expand_deps_list (deps)
1447
1455
end
1448
- @assert length (d_weakdeps) == length (weakdeps)
1449
- return _insert_extension_triggers (pkg, extensions, d_weakdeps)
1456
+
1457
+ total_deps = merge (weakdeps, deps)
1458
+ return _insert_extension_triggers (pkg, extensions, total_deps)
1450
1459
end
1451
1460
end
1452
1461
end
1453
1462
end
1454
1463
return nothing
1455
1464
end
1456
1465
1457
- function _insert_extension_triggers (parent:: PkgId , extensions:: Dict{String, Any} , weakdeps :: Dict{String, Any} )
1466
+ function _insert_extension_triggers (parent:: PkgId , extensions:: Dict{String, Any} , totaldeps :: Dict{String, Any} )
1458
1467
for (ext, triggers) in extensions
1459
1468
triggers = triggers:: Union{String, Vector{String}}
1460
1469
triggers isa String && (triggers = [triggers])
@@ -1468,7 +1477,7 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}
1468
1477
push! (trigger1, gid)
1469
1478
for trigger in triggers
1470
1479
# TODO : Better error message if this lookup fails?
1471
- uuid_trigger = UUID (weakdeps [trigger]:: String )
1480
+ uuid_trigger = UUID (totaldeps [trigger]:: String )
1472
1481
trigger_id = PkgId (uuid_trigger, trigger)
1473
1482
if ! haskey (explicit_loaded_modules, trigger_id) || haskey (package_locks, trigger_id)
1474
1483
trigger1 = get! (Vector{ExtensionId}, EXT_DORMITORY, trigger_id)
@@ -1480,6 +1489,7 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}
1480
1489
end
1481
1490
end
1482
1491
1492
+ precompiling_package:: Bool = false
1483
1493
loading_extension:: Bool = false
1484
1494
precompiling_extension:: Bool = false
1485
1495
function run_extension_callbacks (extid:: ExtensionId )
@@ -2172,6 +2182,11 @@ For more details regarding code loading, see the manual sections on [modules](@r
2172
2182
[parallel computing](@ref code-availability).
2173
2183
"""
2174
2184
function require (into:: Module , mod:: Symbol )
2185
+ if into === Base. __toplevel__ && precompiling_package
2186
+ # this error type needs to match the error type compilecache throws for non-125 errors.
2187
+ error (" `using/import $mod ` outside of a Module detected. Importing a package outside of a module \
2188
+ is not allowed during package precompilation." )
2189
+ end
2175
2190
if _require_world_age[] != typemax (UInt)
2176
2191
Base. invoke_in_world (_require_world_age[], __require, into, mod)
2177
2192
else
@@ -2750,41 +2765,10 @@ function load_path_setup_code(load_path::Bool=true)
2750
2765
return code
2751
2766
end
2752
2767
2753
- """
2754
- check_src_module_wrap(srcpath::String)
2755
-
2756
- Checks that a package entry file `srcpath` has a module declaration, and that it is before any using/import statements.
2757
- """
2758
- function check_src_module_wrap (pkg:: PkgId , srcpath:: String )
2759
- module_rgx = r" ^(|end |\"\"\" )\s *(?:@)*(?:bare)?module\s "
2760
- load_rgx = r" \b (?:using|import)\s "
2761
- load_seen = false
2762
- inside_string = false
2763
- for s in eachline (srcpath)
2764
- if count (" \"\"\" " , s) == 1
2765
- # ignore module docstrings
2766
- inside_string = ! inside_string
2767
- end
2768
- inside_string && continue
2769
- if contains (s, module_rgx)
2770
- if load_seen
2771
- throw (ErrorException (" Package $(repr (" text/plain" , pkg)) source file $srcpath has a using/import before a module declaration." ))
2772
- end
2773
- return true
2774
- end
2775
- if startswith (s, load_rgx)
2776
- load_seen = true
2777
- end
2778
- end
2779
- throw (ErrorException (" Package $(repr (" text/plain" , pkg)) source file $srcpath does not contain a module declaration." ))
2780
- end
2781
-
2782
2768
# this is called in the external process that generates precompiled package files
2783
2769
function include_package_for_output (pkg:: PkgId , input:: String , depot_path:: Vector{String} , dl_load_path:: Vector{String} , load_path:: Vector{String} ,
2784
2770
concrete_deps:: typeof (_concrete_dependencies), source:: Union{Nothing,String} )
2785
2771
2786
- check_src_module_wrap (pkg, input)
2787
-
2788
2772
append! (empty! (Base. DEPOT_PATH ), depot_path)
2789
2773
append! (empty! (Base. DL_LOAD_PATH), dl_load_path)
2790
2774
append! (empty! (Base. LOAD_PATH ), load_path)
@@ -2811,11 +2795,22 @@ function include_package_for_output(pkg::PkgId, input::String, depot_path::Vecto
2811
2795
finally
2812
2796
Core. Compiler. track_newly_inferred. x = false
2813
2797
end
2798
+ # check that the package defined the expected module so we can give a nice error message if not
2799
+ Base. check_package_module_loaded (pkg)
2800
+ end
2801
+
2802
+ function check_package_module_loaded (pkg:: PkgId )
2803
+ if ! haskey (Base. loaded_modules, pkg)
2804
+ # match compilecache error type for non-125 errors
2805
+ error (" $(repr (" text/plain" , pkg)) did not define the expected module `$(pkg. name) `, \
2806
+ check for typos in package module name" )
2807
+ end
2808
+ return nothing
2814
2809
end
2815
2810
2816
2811
const PRECOMPILE_TRACE_COMPILE = Ref {String} ()
2817
2812
function create_expr_cache (pkg:: PkgId , input:: String , output:: String , output_o:: Union{Nothing, String} ,
2818
- concrete_deps:: typeof (_concrete_dependencies), flags:: Cmd = ` ` , internal_stderr:: IO = stderr , internal_stdout:: IO = stdout )
2813
+ concrete_deps:: typeof (_concrete_dependencies), flags:: Cmd = ` ` , internal_stderr:: IO = stderr , internal_stdout:: IO = stdout , isext :: Bool = false )
2819
2814
@nospecialize internal_stderr internal_stdout
2820
2815
rm (output, force= true ) # Remove file if it exists
2821
2816
output_o === nothing || rm (output_o, force= true )
@@ -2884,7 +2879,8 @@ function create_expr_cache(pkg::PkgId, input::String, output::String, output_o::
2884
2879
write (io. in, """
2885
2880
empty!(Base.EXT_DORMITORY) # If we have a custom sysimage with `EXT_DORMITORY` prepopulated
2886
2881
Base.track_nested_precomp($precomp_stack )
2887
- Base.precompiling_extension = $(loading_extension)
2882
+ Base.precompiling_extension = $(loading_extension | isext)
2883
+ Base.precompiling_package = true
2888
2884
Base.include_package_for_output($(pkg_str (pkg)) , $(repr (abspath (input))) , $(repr (depot_path)) , $(repr (dl_load_path)) ,
2889
2885
$(repr (load_path)) , $deps , $(repr (source_path (nothing ))) )
2890
2886
""" )
@@ -2941,18 +2937,18 @@ This can be used to reduce package load times. Cache files are stored in
2941
2937
`DEPOT_PATH[1]/compiled`. See [Module initialization and precompilation](@ref)
2942
2938
for important notes.
2943
2939
"""
2944
- function compilecache (pkg:: PkgId , internal_stderr:: IO = stderr , internal_stdout:: IO = stdout ; flags:: Cmd = ` ` , reasons:: Union{Dict{String,Int},Nothing} = Dict {String,Int} ())
2940
+ 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 )
2945
2941
@nospecialize internal_stderr internal_stdout
2946
2942
path = locate_package (pkg)
2947
2943
path === nothing && throw (ArgumentError (" $(repr (" text/plain" , pkg)) not found during precompilation" ))
2948
- return compilecache (pkg, path, internal_stderr, internal_stdout; flags, reasons)
2944
+ return compilecache (pkg, path, internal_stderr, internal_stdout; flags, reasons, isext )
2949
2945
end
2950
2946
2951
2947
const MAX_NUM_PRECOMPILE_FILES = Ref (10 )
2952
2948
2953
2949
function compilecache (pkg:: PkgId , path:: String , internal_stderr:: IO = stderr , internal_stdout:: IO = stdout ,
2954
2950
keep_loaded_modules:: Bool = true ; flags:: Cmd = ` ` , cacheflags:: CacheFlags = CacheFlags (),
2955
- reasons:: Union{Dict{String,Int},Nothing} = Dict {String,Int} ())
2951
+ reasons:: Union{Dict{String,Int},Nothing} = Dict {String,Int} (), isext :: Bool = false )
2956
2952
2957
2953
@nospecialize internal_stderr internal_stdout
2958
2954
# decide where to put the resulting cache file
@@ -2992,7 +2988,7 @@ function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, in
2992
2988
close (tmpio_o)
2993
2989
close (tmpio_so)
2994
2990
end
2995
- p = create_expr_cache (pkg, path, tmppath, tmppath_o, concrete_deps, flags, internal_stderr, internal_stdout)
2991
+ p = create_expr_cache (pkg, path, tmppath, tmppath_o, concrete_deps, flags, internal_stderr, internal_stdout, isext )
2996
2992
2997
2993
if success (p)
2998
2994
if cache_objects
@@ -3778,10 +3774,17 @@ end
3778
3774
3779
3775
# now check if this file's content hash has changed relative to its source files
3780
3776
if stalecheck
3781
- if ! samefile (includes[1 ]. filename, modpath) && ! samefile (fixup_stdlib_path (includes[1 ]. filename), modpath)
3782
- @debug " Rejecting cache file $cachefile because it is for file $(includes[1 ]. filename) not file $modpath "
3783
- record_reason (reasons, " wrong source" )
3784
- return true # cache file was compiled from a different path
3777
+ if ! samefile (includes[1 ]. filename, modpath)
3778
+ # In certain cases the path rewritten by `fixup_stdlib_path` may
3779
+ # point to an unreadable directory, make sure we can `stat` the
3780
+ # file before comparing it with `modpath`.
3781
+ stdlib_path = fixup_stdlib_path (includes[1 ]. filename)
3782
+ if ! (isreadable (stdlib_path) && samefile (stdlib_path, modpath))
3783
+ ! samefile (fixup_stdlib_path (includes[1 ]. filename), modpath)
3784
+ @debug " Rejecting cache file $cachefile because it is for file $(includes[1 ]. filename) not file $modpath "
3785
+ record_reason (reasons, " wrong source" )
3786
+ return true # cache file was compiled from a different path
3787
+ end
3785
3788
end
3786
3789
for (modkey, req_modkey) in requires
3787
3790
# verify that `require(modkey, name(req_modkey))` ==> `req_modkey`
0 commit comments