diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index 0e263d22d86..b602b431a17 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -3201,12 +3201,13 @@ def define_runtime_constraints(self) -> List[spack.spec.Spec]: # FIXME (compiler as nodes): think of using isinstance(compiler_cls, WrappedCompiler) # Add a dependency on the compiler wrapper - recorder("*").depends_on( - "compiler-wrapper", - when=f"%{compiler.name}@{compiler.versions}", - type="build", - description=f"Add the compiler wrapper when using {compiler}", - ) + for language in ("c", "cxx", "fortran"): + recorder("*").depends_on( + "compiler-wrapper", + when=f"%[virtuals={language}] {compiler.name}@{compiler.versions}", + type="build", + description=f"Add the compiler wrapper when using {compiler} for {language}", + ) if not using_libc_compatibility(): continue @@ -3601,11 +3602,9 @@ def rule_body_from(self, when_spec: "spack.spec.Spec") -> Tuple[str, str]: # (avoid adding virtuals everywhere, if a single edge needs it) _, provider, virtual = clause.args clause.args = "virtual_on_edge", node_placeholder, provider, virtual - body_str = ( - f" {f',{os.linesep} '.join(str(x) for x in body_clauses)},\n" - f" not external({node_variable}),\n" - f" not runtime(Package)" - ).replace(f'"{node_placeholder}"', f"{node_variable}") + body_str = ",\n".join(f" {x}" for x in body_clauses) + body_str += f",\n not external({node_variable})" + body_str = body_str.replace(f'"{node_placeholder}"', f"{node_variable}") for old, replacement in when_substitutions.items(): body_str = body_str.replace(old, replacement) return body_str, node_variable diff --git a/var/spack/repos/builtin.mock/packages/gcc/package.py b/var/spack/repos/builtin.mock/packages/gcc/package.py index d029a522681..59ae7077cc4 100644 --- a/var/spack/repos/builtin.mock/packages/gcc/package.py +++ b/var/spack/repos/builtin.mock/packages/gcc/package.py @@ -81,19 +81,13 @@ def runtime_constraints(cls, *, spec, pkg): spec: spec that will inject runtime dependencies pkg: object used to forward information to the solver """ - pkg("*").depends_on( - "gcc-runtime", - when="%gcc", - type="link", - description="If any package uses %gcc, it depends on gcc-runtime", - ) - pkg("*").depends_on( - f"gcc-runtime@{str(spec.version)}:", - when=f"^[deptypes=build] {spec.name}@{spec.versions}", - type="link", - description=f"If any package uses %{str(spec)}, " - f"it depends on gcc-runtime@{str(spec.version)}:", - ) + for language in ("c", "cxx", "fortran"): + pkg("*").depends_on( + f"gcc-runtime@{spec.version}:", + when=f"%[virtuals={language}] {spec.name}@{spec.versions}", + type="link", + description=f"Inject gcc-runtime when gcc is used as a {language} compiler", + ) gfortran_str = "libgfortran@5" if spec.satisfies("gcc@:6"): @@ -104,18 +98,14 @@ def runtime_constraints(cls, *, spec, pkg): for fortran_virtual in ("fortran-rt", gfortran_str): pkg("*").depends_on( fortran_virtual, - when=f"^[virtuals=fortran deptypes=build] {spec.name}@{spec.versions}", + when=f"%[virtuals=fortran] {spec.name}@{spec.versions}", type="link", description=f"Add a dependency on '{gfortran_str}' for nodes compiled with " - f"{str(spec)} and using the 'fortran' language", + f"{spec} and using the 'fortran' language", ) # The version of gcc-runtime is the same as the %gcc used to "compile" it - pkg("gcc-runtime").requires( - f"@{str(spec.versions)}", when=f"^[deptypes=build] {spec.name}@{spec.versions}" - ) + pkg("gcc-runtime").requires(f"@{spec.versions}", when=f"%{spec.name}@{spec.versions}") # If a node used %gcc@X.Y its dependencies must use gcc-runtime@:X.Y # (technically @:X is broader than ... <= @=X but this should work in practice) - pkg("*").propagate( - f"gcc@:{str(spec.version)}", when=f"^[deptypes=build] {spec.name}@{spec.versions}" - ) + pkg("*").propagate(f"gcc@:{spec.version}", when=f"%{spec.name}@{spec.versions}") diff --git a/var/spack/repos/builtin/packages/gcc/package.py b/var/spack/repos/builtin/packages/gcc/package.py index 5e910e89e9e..5626d6f9f0a 100644 --- a/var/spack/repos/builtin/packages/gcc/package.py +++ b/var/spack/repos/builtin/packages/gcc/package.py @@ -1158,19 +1158,13 @@ def runtime_constraints(cls, *, spec, pkg): spec: spec that will inject runtime dependencies pkg: object used to forward information to the solver """ - pkg("*").depends_on( - "gcc-runtime", - when="%gcc", - type="link", - description="If any package uses %gcc, it depends on gcc-runtime", - ) - pkg("*").depends_on( - f"gcc-runtime@{str(spec.version)}:", - when=f"^[deptypes=build] {spec.name}@{spec.versions}", - type="link", - description=f"If any package uses %{str(spec)}, " - f"it depends on gcc-runtime@{str(spec.version)}:", - ) + for language in ("c", "cxx", "fortran"): + pkg("*").depends_on( + f"gcc-runtime@{spec.version}:", + when=f"%[virtuals={language}] {spec.name}@{spec.versions}", + type="link", + description=f"Inject gcc-runtime when gcc is used as a {language} compiler", + ) gfortran_str = "libgfortran@5" if spec.satisfies("gcc@:6"): @@ -1181,21 +1175,17 @@ def runtime_constraints(cls, *, spec, pkg): for fortran_virtual in ("fortran-rt", gfortran_str): pkg("*").depends_on( fortran_virtual, - when=f"^[virtuals=fortran deptypes=build] {spec.name}@{spec.versions}", + when=f"%[virtuals=fortran] {spec.name}@{spec.versions}", type="link", description=f"Add a dependency on '{gfortran_str}' for nodes compiled with " - f"{str(spec)} and using the 'fortran' language", + f"{spec} and using the 'fortran' language", ) # The version of gcc-runtime is the same as the %gcc used to "compile" it - pkg("gcc-runtime").requires( - f"@{str(spec.versions)}", when=f"^[deptypes=build] {spec.name}@{spec.versions}" - ) + pkg("gcc-runtime").requires(f"@{spec.versions}", when=f"%{spec.name}@{spec.versions}") # If a node used %gcc@X.Y its dependencies must use gcc-runtime@:X.Y # (technically @:X is broader than ... <= @=X but this should work in practice) - pkg("*").propagate( - f"gcc@:{str(spec.version)}", when=f"^[deptypes=build] {spec.name}@{spec.versions}" - ) + pkg("*").propagate(f"gcc@:{spec.version}", when=f"%{spec.name}@{spec.versions}") def _post_buildcache_install_hook(self): if not self.spec.satisfies("platform=linux"): diff --git a/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py b/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py index 9432b19d660..eb70fef136d 100644 --- a/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py +++ b/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py @@ -655,38 +655,32 @@ def determine_variants(cls, exes, version_str): @classmethod def runtime_constraints(cls, *, spec, pkg): - pkg("*").depends_on( - "intel-oneapi-runtime", - when="%oneapi", - type="link", - description="If any package uses %oneapi, it depends on intel-oneapi-runtime", - ) - pkg("*").depends_on( - f"intel-oneapi-runtime@{str(spec.version)}:", - when=f"^[deptypes=build] {spec.name}@{spec.versions}", - type="link", - description=f"If any package uses %{str(spec)}, " - f"it depends on intel-oneapi-runtime@{str(spec.version)}:", - ) + for language in ("c", "cxx", "fortran"): + pkg("*").depends_on( + f"intel-oneapi-runtime@{spec.version}:", + when=f"%[virtuals={language}] {spec.name}@{spec.versions}", + type="link", + description="Inject intel-oneapi-runtime when oneapi is used as " + f"a {language} compiler", + ) for fortran_virtual in ("fortran-rt", "libifcore@5"): pkg("*").depends_on( fortran_virtual, - when=f"^[virtuals=fortran deptypes=build] {spec.name}@{spec.versions}", + when=f"%[virtuals=fortran] {spec.name}@{spec.versions}", type="link", - description=f"Add a dependency on 'libifcore' for nodes compiled with " - f"{str(spec)} and using the 'fortran' language", + description="Add a dependency on 'libifcore' for nodes compiled with " + f"{spec.name}@{spec.versions} and using the 'fortran' language", ) # The version of intel-oneapi-runtime is the same as the %oneapi used to "compile" it pkg("intel-oneapi-runtime").requires( - f"@{str(spec.versions)}", when=f"^[deptypes=build] {spec.name}@{spec.versions}" + f"@{spec.versions}", when=f"%{spec.name}@{spec.versions}" ) - # If a node used %intel-oneapi=runtime@X.Y its dependencies must use @:X.Y + # If a node used %intel-oneapi-runtime@X.Y its dependencies must use @:X.Y # (technically @:X is broader than ... <= @=X but this should work in practice) pkg("*").propagate( - f"intel-oneapi-compilers@:{str(spec.version)}", - when=f"^[deptypes=build] {spec.name}@{spec.versions}", + f"intel-oneapi-compilers@:{spec.version}", when=f"%{spec.name}@{spec.versions}" ) def _cc_path(self):