Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add proposal to deal with multiple build-systems using directives #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

alalazo
Copy link
Member

@alalazo alalazo commented Sep 7, 2021

This SEP propose to deal with multiple build systems using a new directive:

class Hdf5(Package):
    build_system('cmake', when='@X.Y:')
    build_system('autotools')

The semantics of the new directive is that of a single valued variant with a dynamic set of allowed values subject to constraint. If we treat multiple build-systems this way:

  • We can select the build system from a spec similarly to a variant (hdf5 build_system=cmake)
  • We have a clear semantic in case of overlapping constraints among build-systems

More details in the SEP.

Other attempts to solve the same issue in Spack:

PRs related to build-systems that we might want to consider:

@alalazo alalazo added enhancement New feature or request help wanted Extra attention is needed labels Sep 7, 2021
Copy link
Member

@adamjstewart adamjstewart left a comment

Choose a reason for hiding this comment

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

This is an interesting proposal. I spoke to @tgamblin about this a while back and he suggested simply wrapping each class with a @when decorator so that the Hdf5 class could inherit from different base classes based on version. However, it was never clear to me how this would work, and it doesn't allow for the same version to build with multiple build systems. I think the logic proposed in this PR is one of the simplest I've seen for handling this. As for how to implement it internally in Spack's core, I guess I'll have to see what we come up with. My main concern is that the package files remain simple, and this approach seems simple to me.


## The problem

There are multiple packages that are either changing their build-system during the evolution of the project, or using different build-systems for different platforms. Spack, at the moment, provides no support to model this use case. As a result we wrote some [documentation](https://github.com/spack/spack/pull/25174) to enumerate various workarounds that people adopted - each with its own drawbacks. What we would like to have in the long term is proper support for packages that can be built using multiple build-systems.
Copy link
Member

Choose a reason for hiding this comment

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

using different build-systems for different platforms

This is a very good point that I didn't think about while writing spack/spack#25174, glad to see more core developers thinking about Windows support!

Copy link
Member

Choose a reason for hiding this comment

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

Very much so! Consider spack/spack@5818a54, are we going to turn all ./configure-based packages into CMake packages across all platforms just to support Visual Studio? I really hope not... zlib is a teeny tiny package that should be able to build with 0 other deps than a shell and a compiler.

```
Each build-system can be subject to a constraint. In the example above, for instance, `cmake` can be used only if the version of `hdf5` is greater or equal than `X.Y` (while `autotools` is always available).

We can also assume that there is an __implicit preference order__ based on on the order of declaration in the class. In the example above this means that, if no other requests are made by the user, `cmake` is preferred to `autotools` when available.
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 with this, but this "implicit preference order based on the order of declaration in the class" is different than all other directives in Spack, so it may be good to make this very clear in the docs.

```
hdf5 build_system=cmake
```
__which requires the keyword `build_system` to be reserved by Spack__ (similarly to what is done for `dev_path`). It is interesting to note that modeling build-systems this way make them similar to signle-valued variants with the only difference that the set of allowed values is "dynamic" and subject to constraints.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
__which requires the keyword `build_system` to be reserved by Spack__ (similarly to what is done for `dev_path`). It is interesting to note that modeling build-systems this way make them similar to signle-valued variants with the only difference that the set of allowed values is "dynamic" and subject to constraints.
__which requires the keyword `build_system` to be reserved by Spack__ (similarly to what is done for `dev_path`). It is interesting to note that modeling build-systems this way make them similar to single-valued variants with the only difference that the set of allowed values is "dynamic" and subject to constraints.

A lot of users have been asking for this for swapping between Ninja and Makefile in CMakePackage. Would you consider Ninja vs. Makefile to be a build system? We could do build_system=cmake_ninja or build_system=cmake_makefile. Or it could be a different reserved keyword.

Copy link
Member Author

@alalazo alalazo Sep 8, 2021

Choose a reason for hiding this comment

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

I have to think a bit about this. A solution like build_system=cmake_ninja does not require any change in the proposed semantics, but we are effectively splitting the cmake build-system into many build-systems based on the generator we use.

Using hdf5 build_system=cmake generator=ninjaseems more appealing, but we need the ability to attach specific variants based on the build-system being used. That may require the "conditional" variant PR from @becker33:

variant('generator', values=('makefile', 'ninja'), default='makefile', when='build_system=cmake')

class CMakePackage(PackageBase):
# Can be overridden if conditional in derived classes
build_system('cmake')
depends_on('cmake', type='build')
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 write a package that supports both CMake and Autotools, will I have to manually add:

depends_on('cmake', when='build_system=cmake', type='build')

or can that be included in CMakeBuildSystem? Is the build_system=cmake even available in the spec?

Copy link
Member Author

@alalazo alalazo Sep 8, 2021

Choose a reason for hiding this comment

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

Is the build_system=cmake even available in the spec?

Yes, that is available in the spec. There are legitimate use cases where you want to use it in recipes too, e.g. for bootstrapping tools. Think for instance foo can build with cmake and makefile and is a cmake dependency. In CMake's recipe you probably want to specify:

depends_on('foo build_system=makefile')

to avoid circular dependencies.

If I write a package that supports both CMake and Autotools, will I have to manually add: [ ... ]

I think that should be implied and something similar needs to be included only if there are additional constraints to be met e.g. on the version of cmake.

tgamblin pushed a commit to spack/spack that referenced this pull request Apr 5, 2022
Allow declaring possible values for variants with an associated condition. If the variant takes one of those values, the condition is imposed as a further constraint.

The idea of this PR is to implement part of the mechanisms needed for modeling [packages with multiple build-systems]( spack/seps#3). After this PR the build-system directive can be implemented as:
```python
variant(
    'build-system',
    default='cmake',
    values=(
        'autotools',
        conditional('cmake', when='@X.Y:')
    ), 
    description='...',
)
```

Modifications:
- [x] Allow conditional possible values in variants
- [x] Add a unit-test for the feature
- [x] Add documentation
iarspider pushed a commit to iarspider/spack that referenced this pull request Apr 6, 2022
Allow declaring possible values for variants with an associated condition. If the variant takes one of those values, the condition is imposed as a further constraint.

The idea of this PR is to implement part of the mechanisms needed for modeling [packages with multiple build-systems]( spack/seps#3). After this PR the build-system directive can be implemented as:
```python
variant(
    'build-system',
    default='cmake',
    values=(
        'autotools',
        conditional('cmake', when='@X.Y:')
    ), 
    description='...',
)
```

Modifications:
- [x] Allow conditional possible values in variants
- [x] Add a unit-test for the feature
- [x] Add documentation
RikkiButler20 pushed a commit to RikkiButler20/spack that referenced this pull request Apr 6, 2022
Allow declaring possible values for variants with an associated condition. If the variant takes one of those values, the condition is imposed as a further constraint.

The idea of this PR is to implement part of the mechanisms needed for modeling [packages with multiple build-systems]( spack/seps#3). After this PR the build-system directive can be implemented as:
```python
variant(
    'build-system',
    default='cmake',
    values=(
        'autotools',
        conditional('cmake', when='@X.Y:')
    ), 
    description='...',
)
```

Modifications:
- [x] Allow conditional possible values in variants
- [x] Add a unit-test for the feature
- [x] Add documentation
@alalazo
Copy link
Member Author

alalazo commented Dec 1, 2022

@tgamblin This is the first SEP that has been implemented. Should we review the current early proposal, fix it, and merge it? Or should we leave it as it is since the SEP repository is rarely used?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants