depfile: improve tab completion (#33773)
This PR allows you to do: ``` spack env create -d . spack -e . add python spack -e . concretize spack -e . env depfile -o Makefile make in<tab> # -> install make install-<tab> # -> install-deps/ make install-deps/py<tab> # -> install-deps/python-x.y.z-hash make install/zl<tab> # -> install/zlib-x.y.z-hash make SP<tab> # -> make SPACK make SPACK_<tab> # -> make SPACK_INSTALL_FLAGS= ```
This commit is contained in:
parent
d1715c5fdf
commit
af74680405
2 changed files with 47 additions and 20 deletions
|
@ -673,13 +673,16 @@ def build_cache_flag(self, depth):
|
|||
return ""
|
||||
|
||||
def accept(self, node):
|
||||
dag_hash = node.edge.spec.dag_hash()
|
||||
fmt = "{name}-{version}-{hash}"
|
||||
tgt = node.edge.spec.format(fmt)
|
||||
spec_str = node.edge.spec.format(
|
||||
"{name}{@version}{%compiler}{variants}{arch=architecture}"
|
||||
)
|
||||
buildcache_flag = self.build_cache_flag(node.depth)
|
||||
prereqs = " ".join([self.target(dep.spec.dag_hash()) for dep in self.neighbors(node)])
|
||||
self.adjacency_list.append((dag_hash, spec_str, buildcache_flag, prereqs))
|
||||
prereqs = " ".join([self.target(dep.spec.format(fmt)) for dep in self.neighbors(node)])
|
||||
self.adjacency_list.append(
|
||||
(tgt, prereqs, node.edge.spec.dag_hash(), spec_str, buildcache_flag)
|
||||
)
|
||||
|
||||
# We already accepted this
|
||||
return True
|
||||
|
@ -690,6 +693,8 @@ def env_depfile(args):
|
|||
spack.cmd.require_active_env(cmd_name="env depfile")
|
||||
env = ev.active_environment()
|
||||
|
||||
# Special make targets are useful when including a makefile in another, and you
|
||||
# need to "namespace" the targets to avoid conflicts.
|
||||
if args.make_target_prefix is None:
|
||||
target_prefix = os.path.join(env.env_subdir_path, "makedeps")
|
||||
else:
|
||||
|
@ -706,10 +711,10 @@ def get_target(name):
|
|||
return os.path.join(target_prefix, name)
|
||||
|
||||
def get_install_target(name):
|
||||
return os.path.join(target_prefix, ".install", name)
|
||||
return os.path.join(target_prefix, "install", name)
|
||||
|
||||
def get_install_deps_target(name):
|
||||
return os.path.join(target_prefix, ".install-deps", name)
|
||||
return os.path.join(target_prefix, "install-deps", name)
|
||||
|
||||
# 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.
|
||||
|
@ -728,13 +733,22 @@ def get_install_deps_target(name):
|
|||
)
|
||||
|
||||
# Root specs without deps are the prereqs for the environment target
|
||||
root_install_targets = [get_install_target(h.dag_hash()) for h in roots]
|
||||
root_install_targets = [get_install_target(h.format("{name}-{version}-{hash}")) for h in roots]
|
||||
|
||||
# Cleanable targets...
|
||||
cleanable_targets = [get_install_target(h) for h, _, _, _ in make_targets.adjacency_list]
|
||||
cleanable_targets.extend(
|
||||
[get_install_deps_target(h) for h, _, _, _ in make_targets.adjacency_list]
|
||||
)
|
||||
# All install and install-deps targets
|
||||
all_install_related_targets = []
|
||||
|
||||
# Convenience shortcuts: ensure that `make install/pkg-version-hash` triggers
|
||||
# <absolute path to env>/.spack-env/makedeps/install/pkg-version-hash in case
|
||||
# we don't have a custom make target prefix.
|
||||
phony_convenience_targets = []
|
||||
|
||||
for tgt, _, _, _, _ in make_targets.adjacency_list:
|
||||
all_install_related_targets.append(get_install_target(tgt))
|
||||
all_install_related_targets.append(get_install_deps_target(tgt))
|
||||
if args.make_target_prefix is None:
|
||||
phony_convenience_targets.append(os.path.join("install", tgt))
|
||||
phony_convenience_targets.append(os.path.join("install-deps", tgt))
|
||||
|
||||
buf = io.StringIO()
|
||||
|
||||
|
@ -745,15 +759,17 @@ def get_install_deps_target(name):
|
|||
"all_target": get_target("all"),
|
||||
"env_target": get_target("env"),
|
||||
"clean_target": get_target("clean"),
|
||||
"cleanable_targets": " ".join(cleanable_targets),
|
||||
"all_install_related_targets": " ".join(all_install_related_targets),
|
||||
"root_install_targets": " ".join(root_install_targets),
|
||||
"dirs_target": get_target("dirs"),
|
||||
"environment": env.path,
|
||||
"install_target": get_target(".install"),
|
||||
"install_deps_target": get_target(".install-deps"),
|
||||
"install_target": get_target("install"),
|
||||
"install_deps_target": get_target("install-deps"),
|
||||
"any_hash_target": get_target("%"),
|
||||
"jobserver_support": "+" if args.jobserver else "",
|
||||
"adjacency_list": make_targets.adjacency_list,
|
||||
"phony_convenience_targets": " ".join(phony_convenience_targets),
|
||||
"target_prefix": target_prefix,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
SPACK ?= spack
|
||||
SPACK_INSTALL_FLAGS ?=
|
||||
|
||||
.PHONY: {{ all_target }} {{ clean_target }}
|
||||
|
||||
|
@ -10,27 +11,37 @@ SPACK ?= spack
|
|||
{{ dirs_target }}:
|
||||
@mkdir -p {{ install_target }} {{ install_deps_target }}
|
||||
|
||||
{% if phony_convenience_targets %}
|
||||
.PHONY: {{ phony_convenience_targets }}
|
||||
{% endif %}
|
||||
|
||||
# The spack install commands are of the form:
|
||||
# spack -e my_env --no-add --only=package --only=concrete /hash
|
||||
# This is an involved way of expressing that Spack should only install
|
||||
# an individual concrete spec from the environment without deps.
|
||||
{{ install_target }}/%: {{ install_deps_target }}/% | {{ dirs_target }}
|
||||
{{ jobserver_support }}$(SPACK) -e '{{ environment }}' install $(SPACK_BUILDCACHE_FLAG) $(SPACK_INSTALL_FLAGS) --only-concrete --only=package --no-add /$(notdir $@) # $(SPEC)
|
||||
{{ install_target }}/%: | {{ dirs_target }}
|
||||
{{ jobserver_support }}$(SPACK) -e '{{ environment }}' install $(SPACK_BUILDCACHE_FLAG) $(SPACK_INSTALL_FLAGS) --only-concrete --only=package --no-add /$(HASH) # $(SPEC)
|
||||
@touch $@
|
||||
|
||||
{{ install_deps_target }}/%: | {{ dirs_target }}
|
||||
@touch $@
|
||||
|
||||
# Set a human-readable SPEC variable for each target that has a hash
|
||||
{% for (parent, name, build_cache, _) in adjacency_list -%}
|
||||
{% for (parent, _, hash, name, build_cache) in adjacency_list -%}
|
||||
{{ any_hash_target }}/{{ parent }}: HASH = {{ hash }}
|
||||
{{ any_hash_target }}/{{ parent }}: SPEC = {{ name }}
|
||||
{{ any_hash_target }}/{{ parent }}: SPACK_BUILDCACHE_FLAG = {{ build_cache }}
|
||||
{% endfor %}
|
||||
|
||||
# The Spack DAG expressed in targets:
|
||||
{% for (parent, _, _, prereqs) in adjacency_list -%}
|
||||
{% for (parent, prereqs, _, _, _) in adjacency_list -%}
|
||||
{{ install_target }}/{{ parent }}: {{ install_deps_target }}/{{ parent }}
|
||||
{{ install_deps_target }}/{{ parent }}: {{ prereqs }}
|
||||
{% if phony_convenience_targets %}
|
||||
install/{{ parent }}: {{ install_target }}/{{ parent }}
|
||||
install-deps/{{ parent }}: {{ install_deps_target }}/{{ parent }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{{ clean_target }}:
|
||||
rm -rf {{ env_target }} {{ cleanable_targets }}
|
||||
rm -rf {{ env_target }} {{ all_install_related_targets }}
|
||||
|
|
Loading…
Reference in a new issue