depfile: deal with empty / non-concrete env (#40816)
This commit is contained in:
		@@ -672,18 +672,31 @@ def env_depfile(args):
 | 
			
		||||
    # Currently only make is supported.
 | 
			
		||||
    spack.cmd.require_active_env(cmd_name="env depfile")
 | 
			
		||||
 | 
			
		||||
    env = ev.active_environment()
 | 
			
		||||
 | 
			
		||||
    # What things do we build when running make? By default, we build the
 | 
			
		||||
    # root specs. If specific specs are provided as input, we build those.
 | 
			
		||||
    filter_specs = spack.cmd.parse_specs(args.specs) if args.specs else None
 | 
			
		||||
    template = spack.tengine.make_environment().get_template(os.path.join("depfile", "Makefile"))
 | 
			
		||||
    model = depfile.MakefileModel.from_env(
 | 
			
		||||
        ev.active_environment(),
 | 
			
		||||
        env,
 | 
			
		||||
        filter_specs=filter_specs,
 | 
			
		||||
        pkg_buildcache=depfile.UseBuildCache.from_string(args.use_buildcache[0]),
 | 
			
		||||
        dep_buildcache=depfile.UseBuildCache.from_string(args.use_buildcache[1]),
 | 
			
		||||
        make_prefix=args.make_prefix,
 | 
			
		||||
        jobserver=args.jobserver,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # Warn in case we're generating a depfile for an empty environment. We don't automatically
 | 
			
		||||
    # concretize; the user should do that explicitly. Could be changed in the future if requested.
 | 
			
		||||
    if model.empty:
 | 
			
		||||
        if not env.user_specs:
 | 
			
		||||
            tty.warn("no specs in the environment")
 | 
			
		||||
        elif filter_specs is not None:
 | 
			
		||||
            tty.warn("no concrete matching specs found in environment")
 | 
			
		||||
        else:
 | 
			
		||||
            tty.warn("environment is not concretized. Run `spack concretize` first")
 | 
			
		||||
 | 
			
		||||
    makefile = template.render(model.to_dict())
 | 
			
		||||
 | 
			
		||||
    # Finally write to stdout/file.
 | 
			
		||||
 
 | 
			
		||||
@@ -232,6 +232,10 @@ def to_dict(self):
 | 
			
		||||
            "pkg_ids": " ".join(self.all_pkg_identifiers),
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def empty(self):
 | 
			
		||||
        return len(self.roots) == 0
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def from_env(
 | 
			
		||||
        env: ev.Environment,
 | 
			
		||||
@@ -254,15 +258,10 @@ def from_env(
 | 
			
		||||
            jobserver: when enabled, make will invoke Spack with jobserver support. For
 | 
			
		||||
                dry-run this should be disabled.
 | 
			
		||||
        """
 | 
			
		||||
        # If no specs are provided as a filter, build all the specs in the environment.
 | 
			
		||||
        if filter_specs:
 | 
			
		||||
            entrypoints = [env.matching_spec(s) for s in filter_specs]
 | 
			
		||||
        else:
 | 
			
		||||
            entrypoints = [s for _, s in env.concretized_specs()]
 | 
			
		||||
 | 
			
		||||
        roots = env.all_matching_specs(*filter_specs) if filter_specs else env.concrete_roots()
 | 
			
		||||
        visitor = DepfileSpecVisitor(pkg_buildcache, dep_buildcache)
 | 
			
		||||
        traverse.traverse_breadth_first_with_visitor(
 | 
			
		||||
            entrypoints, traverse.CoverNodesVisitor(visitor, key=lambda s: s.dag_hash())
 | 
			
		||||
            roots, traverse.CoverNodesVisitor(visitor, key=lambda s: s.dag_hash())
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        return MakefileModel(env, entrypoints, visitor.adjacency_list, make_prefix, jobserver)
 | 
			
		||||
        return MakefileModel(env, roots, visitor.adjacency_list, make_prefix, jobserver)
 | 
			
		||||
 
 | 
			
		||||
@@ -3382,6 +3382,20 @@ def test_spack_package_ids_variable(tmpdir, mock_packages):
 | 
			
		||||
            assert "post-install: {}".format(s.dag_hash()) in out
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_depfile_empty_does_not_error(tmp_path):
 | 
			
		||||
    # For empty environments Spack should create a depfile that does nothing
 | 
			
		||||
    make = Executable("make")
 | 
			
		||||
    makefile = str(tmp_path / "Makefile")
 | 
			
		||||
 | 
			
		||||
    env("create", "test")
 | 
			
		||||
    with ev.read("test"):
 | 
			
		||||
        env("depfile", "-o", makefile)
 | 
			
		||||
 | 
			
		||||
    make("-f", makefile)
 | 
			
		||||
 | 
			
		||||
    assert make.returncode == 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_unify_when_possible_works_around_conflicts():
 | 
			
		||||
    e = ev.create("coconcretization")
 | 
			
		||||
    e.unify = "when_possible"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user