Skip to content

cmake build system: make "generator" a variant#35552

Merged
haampie merged 2 commits intospack:developfrom
alalazo:features/generator_variant
Mar 18, 2023
Merged

cmake build system: make "generator" a variant#35552
haampie merged 2 commits intospack:developfrom
alalazo:features/generator_variant

Conversation

@alalazo
Copy link
Copy Markdown
Member

@alalazo alalazo commented Feb 17, 2023

This PR make generator a variant in CMakePackage. This allows us to declare proper dependencies on ninja and gmake, and to select generators at concretization time where it makes sense.

Modifications:

  • Add a cmake specific generator directive, that builds on variants and conflicts
  • Modify CMakePackages to use that directive

Comment on lines +52 to +72
allowed_values = ("make", "ninja")
if any(x not in allowed_values for x in names):
msg = "only 'make' and 'ninja' are allowed for CMake's 'generator' directive"
raise ValueError(msg)

default = default or names[0]
not_used = [x for x in allowed_values if x not in names]

def _values(x):
return x in allowed_values

_values.__doc__ = f"{','.join(names)}"

variant(
"generator",
default=default,
values=_values,
description="the build system generator to use",
)
for x in not_used:
conflicts(f"generator={x}")
Copy link
Copy Markdown
Member Author

@alalazo alalazo Feb 17, 2023

Choose a reason for hiding this comment

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

This works fine, but can probably cleaned a bit once we have the drop directive from #35045

@adamjstewart
Copy link
Copy Markdown
Member

The only reason we didn't do this originally was because the thing getting installed (shouldn't) change, so we didn't want to include it in the hash. But with concretizer reuse the default, maybe this doesn't matter as much.

However, the current implementation is more "make generator a directive" than "make generator a variant". The packages that set generator = "Ninja" aren't doing it because only Ninja works, they're doing it because it's faster. I'm in favor of a normal variant at the base class level, and packages shouldn't override the default. I think we should default to Ninja and only override the variant in packages that won't build with Ninja.

@alalazo
Copy link
Copy Markdown
Member Author

alalazo commented Feb 17, 2023

However, the current implementation is more "make generator a directive" than "make generator a variant".

If we have packages that only work with make or only work with ninja we want their generator to be the default, and the other one to be disallowed. That currently means a combination of variant and conflicts, and as soon as #35405 gets in of variant and drop.

The issue are the checks we do on conditional dependencies like:

depends_on("gmake", when="generator=make")

that would raise when only ninja is allowed. The generator wrapper is really a convenience for calling 2 directives with most arguments fixed.


Also forgot to mention that a added benefit is that now the dependency on gmake or ninja is explicit, so I think I can remove a few more directives in packages.

@adamjstewart
Copy link
Copy Markdown
Member

Oh, so you're saying if the base class contains:

variant("generator", values=["make", "ninja"])
depends_on("ninja", when="generator=ninja")

and a subclass contains:

variant("generator", values=["make"])

the subclass will raise audit issues because generator=ninja is invalid? That's annoying.

@alalazo
Copy link
Copy Markdown
Member Author

alalazo commented Feb 17, 2023

will raise audit issues because generator=ninja is invalid? That's annoying.

Actually it won't concretize too, because we do consistency checks also during concretization 😅

@spackbot-app spackbot-app bot added conflicts core PR affects Spack core functionality dependencies new-variant new-version python tests General test capability(ies) update-package labels Feb 17, 2023
@alalazo alalazo force-pushed the features/generator_variant branch from 88bdc67 to 7415f59 Compare February 17, 2023 21:35
@kwryankrattiger
Copy link
Copy Markdown
Contributor

This is much improved over the current model! Thanks!

@alalazo
Copy link
Copy Markdown
Member Author

alalazo commented Feb 28, 2023

@spackbot run pipeline

@spackbot-app
Copy link
Copy Markdown

spackbot-app bot commented Feb 28, 2023

I've started that pipeline for you!

@alalazo alalazo force-pushed the features/generator_variant branch from 7415f59 to e4b7561 Compare March 1, 2023 09:54
@adamjstewart
Copy link
Copy Markdown
Member

In order to avoid the aforementioned concretizer/audit check issue, could we instead use:

variant("generator", values=["make", "ninja"])
depends_on("ninja", when="generator=ninja")

in the base class and:

conflicts("generator=ninja")

in subclasses that only support make? Then we don't need to add a whole new directive just for this.

@alalazo
Copy link
Copy Markdown
Member Author

alalazo commented Mar 7, 2023

@adamjstewart For reasons related to clingo it's better if packages that only support Ninja have ninja as the default generator. That means the packages also need to override the variant. Hence, having a declarative way of setting a conflict and declaring a variant while providing only the information that is necessary.

@adamjstewart
Copy link
Copy Markdown
Member

For reasons related to clingo

This doesn't tell me a lot, but I trust you. Just trying to avoid adding more and more hyper-specific directives if we don't need them.

@alalazo
Copy link
Copy Markdown
Member Author

alalazo commented Mar 7, 2023

This doesn't tell me a lot, but I trust you. Just trying to avoid adding more and more hyper-specific directives if we don't need them.

If we don't make ninja the default, the only value possible would indeed be ninja - but with a penalty in the optimization. That can steer clingo towards weird solutions.

@alalazo alalazo force-pushed the features/generator_variant branch 2 times, most recently from 3c9e0e2 to 4cd497f Compare March 8, 2023 12:08
@alalazo alalazo force-pushed the features/generator_variant branch from 4cd497f to 679859c Compare March 16, 2023 13:10
@alalazo
Copy link
Copy Markdown
Member Author

alalazo commented Mar 17, 2023

@spackbot run pipeline

@spackbot-app
Copy link
Copy Markdown

spackbot-app bot commented Mar 17, 2023

I've started that pipeline for you!

@alalazo
Copy link
Copy Markdown
Member Author

alalazo commented Mar 17, 2023

@spackbot run pipeline

@spackbot-app
Copy link
Copy Markdown

spackbot-app bot commented Mar 17, 2023

I've started that pipeline for you!

with pytest.raises(spack.package_base.InstallError):
s.package.builder.std_cmake_args
spack.build_systems.cmake.CMakeBuilder.std_args(
s.package, generator="Yellow Sticky Notes"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

😆


depends_on("cmake", type="build")
depends_on("ninja", type="build", when="platform=windows")
depends_on("gmake", type="build", when="generator=make")
Copy link
Copy Markdown
Member

@haampie haampie Mar 17, 2023

Choose a reason for hiding this comment

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

I approve of this!

$ spack spec gmake +guile | grep cmake

has nothing on current develop, so it shouldn't break "advanced" gmake builds. gmake ~guile doesn't have deps.

Copy link
Copy Markdown
Member

@haampie haampie left a comment

Choose a reason for hiding this comment

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

I grepped for gmake build deps among packages of which there's only two cmake packages that specify a bound on it, so that looks fine. Ninja I think you got right too

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.

4 participants