Skip to content

Commit f6f3553

Browse files
add Base.isprecompiled(pkg::PkgId) (#50218)
1 parent 5db930e commit f6f3553

File tree

4 files changed

+65
-1
lines changed

4 files changed

+65
-1
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ New library functions
5757
* `fourthroot(x)` is now defined in `Base.Math` and can be used to compute the fourth root of `x`.
5858
It can also be accessed using the unicode character ``, which can be typed by `\fourthroot<tab>` ([#48899]).
5959
* `Libc.memmove`, `Libc.memset`, and `Libc.memcpy` are now defined, whose functionality matches that of their respective C calls.
60+
* `Base.isprecompiled(pkg::PkgId)` to identify whether a package has already been precompiled ([#50218]).
6061

6162
New library features
6263
--------------------

base/loading.jl

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
13681427
function _tryrequire_from_serialized(modkey::PkgId, build_id::UInt128)
13691428
assert_havelock(require_lock)

doc/src/base/base.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ Base.identify_package
462462
Base.locate_package
463463
Base.require
464464
Base.compilecache
465+
Base.isprecompiled
465466
```
466467

467468
## Internals

test/precompile.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,10 @@ precompile_test_harness("code caching") do dir
655655
precompile(getelsize, (Vector{Int32},))
656656
end
657657
""")
658-
Base.compilecache(Base.PkgId(string(Cache_module)))
658+
pkgid = Base.PkgId(string(Cache_module))
659+
@test !Base.isprecompiled(pkgid)
660+
Base.compilecache(pkgid)
661+
@test Base.isprecompiled(pkgid)
659662
@eval using $Cache_module
660663
M = getfield(@__MODULE__, Cache_module)
661664
# Test that this cache file "owns" all the roots

0 commit comments

Comments
 (0)