@@ -41,7 +41,7 @@ function ExplicitEnv(::Nothing, envpath::String="")
4141end
4242function ExplicitEnv (envpath:: String )
4343 # Handle missing project file by creating an empty environment
44- if ! isfile (envpath)
44+ if ! isfile (envpath) || project_file_manifest_path (envpath) === nothing
4545 envpath = abspath (envpath)
4646 return ExplicitEnv (nothing , envpath)
4747 end
@@ -471,7 +471,7 @@ function collect_all_deps(direct_deps, dep, alldeps=Set{Base.PkgId}())
471471end
472472
473473
474- function precompilepkgs (pkgs:: Vector{String} = String[];
474+ function precompilepkgs (pkgs:: Union{ Vector{String}, Vector{PkgId} }= String[];
475475 internal_call:: Bool = false ,
476476 strict:: Bool = false ,
477477 warn_loaded:: Bool = true ,
@@ -490,7 +490,7 @@ function precompilepkgs(pkgs::Vector{String}=String[];
490490 IOContext {IO} (io), fancyprint, manifest, ignore_loaded)
491491end
492492
493- function _precompilepkgs (pkgs:: Vector{String} ,
493+ function _precompilepkgs (pkgs:: Union{ Vector{String}, Vector{PkgId} } ,
494494 internal_call:: Bool ,
495495 strict:: Bool ,
496496 warn_loaded:: Bool ,
@@ -502,6 +502,23 @@ function _precompilepkgs(pkgs::Vector{String},
502502 manifest:: Bool ,
503503 ignore_loaded:: Bool )
504504 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
505522
506523 time_start = time_ns ()
507524
@@ -655,8 +672,7 @@ function _precompilepkgs(pkgs::Vector{String},
655672 # if called from loading precompilation it may be a package from another environment stack
656673 # where we don't have access to the dep graph, so just add as a single package and do serial
657674 # 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
660676 pkgid === nothing && continue
661677 if ! haskey (direct_deps, pkgid)
662678 @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},
704720 circular_deps = Base. PkgId[]
705721 for pkg in keys (direct_deps)
706722 @assert isempty (stack)
723+ pkg in serial_deps && continue # skip serial deps as we don't have their dependency graph
707724 if scan_pkg! (stack, could_be_cycle, cycles, pkg, direct_deps)
708725 push! (circular_deps, pkg)
709726 for pkg_config in keys (was_processed)
@@ -717,18 +734,31 @@ function _precompilepkgs(pkgs::Vector{String},
717734 end
718735 @debug " precompile: circular dep check done"
719736
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`?
720741 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]
723744 end
724745 keep = Set {Base.PkgId} ()
725746 for dep in direct_deps
726747 dep_pkgid = first (dep)
727- if dep_pkgid. name in pkgs
748+ if dep_pkgid. name in pkg_names
728749 push! (keep, dep_pkgid)
729750 collect_all_deps (direct_deps, dep_pkgid, keep)
730751 end
731752 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
732762 for ext in keys (ext_to_parent)
733763 if issubset (collect_all_deps (direct_deps, ext), keep) # if all extension deps are kept
734764 push! (keep, ext)
@@ -936,7 +966,8 @@ function _precompilepkgs(pkgs::Vector{String},
936966 for (pkg, deps) in direct_deps
937967 cachepaths = get! (() -> Base. find_all_in_cache_path (pkg), cachepath_cache, pkg)
938968 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)
940971 for config in configs
941972 pkg_config = (pkg, config)
942973 if sourcepath === nothing
@@ -1063,7 +1094,7 @@ function _precompilepkgs(pkgs::Vector{String},
10631094 str = sprint (context= io) do iostr
10641095 if ! quick_exit
10651096 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."
10671098 printpkgstyle (iostr, :Precompiling , what)
10681099 end
10691100 plural = length (configs) > 1 ? " dependency configurations" : ndeps == 1 ? " dependency" : " dependencies"
0 commit comments