@@ -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