@@ -41,7 +41,7 @@ function ExplicitEnv(::Nothing, envpath::String="")
41
41
end
42
42
function ExplicitEnv (envpath:: String )
43
43
# Handle missing project file by creating an empty environment
44
- if ! isfile (envpath)
44
+ if ! isfile (envpath) || project_file_manifest_path (envpath) === nothing
45
45
envpath = abspath (envpath)
46
46
return ExplicitEnv (nothing , envpath)
47
47
end
@@ -471,7 +471,7 @@ function collect_all_deps(direct_deps, dep, alldeps=Set{Base.PkgId}())
471
471
end
472
472
473
473
474
- function precompilepkgs (pkgs:: Vector{String} = String[];
474
+ function precompilepkgs (pkgs:: Union{ Vector{String}, Vector{PkgId} }= String[];
475
475
internal_call:: Bool = false ,
476
476
strict:: Bool = false ,
477
477
warn_loaded:: Bool = true ,
@@ -490,7 +490,7 @@ function precompilepkgs(pkgs::Vector{String}=String[];
490
490
IOContext {IO} (io), fancyprint, manifest, ignore_loaded)
491
491
end
492
492
493
- function _precompilepkgs (pkgs:: Vector{String} ,
493
+ function _precompilepkgs (pkgs:: Union{ Vector{String}, Vector{PkgId} } ,
494
494
internal_call:: Bool ,
495
495
strict:: Bool ,
496
496
warn_loaded:: Bool ,
@@ -502,6 +502,23 @@ function _precompilepkgs(pkgs::Vector{String},
502
502
manifest:: Bool ,
503
503
ignore_loaded:: Bool )
504
504
requested_pkgs = copy (pkgs) # for understanding user intent
505
+ pkg_names = pkgs isa Vector{String} ? copy (pkgs) : String[pkg. name for pkg in pkgs]
506
+ if pkgs isa Vector{PkgId}
507
+ requested_pkgids = copy (pkgs)
508
+ else
509
+ requested_pkgids = PkgId[]
510
+ for name in pkgs
511
+ pkgid = Base. identify_package (name)
512
+ if pkgid === nothing
513
+ if _from_loading
514
+ return # leave it up to loading to handle this
515
+ else
516
+ throw (PkgPrecompileError (" Unknown package: $name " ))
517
+ end
518
+ end
519
+ push! (requested_pkgids, pkgid)
520
+ end
521
+ end
505
522
506
523
time_start = time_ns ()
507
524
@@ -655,8 +672,7 @@ function _precompilepkgs(pkgs::Vector{String},
655
672
# if called from loading precompilation it may be a package from another environment stack
656
673
# where we don't have access to the dep graph, so just add as a single package and do serial
657
674
# precompilation of its deps within the job.
658
- for pkg in requested_pkgs # In case loading asks for multiple packages
659
- pkgid = Base. identify_package (pkg)
675
+ for pkgid in requested_pkgids # In case loading asks for multiple packages
660
676
pkgid === nothing && continue
661
677
if ! haskey (direct_deps, pkgid)
662
678
@debug " precompile: package `$(pkgid) ` is outside of the environment, so adding as single package serial job"
@@ -704,6 +720,7 @@ function _precompilepkgs(pkgs::Vector{String},
704
720
circular_deps = Base. PkgId[]
705
721
for pkg in keys (direct_deps)
706
722
@assert isempty (stack)
723
+ pkg in serial_deps && continue # skip serial deps as we don't have their dependency graph
707
724
if scan_pkg! (stack, could_be_cycle, cycles, pkg, direct_deps)
708
725
push! (circular_deps, pkg)
709
726
for pkg_config in keys (was_processed)
@@ -717,18 +734,31 @@ function _precompilepkgs(pkgs::Vector{String},
717
734
end
718
735
@debug " precompile: circular dep check done"
719
736
737
+ # If you have a workspace and want to precompile all projects in it, look through all packages in the manifest
738
+ # instead of collecting from a project i.e. not filter out packages that are in the current project.
739
+ # i.e. Pkg sets manifest to true for workspace precompile requests
740
+ # TODO : rename `manifest`?
720
741
if ! manifest
721
- if isempty (pkgs )
722
- pkgs = [pkg. name for pkg in project_deps]
742
+ if isempty (pkg_names )
743
+ pkg_names = [pkg. name for pkg in project_deps]
723
744
end
724
745
keep = Set {Base.PkgId} ()
725
746
for dep in direct_deps
726
747
dep_pkgid = first (dep)
727
- if dep_pkgid. name in pkgs
748
+ if dep_pkgid. name in pkg_names
728
749
push! (keep, dep_pkgid)
729
750
collect_all_deps (direct_deps, dep_pkgid, keep)
730
751
end
731
752
end
753
+ # Also keep packages that were explicitly requested as PkgIds (for extensions)
754
+ if pkgs isa Vector{PkgId}
755
+ for requested_pkgid in requested_pkgids
756
+ if haskey (direct_deps, requested_pkgid)
757
+ push! (keep, requested_pkgid)
758
+ collect_all_deps (direct_deps, requested_pkgid, keep)
759
+ end
760
+ end
761
+ end
732
762
for ext in keys (ext_to_parent)
733
763
if issubset (collect_all_deps (direct_deps, ext), keep) # if all extension deps are kept
734
764
push! (keep, ext)
@@ -936,7 +966,8 @@ function _precompilepkgs(pkgs::Vector{String},
936
966
for (pkg, deps) in direct_deps
937
967
cachepaths = get! (() -> Base. find_all_in_cache_path (pkg), cachepath_cache, pkg)
938
968
sourcepath = Base. locate_package (pkg)
939
- single_requested_pkg = length (requested_pkgs) == 1 && only (requested_pkgs) == pkg. name
969
+ single_requested_pkg = length (requested_pkgs) == 1 &&
970
+ (pkg in requested_pkgids || pkg. name in pkg_names)
940
971
for config in configs
941
972
pkg_config = (pkg, config)
942
973
if sourcepath === nothing
@@ -1063,7 +1094,7 @@ function _precompilepkgs(pkgs::Vector{String},
1063
1094
str = sprint (context= io) do iostr
1064
1095
if ! quick_exit
1065
1096
if fancyprint # replace the progress bar
1066
- what = isempty (requested_pkgs ) ? " packages finished." : " $(join (requested_pkgs , " , " , " and " )) finished."
1097
+ what = isempty (requested_pkgids ) ? " packages finished." : " $(join ((p . name for p in requested_pkgids) , " , " , " and " )) finished."
1067
1098
printpkgstyle (iostr, :Precompiling , what)
1068
1099
end
1069
1100
plural = length (configs) > 1 ? " dependency configurations" : ndeps == 1 ? " dependency" : " dependencies"
0 commit comments