Skip to content

Conversation

@kennyweiss
Copy link
Member

@kennyweiss kennyweiss commented Dec 12, 2025

Summary

  • This PR adds a components variant to Axom's spack package to allow users to provide an explicit list of components to enable.
    • By default (when components is not provided, or when components=all) all components are enabled
    • All components (other than core, which is always on) can be disabled with components=none

- The components are validated during the initconfig stage -- if the component's required dependencies are not enabled, we get a SpackError indicating the missing dependencies. We also validate against the component's required package dependencies

  • We use Spack's requires/conflicts mechanisms to any missing inter-component or package dependencies. E.g. since inlet depends on sidre and conduit (among others), adding components=inlet to the spec will enable sidre and conduit. Thanks @tgamblin for the suggestions!

  • This PR also adds a conduit variant (enabled by default). Previously, conduit was always required

  • This PR also deprecates the profiling variant in favor of new adiak and caliper variants.

  • Resolves Sina Spack Variant #1698 (tag @ldowen)

  • Related to What extra configuration tests are needed? #1722

Some test runs (updated after improving validation)

Run w/ components=inlet:

./scripts/uberenv/uberenv.py --spec "~hdf5~c2c~mfem~raja~umpire~scr~lua+devtools~fortran~mpi~openmp components=inlet  %clang_19"

Concretized after adding dependencies on primal, sidre and slic (also adds +conduit, but that was on by default):

	axom@develop
		~adiak~c2c~caliper+conduit+cpp14~cuda+devtools+examples~fortran~hdf5+int64~ipo~lua~mfem~mpi~opencascade~openmp+python~raja~rocm~scr+shared+tools+tutorials~umpire
		components:=inlet,primal,sidre,slic

Invalid run: components=inlets ~conduit:

 >./scripts/uberenv/uberenv.py --spec "~hdf5~c2c~mfem~raja~umpire~scr~lua+devtools~fortran~mpi~openmp~conduit components=inlet  %clang_19"

==> Error: failed to concretize

`axom@develop~c2c~conduit+devtools~fortran~hdf5~lua~mfem~mpi~openmp~raja~scr~umpire components=inlet %[when='%fortran'] fortran=gcc %[when='%c'] c=clang %[when='%cxx'] cxx=clang %[when='%mpi'] mvapich2@2.3.7.clang_19` for the following reasons:
     1. cannot satisfy a requirement for package 'axom'.
[spack version: 1.0.2 (734c5db2121b01c373eed6538e452f18887e9e44)

Note: the error message doesn't explicitly note the failure as +conduit/~conduit. I'll see if spack can improve this.

Update -- we get a much better error message in spack@develop (due to this PR: spack/spack#45800)

==> Error: failed to concretize `axom@develop~c2c~conduit+devtools~fortran~hdf5~lua~mfem~mpi~openmp~raja~scr~umpire components=inlet %[when='%fortran'] fortran=gcc %[when='%c'] c=clang %[when='%cxx'] cxx=clang %[when='%mpi'] mvapich2@2.3.7.clang_19` for the following reasons:
     1. 'axom' requires conflicting variant values '~conduit' and '+conduit'
     2. 'axom' requires conflicting variant values '~conduit' and '+conduit'
        required because +conduit is a requirement for package axom when components=sina 
          required because axom@develop~c2c~conduit+devtools~fortran~hdf5~lua~mfem~mpi~openmp~raja~scr~umpire components=inlet %[when='%fortran'] fortran=gcc %[when='%c'] c=clang %[when='%cxx'] cxx=clang %[when='%mpi'] mvapich2@2.3.7.clang_19 requested explicitly 

Thanks for anticipating this @scheibelp!


Run w/ components=all:

	./scripts/uberenv/uberenv.py --spec " components=all  %clang_19"

Concretized to:

	axom@develop 
		~adiak~c2c~caliper+conduit+cpp14~cuda~devtools+examples+fortran+hdf5+int64~ipo+lua~mfem+mpi~opencascade+openmp~python+raja~rocm~scr+shared+tools+tutorials+umpire
		components:=all,bump,inlet,klee,lumberjack,mint,mir,multimat,primal,quest,sidre,sina,slam,slic,spin

Run w/ components=none:

>./scripts/uberenv/uberenv.py --spec " components=none  %clang_19"

Concretized to:

	axom@develop 
		~adiak~c2c~caliper+conduit+cpp14~cuda~devtools+examples+fortran+hdf5+int64~ipo+lua~mfem+mpi~opencascade+openmp~python+raja~rocm~scr+shared+tools+tutorials+umpire
		components:=none

@kennyweiss kennyweiss self-assigned this Dec 12, 2025
@kennyweiss kennyweiss added App Integration Issues related to integration with applications TPL Issues related to Axom's third party libraries User Request Issues related to user requests labels Dec 12, 2025
@kennyweiss kennyweiss mentioned this pull request Dec 12, 2025
when="@:0.12.0",
description="Build with hooks for Adiak/Caliper performance analysis. " \
"Deprecated -- use the adiak and/or caliper variants directly.",
)
Copy link
Member Author

Choose a reason for hiding this comment

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

The profiling variant added a dependency on adiak and caliper. Since sina has a soft dependency on adiak, I replaced it with direct variants for adiak and caliper.

Should we remove the profiling variant? In this PR I added a description that this variant in deprecated and changed the when line.

Is there a better way to do this? I noticed this open issue on spack spack/spack#38829

Copy link
Member

@adrienbernede adrienbernede Dec 15, 2025

Choose a reason for hiding this comment

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

I think deprecating before removing is the recommended way. It sends the signal that users should prepare for removal, while reducing the risk that they still use the variant at next release when you effectively remove the variant... at the cost of maintaining both for a while.

Drawback: without deprecation support like suggested in the mentioned PR, the deprecation will likely go unnoticed.

variant("tutorials", default=True, description="Build tutorials")

# Hard requirement after Axom 0.6.1
variant("cpp14", default=True, description="Build with C++14 support")
Copy link
Member Author

@kennyweiss kennyweiss Dec 12, 2025

Choose a reason for hiding this comment

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

Given that we have a hard requirement on c++17 and soon c++20, we should remove/update the cpp14 variant, but I wasn't sure about the best way to do that. E.g. do we need to keep old variants around and change the when logic?

Presumably, we should use cxxstd instead of hard-coding the language version.

I'll create an issue to track this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Update: #1741

Copy link
Member

@BradWhitlock BradWhitlock left a comment

Choose a reason for hiding this comment

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

These changes look reasonable to me. Thanks!

Comment on lines +208 to +183
depends_on("conduit+python", when="+devtools")
depends_on("conduit~python", when="~devtools")
Copy link
Member Author

Choose a reason for hiding this comment

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

@bmhan12 -- I think this conduit+python dependency on devtools is meant to be temporary.
If so, could you please add an issue to describe and track it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Tracked in issue #1742!

Comment on lines +238 to 239
# we're planning to remove support for the profiling variant, but still need to support it for now
depends_on("adiak", when="+adiak")
depends_on("caliper", when="+caliper")
with when("+profiling"):
depends_on("adiak")
depends_on("caliper+adiak~papi")

depends_on("caliper+cuda", when="+cuda")
depends_on("caliper~cuda", when="~cuda")
depends_on("caliper")

depends_on("caliper+rocm", when="+rocm")
depends_on("caliper~rocm", when="~rocm")
with when("^adiak"):
for fwd in ("mpi", "shared"):
depends_on(f"adiak+{fwd}", when=f"+{fwd}")

for dep in ["adiak", "caliper"]:
depends_on(f"{dep}+mpi", when="+mpi")
depends_on(f"{dep}~mpi", when="~mpi")
depends_on(f"{dep}+shared", when="+shared")
depends_on(f"{dep}~shared", when="~shared")
with when("^caliper"):
for fwd in ("cuda", "rocm", "mpi", "shared"):
depends_on(f"caliper+{fwd}", when=f"+{fwd}")

for val in CudaPackage.cuda_arch_values:
ext_cuda_dep = f"+cuda cuda_arch={val}"
depends_on(f"raja {ext_cuda_dep}", when=f"+raja {ext_cuda_dep}")
depends_on(f"umpire {ext_cuda_dep}", when=f"+umpire {ext_cuda_dep}")
depends_on(f"caliper {ext_cuda_dep}", when=f"+profiling {ext_cuda_dep}")
depends_on(f"caliper {ext_cuda_dep}", when=f"^caliper {ext_cuda_dep}")
depends_on(f"mfem {ext_cuda_dep}", when=f"+mfem {ext_cuda_dep}")

for val in ROCmPackage.amdgpu_targets:
ext_rocm_dep = f"+rocm amdgpu_target={val}"
depends_on(f"raja {ext_rocm_dep}", when=f"+raja {ext_rocm_dep}")
depends_on(f"umpire {ext_rocm_dep}", when=f"+umpire {ext_rocm_dep}")
depends_on(f"caliper {ext_rocm_dep}", when=f"+profiling {ext_rocm_dep}")
depends_on(f"caliper {ext_rocm_dep}", when=f"^caliper {ext_rocm_dep}")
depends_on(f"mfem {ext_rocm_dep}", when=f"+mfem {ext_rocm_dep}")
Copy link
Member Author

Choose a reason for hiding this comment

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

Could someone please double-check these changes? I was trying to support the new adiak and caliper variants as well as the old profiling one, so I changed the +foo (which checks a variant) to ^foo (which checks a dependency). It seems to work and makes sense to me, but please let me know if there's a better way to do it.

path_replacements = {}

# Validate the 'components' spec, which can selectively enable components
self._validate_component_deps()
Copy link
Member Author

Choose a reason for hiding this comment

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

Should the validation happen in initconfig? i.e. after concretization and after all of axom's dependencies have been built.

Please let me know if there's an earlier place that this can be done.

@kennyweiss kennyweiss force-pushed the feature/kweiss/component-variants branch from 0029e61 to e9d8309 Compare December 12, 2025 20:13
caliper:
require:
- spec: "~kokkos"
- spec: "~kokkos~papi"
Copy link
Member Author

Choose a reason for hiding this comment

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

I moved caliper~papi to our defaults.yaml since the previous way would impose constraints on other axom users.

Is there a reason to keep it in axom/package.py?

@kennyweiss kennyweiss requested a review from tgamblin December 15, 2025 03:29
@tgamblin
Copy link
Member

The axom package looks way better (160 added lines, nearly all declarative vs. 242 in the first revision with custom consistency checking). We can prioritize improving the error messages for package requirements in Spack.

Comment on lines +276 to +277
requires("components=slic,spin,primal", when="components=bump")
requires("components=sidre,slic,primal", when="components=inlet")
Copy link
Member

@adrienbernede adrienbernede Dec 15, 2025

Choose a reason for hiding this comment

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

Because I never used it, I guess it is trivial that spack will merge the required components lists ?

This can be tested by concretizing axom components=bump,inlet, which should activate bump,inlet,sidre,slic,spin,primal.

Based on documentation, I have no doubt multi-valued variants are mergeable, but documentation on requires is not explicit on this possibility in that particular case.

Comment on lines 553 to 559
if spec.satisfies("+profiling"):
dep_dir = get_spec_path(spec, "adiak", path_replacements)
entries.append(cmake_cache_path("ADIAK_DIR", dep_dir))

dep_dir = get_spec_path(spec, "caliper", path_replacements)
entries.append(cmake_cache_path("CALIPER_DIR", dep_dir))

Copy link
Member

Choose a reason for hiding this comment

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

If I read correctly, +profiling will still add ^adiak and caliper, but not +adiak and +caliper.
Therefore, if you remove the above section, I wonder how ADIAK_DIR and CALIPER_DIR will be set.
Unless they are replaced by TPL_ROOT ?

Copy link
Member

Choose a reason for hiding this comment

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

I agree that if you use a variant to force a conditional dep, you should force the variant here and not the dep (doing it this way introduces two ways to get the dependency, when you really want ^name to be satisfied if and only if +name is also satisfied)

Copy link
Member

@rhornung67 rhornung67 left a comment

Choose a reason for hiding this comment

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

Thank you @kennyweiss

@kennyweiss
Copy link
Member Author

kennyweiss commented Dec 19, 2025

I'm getting some vague error messages from spack with +profiling:

>./scripts/uberenv/uberenv.py --spec "+profiling~conduit~hdf5~umpire~raja components=none %clang_19"

==> Error: failed to concretize `axom@develop~conduit~hdf5+profiling~raja~umpire components=none %[when='%fortran'] fortran=gcc %[when='%c'] c=clang %[when='%cxx'] cxx=clang %[when='%mpi'] mvapich2@2.3.7.clang_19` for the following reasons:
     1. Cannot satisfy 'axom@develop' 1(0.12.0)
     2. Cannot satisfy 'axom@=develop' 1(0.12.0)
     3. Cannot satisfy 'axom@develop' 4(0.12.0)
        required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
          required because axom@develop~conduit~hdf5+profiling~raja~umpire components=none %[when='%fortran'] fortran=gcc %[when='%c'] c=clang %[when='%cxx'] cxx=clang %[when='%mpi'] mvapich2@2.3.7.clang_19 requested explicitly 
          required because Conditional dependency in ^[when=%fortran]gcc 
            required because Conditional dependency in ^[when=%c]llvm 
              required because Conditional dependency in ^[when=%cxx]llvm 
            required because Conditional dependency in ^[when=%cxx]llvm 
          required because Conditional dependency in ^[when=%c]llvm 
          required because Conditional dependency in ^[when=%cxx]llvm 
     4. Cannot satisfy 'axom@develop' 4(0.12.0)
        required because Conditional dependency in ^[when=%cxx]llvm 
          required because axom@develop~conduit~hdf5+profiling~raja~umpire components=none %[when='%fortran'] fortran=gcc %[when='%c'] c=clang %[when='%cxx'] cxx=clang %[when='%mpi'] mvapich2@2.3.7.clang_19 requested explicitly 
          required because Conditional dependency in ^[when=%fortran]gcc 
            required because Conditional dependency in ^[when=%c]llvm 
              required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
            required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
          required because Conditional dependency in ^[when=%c]llvm 
          required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
     5. Cannot satisfy 'axom@develop' 4(0.12.0)
        required because Conditional dependency in ^[when=%c]llvm 
          required because axom@develop~conduit~hdf5+profiling~raja~umpire components=none %[when='%fortran'] fortran=gcc %[when='%c'] c=clang %[when='%cxx'] cxx=clang %[when='%mpi'] mvapich2@2.3.7.clang_19 requested explicitly 
          required because Conditional dependency in ^[when=%fortran]gcc 
            required because Conditional dependency in ^[when=%cxx]llvm 
              required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
            required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
          required because Conditional dependency in ^[when=%cxx]llvm 
          required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
     6. Cannot satisfy 'axom@develop' 4(0.12.0)
        required because Conditional dependency in ^[when=%fortran]gcc 
          required because axom@develop~conduit~hdf5+profiling~raja~umpire components=none %[when='%fortran'] fortran=gcc %[when='%c'] c=clang %[when='%cxx'] cxx=clang %[when='%mpi'] mvapich2@2.3.7.clang_19 requested explicitly 
          required because Conditional dependency in ^[when=%c]llvm 
            required because Conditional dependency in ^[when=%cxx]llvm 
              required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
            required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
          required because Conditional dependency in ^[when=%cxx]llvm 
          required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
     7. Cannot satisfy 'axom@develop' 4(0.12.0)
        required because axom@develop~conduit~hdf5+profiling~raja~umpire components=none %[when='%fortran'] fortran=gcc %[when='%c'] c=clang %[when='%cxx'] cxx=clang %[when='%mpi'] mvapich2@2.3.7.clang_19 requested explicitly 
     8. Cannot satisfy 'axom@=develop' 4(0.12.0)
        required because axom is a develop spec 
          required because axom@develop~conduit~hdf5+profiling~raja~umpire components=none %[when='%fortran'] fortran=gcc %[when='%c'] c=clang %[when='%cxx'] cxx=clang %[when='%mpi'] mvapich2@2.3.7.clang_19 requested explicitly 
          required because Conditional dependency in ^[when=%fortran]gcc 
            required because Conditional dependency in ^[when=%c]llvm 
              required because Conditional dependency in ^[when=%cxx]llvm 
                required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
              required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
            required because Conditional dependency in ^[when=%cxx]llvm 
            required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
          required because Conditional dependency in ^[when=%c]llvm 
          required because Conditional dependency in ^[when=%cxx]llvm 
          required because Conditional dependency in ^[when=%mpi]mvapich2@2.3.7.clang_19 
[spack version: 1.2.0.dev0 (06973ac962e73338485ceb84a4febd940155bb89)

It feels like spack thinks it's telling me 8 different things, but all I'm getting from it
is that there's something that can't be satisfied :(


Update -- I found the problem! I was trying to test the profiling variant against axom@develop, and I explicitly said it shouldn't work past axom@0.12:

variant(
    "profiling",
    default=False,
    when="@:0.12.0",      ## <----  Version restriction here
    ...
)

So, spack was doing the right thing, but it didn't tell me why.

@scheibelp @tgamblin @becker33 -- this seems like a good candidate for improved Spack error messages.

The components can either be "all" (default), which enables all Axom components,
or it can be a comma separated list of components, e.g. 'components=slic,sidre'.

If components is not specified, all components will be enabled.
Use 'components=none' to disable all components (other than core, which is always on).

We validate the list to ensure that all hard dependencies of the requested
components are enabled, e.g. 'components=inlet,sidre,slic' would pass,
but 'components=inlet' would fail since inlet depends on sidre.
And adds a fix to allow Axom to configure with '~conduit'
…g "profiling" variant

Users have requested the option to enable/disable adiak and caliper separately.
I left in support for the "profiling" variant for now.
sina's tests use slic
The mir component no longer has a hard dependency on raja or umpire.
We now add any missing components and dependencies to satisfy required dependencies.
E.g. if `components=sina`, we will add `slic` and `conduit` to ensure a valid configuration.

Credits: Thanks @tgamblin for the suggestions!
…conduit

Specifically, we skip some of the entries, such as "lua",  which can be
in a different installation path. We also take the directory of the main package (axom-*)
since the library we're checking might start with the same letter (e.g. adiak).
@kennyweiss kennyweiss force-pushed the feature/kweiss/component-variants branch from 8f4c24b to 6527843 Compare December 19, 2025 19:04
@kennyweiss kennyweiss merged commit 1fdc43d into develop Dec 19, 2025
15 checks passed
@kennyweiss kennyweiss deleted the feature/kweiss/component-variants branch December 19, 2025 20:47
@chapman39 chapman39 mentioned this pull request Dec 19, 2025
17 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

App Integration Issues related to integration with applications TPL Issues related to Axom's third party libraries User Request Issues related to user requests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sina Spack Variant