@@ -1364,6 +1364,65 @@ end
13641364
13651365# End extensions
13661366
1367+ # should sync with the types of arguments of `stale_cachefile`
1368+ const StaleCacheKey = Tuple{Base. PkgId, UInt128, String, String}
1369+
1370+ """
1371+ Base.isprecompiled(pkg::PkgId; ignore_loaded::Bool=false)
1372+
1373+ Returns whether a given PkgId within the active project is precompiled.
1374+
1375+ By default this check observes the same approach that code loading takes
1376+ with respect to when different versions of dependencies are currently loaded
1377+ to that which is expected. To ignore loaded modules and answer as if in a
1378+ fresh julia session specify `ignore_loaded=true`.
1379+
1380+ !!! compat "Julia 1.10"
1381+ This function requires at least Julia 1.10.
1382+ """
1383+ function isprecompiled (pkg:: PkgId ;
1384+ ignore_loaded:: Bool = false ,
1385+ stale_cache:: Dict{StaleCacheKey,Bool} = Dict {StaleCacheKey, Bool} (),
1386+ cachepaths:: Vector{String} = Base. find_all_in_cache_path (pkg),
1387+ sourcepath:: Union{String,Nothing} = Base. locate_package (pkg)
1388+ )
1389+ isnothing (sourcepath) && error (" Cannot locate source for $(repr (pkg)) " )
1390+ for path_to_try in cachepaths
1391+ staledeps = stale_cachefile (sourcepath, path_to_try, ignore_loaded = true )
1392+ if staledeps === true
1393+ continue
1394+ end
1395+ staledeps, _ = staledeps:: Tuple{Vector{Any}, Union{Nothing, String}}
1396+ # finish checking staledeps module graph
1397+ for i in 1 : length (staledeps)
1398+ dep = staledeps[i]
1399+ dep isa Module && continue
1400+ modpath, modkey, modbuild_id = dep:: Tuple{String, PkgId, UInt128}
1401+ modpaths = find_all_in_cache_path (modkey)
1402+ for modpath_to_try in modpaths:: Vector{String}
1403+ stale_cache_key = (modkey, modbuild_id, modpath, modpath_to_try):: StaleCacheKey
1404+ if get! (() -> stale_cachefile (stale_cache_key... ; ignore_loaded) === true ,
1405+ stale_cache, stale_cache_key)
1406+ continue
1407+ end
1408+ @goto check_next_dep
1409+ end
1410+ @goto check_next_path
1411+ @label check_next_dep
1412+ end
1413+ try
1414+ # update timestamp of precompilation file so that it is the first to be tried by code loading
1415+ touch (path_to_try)
1416+ catch ex
1417+ # file might be read-only and then we fail to update timestamp, which is fine
1418+ ex isa IOError || rethrow ()
1419+ end
1420+ return true
1421+ @label check_next_path
1422+ end
1423+ return false
1424+ end
1425+
13671426# loads a precompile cache file, after checking stale_cachefile tests
13681427function _tryrequire_from_serialized (modkey:: PkgId , build_id:: UInt128 )
13691428 assert_havelock (require_lock)
0 commit comments