@@ -322,6 +322,31 @@ function manifest_deps_get(env::String, where::PkgId, name::String, cache::TOMLC
322322    return  nothing 
323323end 
324324
325+ function  uuid_in_environment (project_file:: String , uuid:: UUID , cache:: TOMLCache )
326+     #  First, check to see if we're looking for the environment itself
327+     proj_uuid =  get (parsed_toml (cache, project_file), " uuid" nothing )
328+     if  proj_uuid != =  nothing  &&  UUID (proj_uuid) ==  uuid
329+         return  true 
330+     end 
331+ 
332+     #  Check to see if there's a Manifest.toml associated with this project
333+     manifest_file =  project_file_manifest_path (project_file, cache)
334+     if  manifest_file ===  nothing 
335+         return  false 
336+     end 
337+     manifest =  parsed_toml (cache, manifest_file)
338+     for  (dep_name, entries) in  manifest
339+         for  entry in  entries
340+             entry_uuid =  get (entry, " uuid" nothing ):: Union{String, Nothing} 
341+             if  uuid != =  nothing  &&  UUID (entry_uuid) ==  uuid
342+                 return  true 
343+             end 
344+         end 
345+     end 
346+     #  If all else fails, return `false`
347+     return  false 
348+ end 
349+ 
325350function  manifest_uuid_path (env:: String , pkg:: PkgId , cache:: TOMLCache ):: Union{Nothing,String} 
326351    project_file =  env_project_file (env)
327352    if  project_file isa  String
@@ -950,7 +975,7 @@ function _require(pkg::PkgId, cache::TOMLCache)
950975            if  (0  ==  ccall (:jl_generating_output , Cint, ())) ||  (JLOptions (). incremental !=  0 )
951976                #  spawn off a new incremental pre-compile task for recursive `require` calls
952977                #  or if the require search declared it was pre-compiled before (and therefore is expected to still be pre-compilable)
953-                 cachefile =  compilecache (pkg, path)
978+                 cachefile =  compilecache (pkg, path, cache )
954979                if  isa (cachefile, Exception)
955980                    if  precompilableerror (cachefile)
956981                        verbosity =  isinteractive () ?  CoreLogging. Info :  CoreLogging. Debug
@@ -1195,7 +1220,7 @@ end
11951220@assert  precompile (create_expr_cache, (PkgId, String, String, typeof (_concrete_dependencies), Bool))
11961221@assert  precompile (create_expr_cache, (PkgId, String, String, typeof (_concrete_dependencies), Bool))
11971222
1198- function  compilecache_path (pkg:: PkgId ):: String 
1223+ function  compilecache_path (pkg:: PkgId , cache :: TOMLCache ):: String 
11991224    entrypath, entryfile =  cache_file_entry (pkg)
12001225    cachepath =  joinpath (DEPOT_PATH [1 ], entrypath)
12011226    isdir (cachepath) ||  mkpath (cachepath)
@@ -1205,6 +1230,7 @@ function compilecache_path(pkg::PkgId)::String
12051230        crc =  _crc32c (something (Base. active_project (), " " 
12061231        crc =  _crc32c (unsafe_string (JLOptions (). image_file), crc)
12071232        crc =  _crc32c (unsafe_string (JLOptions (). julia_bin), crc)
1233+         crc =  _crc32c (get_preferences_hash (pkg. uuid, cache), crc)
12081234        project_precompile_slug =  slug (crc, 5 )
12091235        abspath (cachepath, string (entryfile, " _" " .ji" 
12101236    end 
@@ -1218,18 +1244,17 @@ This can be used to reduce package load times. Cache files are stored in
12181244`DEPOT_PATH[1]/compiled`. See [Module initialization and precompilation](@ref) 
12191245for important notes. 
12201246""" 
1221- function  compilecache (pkg:: PkgId , cache:: TOMLCache  =  TOMLCache ())
1247+ function  compilecache (pkg:: PkgId , cache:: TOMLCache  =  TOMLCache (), show_errors :: Bool   =   true )
12221248    path =  locate_package (pkg, cache)
12231249    path ===  nothing  &&  throw (ArgumentError (" $pkg  not found during precompilation" 
1224-     return  compilecache (pkg, path)
1250+     return  compilecache (pkg, path, cache, show_errors )
12251251end 
12261252
12271253const  MAX_NUM_PRECOMPILE_FILES =  10 
12281254
1229- #  `show_errors` is an "internal" interface for Pkg.precompile
1230- function  compilecache (pkg:: PkgId , path:: String , show_errors:: Bool  =  true )
1255+ function  compilecache (pkg:: PkgId , path:: String , cache:: TOMLCache  =  TOMLCache (), show_errors:: Bool  =  true )
12311256    #  decide where to put the resulting cache file
1232-     cachefile =  compilecache_path (pkg)
1257+     cachefile =  compilecache_path (pkg, cache )
12331258    cachepath =  dirname (cachefile)
12341259    #  prune the directory with cache files
12351260    if  pkg. uuid != =  nothing 
@@ -1333,6 +1358,8 @@ function parse_cache_header(f::IO)
13331358        end 
13341359        totbytes -=  4  +  4  +  n2 +  8 
13351360    end 
1361+     prefs_hash =  read (f, UInt64)
1362+     totbytes -=  8 
13361363    @assert  totbytes ==  12  " header of cache file appears to be corrupt" 
13371364    srctextpos =  read (f, Int64)
13381365    #  read the list of modules that are required to be present during loading
@@ -1345,7 +1372,7 @@ function parse_cache_header(f::IO)
13451372        build_id =  read (f, UInt64) #  build id
13461373        push! (required_modules, PkgId (uuid, sym) =>  build_id)
13471374    end 
1348-     return  modules, (includes, requires), required_modules, srctextpos
1375+     return  modules, (includes, requires), required_modules, srctextpos, prefs_hash 
13491376end 
13501377
13511378function  parse_cache_header (cachefile:: String ; srcfiles_only:: Bool = false )
@@ -1354,21 +1381,21 @@ function parse_cache_header(cachefile::String; srcfiles_only::Bool=false)
13541381        ! isvalid_cache_header (io) &&  throw (ArgumentError (" Invalid header in cache file $cachefile ." 
13551382        ret =  parse_cache_header (io)
13561383        srcfiles_only ||  return  ret
1357-         modules, (includes, requires), required_modules, srctextpos =  ret
1384+         modules, (includes, requires), required_modules, srctextpos, prefs_hash  =  ret
13581385        srcfiles =  srctext_files (io, srctextpos)
13591386        delidx =  Int[]
13601387        for  (i, chi) in  enumerate (includes)
13611388            chi. filename ∈  srcfiles ||  push! (delidx, i)
13621389        end 
13631390        deleteat! (includes, delidx)
1364-         return  modules, (includes, requires), required_modules, srctextpos
1391+         return  modules, (includes, requires), required_modules, srctextpos, prefs_hash 
13651392    finally 
13661393        close (io)
13671394    end 
13681395end 
13691396
13701397function  cache_dependencies (f:: IO )
1371-     defs, (includes, requires), modules =  parse_cache_header (f)
1398+     defs, (includes, requires), modules, srctextpos, prefs_hash  =  parse_cache_header (f)
13721399    return  modules, map (chi ->  (chi. filename, chi. mtime), includes)  #  return just filename and mtime
13731400end 
13741401
@@ -1383,7 +1410,7 @@ function cache_dependencies(cachefile::String)
13831410end 
13841411
13851412function  read_dependency_src (io:: IO , filename:: AbstractString )
1386-     modules, (includes, requires), required_modules, srctextpos =  parse_cache_header (io)
1413+     modules, (includes, requires), required_modules, srctextpos, prefs_hash  =  parse_cache_header (io)
13871414    srctextpos ==  0  &&  error (" no source-text stored in cache file" 
13881415    seek (io, srctextpos)
13891416    return  _read_dependency_src (io, filename)
@@ -1428,6 +1455,37 @@ function srctext_files(f::IO, srctextpos::Int64)
14281455    return  files
14291456end 
14301457
1458+ #  Find the Project.toml that we should load/store to for Preferences
1459+ function  get_preferences_project_path (uuid:: UUID , cache:: TOMLCache  =  TOMLCache ())
1460+     for  env in  load_path ()
1461+         project_file =  env_project_file (env)
1462+         if  ! isa (project_file, String)
1463+             continue 
1464+         end 
1465+         if  uuid_in_environment (project_file, uuid, cache)
1466+             return  project_file
1467+         end 
1468+     end 
1469+     return  nothing 
1470+ end 
1471+ 
1472+ function  get_preferences (uuid:: UUID , cache:: TOMLCache  =  TOMLCache ();
1473+                          prefs_key:: String  =  " compile-preferences" 
1474+     project_path =  get_preferences_project_path (uuid, cache)
1475+     if  project_path != =  nothing 
1476+         preferences =  get (parsed_toml (cache, project_path), prefs_key, Dict {String,Any} ())
1477+         if  haskey (preferences, string (uuid))
1478+             return  preferences[string (uuid)]
1479+         end 
1480+     end 
1481+     #  Fall back to default value of "no preferences".
1482+     return  Dict {String,Any} ()
1483+ end 
1484+ get_preferences_hash (uuid:: UUID , cache:: TOMLCache  =  TOMLCache ()) =  UInt64 (hash (get_preferences (uuid, cache)))
1485+ get_preferences_hash (m:: Module , cache:: TOMLCache  =  TOMLCache ()) =  get_preferences_hash (PkgId (m). uuid, cache)
1486+ get_preferences_hash (:: Nothing , cache:: TOMLCache  =  TOMLCache ()) =  UInt64 (hash (Dict {String,Any} ()))
1487+ 
1488+ 
14311489#  returns true if it "cachefile.ji" is stale relative to "modpath.jl"
14321490#  otherwise returns the list of dependencies to also check
14331491stale_cachefile (modpath:: String , cachefile:: String ) =  stale_cachefile (modpath, cachefile, TOMLCache ())
@@ -1438,7 +1496,7 @@ function stale_cachefile(modpath::String, cachefile::String, cache::TOMLCache)
14381496            @debug  " Rejecting cache file $cachefile  due to it containing an invalid cache header" 
14391497            return  true  #  invalid cache file
14401498        end 
1441-         ( modules, (includes, requires), required_modules)  =  parse_cache_header (io)
1499+         modules, (includes, requires), required_modules, srctextpos, prefs_hash  =  parse_cache_header (io)
14421500        id =  isempty (modules) ?  nothing  :  first (modules). first
14431501        modules =  Dict {PkgId, UInt64} (modules)
14441502
@@ -1514,6 +1572,12 @@ function stale_cachefile(modpath::String, cachefile::String, cache::TOMLCache)
15141572        end 
15151573
15161574        if  isa (id, PkgId)
1575+             curr_prefs_hash =  get_preferences_hash (id. uuid, cache)
1576+             if  prefs_hash !=  curr_prefs_hash
1577+                 @debug  " Rejecting cache file $cachefile  because preferences hash does not match 0x$(string (prefs_hash, base= 16 ))  != 0x$(string (curr_prefs_hash, base= 16 )) " 
1578+                 return  true 
1579+             end 
1580+ 
15171581            get! (PkgOrigin, pkgorigins, id). cachepath =  cachefile
15181582        end 
15191583
0 commit comments