-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Allow packages with multiple build-systems (separate classes) #30738
Allow packages with multiple build-systems (separate classes) #30738
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Took a look at this version but it's really unclear what's going on here. Some packages like python
switched back to AutotoolsPackage
with no explanation of how they work on Windows, other packages like uncrustify
look the same as in #30411, other packages like zlib
have a new *Builder
class and I'm not sure what that's for or why it's necessary. Were all packages updated for this PR or is only zlib
representative of what the package would need to look like? I wonder if it would be easier for me to propose what I would like a package.py
to look like and you can tell me which of these are possible and which aren't.
Can you point which ones are you referring to? Might have missed something during a rebase.
Packages like
Packages like From the point of view of functionality this PR and #30411 are the same, but this one moves building concerns to a separate class internally - it's a way to start moving all the responsibilities now in For instance we don't need to fiddle with Python's class model to have a mock build. Just create a new |
6fa3119
to
52fe165
Compare
52fe165
to
0b11425
Compare
e4d292c
to
6831935
Compare
Marked as "ready for review" to start running pipelines on this branch, and fix the failures |
6831935
to
a7f5e23
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've looked through most of this and wanted to start with some high-level questions/comments:
-
There is some ambiguity in what goes into a Package vs. a Builder
- e.g. IntelPackage has "configure" as a run_before method in the package
- I assume the rule of thumb is "if it has anything to do with the build process, it should go in the builder" (e.g. cmake_args)
- Even this concept is sometimes murky: e.g. cases where setup_build_environment sets environment variables that are later used by the build system
- (a) Allow packages with multiple build-systems (inheritance) #30411 avoids forcing users to confront this ambiguity so IMO that has an advantage
- I should make sure to clarify: the main thing I like is the ability to designate methods in packages as being associated with a specific build system superclass phase
- I'm not sure if I perceive what about this leads to the problems Allow packages with multiple build-systems (inheritance) #30411 has (there's some related discussion in next point)
-
PackageAdapterMeta uses legacy_* attributes of builders to determine what the Package can override
- At the moment, if you take cmake.py, and combine all the legacy_* definitions, it appears to "cover" the entire builder
- Why not defer all method calls to the package generically vs. having different categories of overrides?
- (I assumed that can be achieved by using *args/**kwargs)
- Is the goal to eventually remove these (or in fact raise an error if the subclass defines them)?
- If so, you could use decorators to track Package methods that should override the build class
_PackageAdapterMeta
could use these instead oflegacy_*
attributes (so in that sense I don't think the PR would be complicated much by supporting (a))
-
It looks easy to support custom phases:
- If
_PackageAdapterMeta.__new__
changes
for phase_name in default_builder_cls.phases:
to
for phase_name in default_builder_cls.phases + package_class.phases:
then it looks like phases would be retrieved from the package just fine. - (I assume it would be trivial to retrieve the package class when creating the builder)
- If
-
(minor)
NMakeBuilder
andMakefileBuilder
both define build_directory- I assume users might be confused that they have to override both of these for packages that build on Linux and Windows
- My concern is possible confusion/frustration when builders with identically-named attributes also coincidentally would have identical intent/implementation
-
(minor) The concept that you inherit a buildsystem class, then define a sibling class with a specific name and it will be used automatically, is not immediately clear
- It avoids having to come up with names like FooCmakeBuilder, so the concept is useful
- It will need some explanation though
-
If someone overrides an Autotools package and wants to define setup_build_environment/configure then, following the idioms established in this PR, they now have to modify/define two classes
- My understanding is that this isn't initially required because of PackageAdapterMeta, but that eventually that would be the intent
- My point with this is that even for users that don't need to inherit multiple build systems, they will (eventually) need to consider this layout
Just a few "easy" answers, before discussing the PR in the call today: There is some ambiguity in what goes into a Package vs. a Builder
The
This is true, I don't remember if I raised the issue somewhere but I agree with what you say. At the moment I left the PackageAdapterMeta uses legacy_* attributes of builders to determine what the Package can override
Yes, the idea is to deprecate the current layout of NMakeBuilder and MakefileBuilder both define build_directoryThat's already the case for e.g. The concept that you inherit a buildsystem class, then define a sibling class with a specific name and it will be used automatically, is not immediately clearNothing has been documented so far, as documentation changes will also be big - and no design has been thoroughly discussed yet. |
a7f5e23
to
42414b9
Compare
adding @bangerth to dealii/oce discussion |
@alalazo should we think about making it so the build system variant doesn't count towards the default/non-default variant count? I guess for most scenarios we probably do want to prioritize the default build system, so maybe this really is a specific thing we need to tweak |
So far I think it's fine, in the sense that this issue is really due to
|
This commit extends the DSL that can be used in packages to allow declaring that a package uses different build-systems under different conditions. It requires each spec to have a `build_system` single valued variant. The variant can be used in many context to query, manipulate or select the build system associated with a concrete spec. The knowledge to build a package has been moved out of the PackageBase hierarchy, into a new Builder hierarchy. Customization of the default behavior for a given builder can be obtained by coding a new derived builder in package.py. The "run_after" and "run_before" decorators are now applied to methods on the builder. They can also incorporate a "when=" argument to specify that a method is run only when certain conditions apply. For packages that do not define their own builder, forwarding logic is added between the builder and package (methods not found in one will be retrieved from the other); this PR is expected to be fully backwards compatible with unmodified packages that use a single build system.
Thanks everyone. deal.II should be able to build against modern versions of TBB (and if it doesn't, then that's a bug we need to fix) and the same should be true for OpenCASCADE vs OCE: deal.II should be able to build against either, and their most current versions, and if that is not true we need to fix this. As mentioned above, what these packages do is (regrettably) out of our hands. I wished they all used cmake, but we can't force them to :-( |
Unfortunately openvdb also needs an older version of intel-tbb (this isn't recorded in the dependencies, but at least for us it won't build with 2021, only 2020). Now that 2020 won't build, we can't build openvdb. There are newer versions of openvdb available though, which may be worth trying (@eloop). |
|
This commit extends the DSL that can be used in packages to allow declaring that a package uses different build-systems under different conditions. It requires each spec to have a `build_system` single valued variant. The variant can be used in many context to query, manipulate or select the build system associated with a concrete spec. The knowledge to build a package has been moved out of the PackageBase hierarchy, into a new Builder hierarchy. Customization of the default behavior for a given builder can be obtained by coding a new derived builder in package.py. The "run_after" and "run_before" decorators are now applied to methods on the builder. They can also incorporate a "when=" argument to specify that a method is run only when certain conditions apply. For packages that do not define their own builder, forwarding logic is added between the builder and package (methods not found in one will be retrieved from the other); this PR is expected to be fully backwards compatible with unmodified packages that use a single build system.
@tgamblin I also timed develop at 83ee500 with this PR at commit 30c9ff5 to check the impact of adding a variant everywhere: radiuss_develop.csv There's some impact, but overall not really noticeable: |
fixes #12736 (in this PR the
run_after
decorator has an optionalwhen=
argument)closes #30411
This PR extends the DSL that can be used in packages to allow declaring that a package uses different build-systems under different conditions. The main design decision both in here and in #30411 is to require each and every spec to have a
build_system
single valued variant. This variant can be used in many contexts to manipulate (force, query, display etc.) the build-system associated with a concrete spec.Expected backward incompatibilities
Methods decorated with@when
that expect the base case to be present in the build-system base classMethods usingsuper
to access build properties of the package, or expecting some of the methods that moved to be present in thePackage
class hierarchyPackages defining a customphases
attributePros
Builder
objects easier to swap in and out.buildsystem
variant will determine whichBuilder
class is instantiated.Cons
This PR is fairly compatible with what we had before but not as compatible as Allow packages with multiple build-systems (inheritance) #30411.package.py
The
buildsystem
directiveTo make it easy to declare the build-system, a new directive has been created. This directive is essentially a wrapper around
variant
:For packages with a single buildsystem, the directive is already used in base classes - so no modifications are needed for packages in that sense.
Decorators to customize phases
There will be only a single
run_after
and a singlerun_before
decorator, as it is the case currently. These decorators can be used within each specific builder class:There is no restriction on the choice of the names that can be used for buildsystems, e.g. we can have
buildsystem=cmake
. This is because we don't need to have separate decorators, since the partitioning of information is implemented by the class design.Dynamic adapter for backward compatibility
To obtain a reasonable degree of backward compatibility, if the
package.py
doesn't contain specializations of the base builder classes, an adapter class is constructed on the fly. This class tries to, in order:The class is created dynamically by a metaclass which generates methods to intercept certain attributes, methods or phases. As an example this is how attribute interceptors are created:
To know which names to look for, each build-system must define at a class level the legacy attribute and method names
Example of packages with multiple build-systems
arpack-ng
nasm
uncrustify