Skip to content

spack info: show conditional dependencies and licenses; allow filtering#51137

Merged
tgamblin merged 13 commits intodevelopfrom
better-dependency-info
Oct 19, 2025
Merged

spack info: show conditional dependencies and licenses; allow filtering#51137
tgamblin merged 13 commits intodevelopfrom
better-dependency-info

Conversation

@tgamblin
Copy link
Copy Markdown
Member

@tgamblin tgamblin commented Aug 11, 2025

spack info has always shown dependencies grouped by type, but not conditional dependency information. While conditional deps are often very relevant, users have to read raw package files to see them.

This PR generifies the code used to display variants and uses it for dependencies and licenses too. As with variants, dependencies are shown grouped by conditions, with unconditional dependencies first. Users can supply the --by-name argument to list ordered first by name instead.

--by-name is meant to replace --variants-by-name. --variants-by-name still works but is suppressed from help and has the same function as --by-name.

spack info gcc before and after:

Screenshot 2025-08-10 at 10 28 36 PM Screenshot 2025-08-10 at 10 29 20 PM

As there is increasingly more information displayed by spack info, it can be useful to filter out variants, dependencies, versions, etc. that are irrelevant to certain package configurations.

This PR also allows spack info to take a spec instead of a package name, so users can run, e.g.:

to get only information relevant to 1.14.x versions of hdf5. Versions, dependencies, variants, and licenses are now filtered based on the input spec.

Before and after:

Screenshot 2025-08-10 at 10 33 03 PM Screenshot 2025-08-10 at 10 33 22 PM
  • generify when-grouping code to use a Formatter class
  • Rewrite variant code to use generic formatter.
  • Rewrite dependency code to use generic formatter.
  • Rewrite license code to use generic formatter.
  • add full type annotations to cmd/info.py
  • allow spack info to take a spec instead of a package name
  • filter spack info output versions, dependencies, variants, and licenses based on the input spec
  • tests

@tgamblin tgamblin force-pushed the better-dependency-info branch 3 times, most recently from 3db9053 to 29dc0ea Compare August 14, 2025 08:01
@alalazo alalazo self-assigned this Aug 14, 2025
@alalazo alalazo self-requested a review August 14, 2025 16:48
Copy link
Copy Markdown
Member

@alalazo alalazo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks great. I think there is an issue with single-value variant. For instance check the dependencies of:

$ spack info zlib-ng build_system=autotools

vs.

$ spack info zlib-ng build_system:=autotools

Since build_system is multi=False specifying a value prevents other values to be possible.

Another issue is with conditional variants. For instance, in all CudaPackages, if we specify:

$ spack info trilinos~cuda

we continue to see pages of cuda_arch, even if that variant is gated on +cuda.

Finally, just a comment on colors (disregard this if you don't agree). I wouldn't use red for run dependencies, cause red is usually associated with failures. Maybe yellow?

Screenshot from 2025-08-15 09-36-52
I'll dive into code next.

Copy link
Copy Markdown
Member

@alalazo alalazo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comments, and two hints on the variant issues.

@haampie
Copy link
Copy Markdown
Member

haampie commented Aug 28, 2025

Does this fix #51222?

@tgamblin
Copy link
Copy Markdown
Member Author

I would say that it is in the spirit of #51222, in that it allows filtering by spec, but it doesn't exactly fix it b/c it doesn't address filtering by things like --phases or other metadata that's not on the spec.

I think a refactor towards something more general like --show versions,phases is in order (as there is a constantly growing number of sections). The current args are inconsistent as some of them are positive (--phases) and some of them are negative (--no-dependencies). I would rather just let the user say what they want.

@tgamblin
Copy link
Copy Markdown
Member Author

tgamblin commented Sep 29, 2025

@alalazo - I apparently wasn't in the loop with you and @haampie on the review of #35681, but in testing this I noticed that this code breaks the spack info filtering here for variant and dependency conditions that include versions, because spack.fetch_strategy.for_package_version() is actually modifying pkg.spec.

Does it have to do that? Can we not defensively copy in spack.fetch_strategy.for_package_version()? Why does it need to mutate the spec on the passed in package?

@tgamblin tgamblin force-pushed the better-dependency-info branch 5 times, most recently from 4b79bce to 26cb54f Compare October 14, 2025 20:43
@tgamblin tgamblin requested a review from alalazo October 14, 2025 20:59
@tgamblin
Copy link
Copy Markdown
Member Author

@alalazo: This PR is getting fairly large now but it's much improved. The commits are, I think, well factored into independent fixes/features now.

  1. Fixing all the spec stuff above requires knowing something about the package. I was using Spec.intersects(), which says whether two constraints may coincide, but it knows too little about variants to do what you want, e.g., to know that a variant is only ever single-valued, or to know that the presence of a variant that's conditional on the value of some single-valued variant implies that no other values for that variant are allowable. I put in some static analysis in a new method on the Package to handle these cases, and it allows for much more aggressive filtering. e.g., if you ask for generator=make, it knows to rule out dependencies with build_system=autotools.
  2. I added something that's maybe controversial -- if there are lots of deps, Spack now recommends getting rid of the bigger clumps of them by toggling certain variants at the end of spack info. I may remove this reminder later, but for now it's there to help with the many packages that use loops to set up locked cuda and/or rocm dependencies. I think this will ultimately be made much less necessary by Allow packages to depend on my.version, variant=my.value, etc. #41700, (where lots of rules will be reduced to something like `depends_on("dep cuda_arch={self.variants['cuda_arch'].value}"), but that is not ready yet.
  3. I made text wrapping in spack info color-aware, which saves a space and avoids weird formatting.
  4. I added some code to handle cases where the dependency spec is very long, e.g. some dependencies on boost have many variants. Instead of cramming the deptypes against the right margin, one letter per line, spack info now reserves 30 cols for the values in variant definitions, and it just puts them on the next line if the dep spec is too long.

See what you think and let me know if this is more usable.

@tgamblin tgamblin force-pushed the better-dependency-info branch 6 times, most recently from 79df9eb to d8157f0 Compare October 16, 2025 02:14
This is a hack while we figure out why it's doing this

Signed-off-by: Todd Gamblin <[email protected]>
@tgamblin tgamblin force-pushed the better-dependency-info branch 2 times, most recently from 2de8ce1 to 179ada9 Compare October 17, 2025 06:02
`spack info` has always shown dependencies grouped by type, but not
conditional dependency information.  This generifies the code used
to display variants and uses it for dependencies as well.

As with variants, dependencies are shown grouped by conditions, with
unconditional dependencies first.

- [x] generify when-grouping code to use a `Formatter` class
- [x] Rewrite variant code to use generic formatter.
- [x] Rewrite dependency code to use generic formatter.
- [x] add full type annotations to `cmd/info.py`

Signed-off-by: Todd Gamblin <[email protected]>
`spack info` has historically accepted a package name but not a spec.

Now that it shows lots of conditional information, it can be useful
to filter out variants, dependencies, versions, etc. that are irrelevant
to certain package configurations.

- [x] allow `spack info` to take a spec instead of a package name
- [x] filter `spack info` output versions, dependencies, variants, and
      licenses based on the input spec

Signed-off-by: Todd Gamblin <[email protected]>
After adding dependencies, it is often much clearer to list info output by name, since
there can be a very large number of dependency conditions in the output.

`--by-when` is still an option, and the `--by-name` argument is still present even
though it is the default.

Signed-off-by: Todd Gamblin <[email protected]>
…itions

This will advise users to add, e.g., `~cuda` and `~rocm` when output for a package is
very long. This makes the feature more discoverable.

Signed-off-by: Todd Gamblin <[email protected]>
For complex dependencies like boost, there may be many required variants. Ensure that
they don't push deptypes off the edge of the screen by setting a min width and showing
deptypes on the next line when the dependency spec is too long.

Signed-off-by: Todd Gamblin <[email protected]>
- need to use long_spec for this

Signed-off-by: Todd Gamblin <[email protected]>
@tgamblin tgamblin force-pushed the better-dependency-info branch from 179ada9 to 6b28358 Compare October 17, 2025 06:04
@tgamblin
Copy link
Copy Markdown
Member Author

Finally, just a comment on colors (disregard this if you don't agree). I wouldn't use red for run dependencies, cause red is usually associated with failures. Maybe yellow?

I went with blue and also fixed a couple bugs. This should be all done.

Copy link
Copy Markdown
Member

@alalazo alalazo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use cases pointed out in the previous review have been addressed 💯 Only minor comments that we can leave for a following PR.

@tgamblin tgamblin merged commit 20d4a0a into develop Oct 19, 2025
33 checks passed
@tgamblin tgamblin deleted the better-dependency-info branch October 19, 2025 21:48
@tgamblin tgamblin mentioned this pull request Oct 20, 2025
@tgamblin tgamblin added this to the v1.1.0 milestone Nov 14, 2025
tgamblin added a commit that referenced this pull request Nov 15, 2025
#51137 displays `when` conditions for dependencies, but it doesn't
display direct or transitive dependencies in conditions. This is
used frequently for things like

* `when="^[email protected]:"`: optional deps for particular pythons
* `when="%clang@34:"`: optional deps depending on build compiler

- [x] change format for when from `Spec.format()` to `_long_spec()`
- [x] add a test

Signed-off-by: Todd Gamblin <[email protected]>
alalazo pushed a commit that referenced this pull request Nov 21, 2025
…51588)

#51137 displays `when` conditions for dependencies, but it doesn't
display direct or transitive dependencies in conditions. This is
used frequently for things like

* `when="^[email protected]:"`: optional deps for particular pythons
* `when="%clang@34:"`: optional deps depending on build compiler

- [x] change format for when from `Spec.format()` to `_long_spec()`
- [x] add a test

Signed-off-by: Todd Gamblin <[email protected]>
psakievich pushed a commit to psakievich/spack that referenced this pull request Dec 1, 2025
…pack#51588)

spack#51137 displays `when` conditions for dependencies, but it doesn't
display direct or transitive dependencies in conditions. This is
used frequently for things like

* `when="^[email protected]:"`: optional deps for particular pythons
* `when="%clang@34:"`: optional deps depending on build compiler

- [x] change format for when from `Spec.format()` to `_long_spec()`
- [x] add a test

Signed-off-by: Todd Gamblin <[email protected]>
@becker33 becker33 mentioned this pull request Jan 10, 2026
becker33 pushed a commit that referenced this pull request Jan 10, 2026
…51588)

#51137 displays `when` conditions for dependencies, but it doesn't
display direct or transitive dependencies in conditions. This is
used frequently for things like

* `when="^[email protected]:"`: optional deps for particular pythons
* `when="%clang@34:"`: optional deps depending on build compiler

- [x] change format for when from `Spec.format()` to `_long_spec()`
- [x] add a test

Signed-off-by: Todd Gamblin <[email protected]>
becker33 pushed a commit that referenced this pull request Jan 11, 2026
…51588)

#51137 displays `when` conditions for dependencies, but it doesn't
display direct or transitive dependencies in conditions. This is
used frequently for things like

* `when="^[email protected]:"`: optional deps for particular pythons
* `when="%clang@34:"`: optional deps depending on build compiler

- [x] change format for when from `Spec.format()` to `_long_spec()`
- [x] add a test

Signed-off-by: Todd Gamblin <[email protected]>
Signed-off-by: Gregory Becker <[email protected]>
becker33 pushed a commit that referenced this pull request Jan 15, 2026
…51588)

#51137 displays `when` conditions for dependencies, but it doesn't
display direct or transitive dependencies in conditions. This is
used frequently for things like

* `when="^[email protected]:"`: optional deps for particular pythons
* `when="%clang@34:"`: optional deps depending on build compiler

- [x] change format for when from `Spec.format()` to `_long_spec()`
- [x] add a test

Signed-off-by: Todd Gamblin <[email protected]>
Signed-off-by: Gregory Becker <[email protected]>
vjranagit pushed a commit to vjranagit/spack that referenced this pull request Jan 18, 2026
…pack#51588)

spack#51137 displays `when` conditions for dependencies, but it doesn't
display direct or transitive dependencies in conditions. This is
used frequently for things like

* `when="^[email protected]:"`: optional deps for particular pythons
* `when="%clang@34:"`: optional deps depending on build compiler

- [x] change format for when from `Spec.format()` to `_long_spec()`
- [x] add a test

Signed-off-by: Todd Gamblin <[email protected]>
Signed-off-by: Gregory Becker <[email protected]>
becker33 pushed a commit that referenced this pull request Jan 22, 2026
…51588)

#51137 displays `when` conditions for dependencies, but it doesn't
display direct or transitive dependencies in conditions. This is
used frequently for things like

* `when="^[email protected]:"`: optional deps for particular pythons
* `when="%clang@34:"`: optional deps depending on build compiler

- [x] change format for when from `Spec.format()` to `_long_spec()`
- [x] add a test

Signed-off-by: Todd Gamblin <[email protected]>
Signed-off-by: Gregory Becker <[email protected]>
becker33 pushed a commit that referenced this pull request Jan 26, 2026
…51588)

#51137 displays `when` conditions for dependencies, but it doesn't
display direct or transitive dependencies in conditions. This is
used frequently for things like

* `when="^[email protected]:"`: optional deps for particular pythons
* `when="%clang@34:"`: optional deps depending on build compiler

- [x] change format for when from `Spec.format()` to `_long_spec()`
- [x] add a test

Signed-off-by: Todd Gamblin <[email protected]>
Signed-off-by: Gregory Becker <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants