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

RFE: Declarative build system support #1087

Closed
pmatilai opened this issue Feb 26, 2020 · 13 comments
Closed

RFE: Declarative build system support #1087

pmatilai opened this issue Feb 26, 2020 · 13 comments
Assignees
Labels
handsfree Packaging automation and convenience RFE
Milestone

Comments

@pmatilai
Copy link
Member

pmatilai commented Feb 26, 2020

Vast majority of software projects use a common, known build system where the steps to build and install only differ by configuration details. In rpm itself we have common macros for autotools-based projects (%configure, %make_build, %make_install), and distros have added macros to do the same for various other build systems, including language-specific ecosystems. These simplify life greatly but packagers still need to fill in specs with this redundant boilerplate for each and every project, that boilerplate just has to go away in the common case.

We should implement means to fill up the boilerplate by simply defining the project build system type, eg "Buildsystem: autotools". This would automatically populate the relevant sections with content defined in "autotools" configuration except where a section is already defined by the spec. Specifying an unknown build system would return an explicit error, ie the build systems would be "registered" by dropping a file in a known location rather than just macros defined wherever.

Actual build and install steps are common for all well-behaved packages, but configuration often has project-specific values so while a default configuration should be supplied, it needs be easy to override without reverting to all-manual spec foo. Hence we need at least #1086 for this.

Similarly there's often a need for some more or less minor tweaks to upstream build/install process, this must not require reverting to manually redefining all that. So I suppose we need pre- and post-section scripts, eg %build(post) where such manual tweaks can be placed.

Finally, there are multiple levels of possible default templates: %clean is rather universal and we already supply a default for that as a special case, and similarly %prep could quite univerally default to %autosetup -p1. Both should be overridable by buildsystem specifics though.

As an more practical example, here's an excerpt from a typical autotools project :

%prep
%autosetup

%build
%configure
%make_build

%install
%make_install

All that would simply become:

BuildSystem: autotools

This would be defined by eg /usr/lib/rpm/buildsystem/autotools file contents which could be just a macro file looking somewhat like this:

%__autotools_configure\
%configure

%__autotools_build\
%make_build\

%__autotools_install\
%make_install

...and eg cmake definition would only really differ from that on the configure section. Python etc would use their own macros as distros have defined. This would also serve as an API to which the various language-specific build systems etc can be developed for so the definitions are cross-distro shareable.

Crucial design goals:

  • minimize spec boilerplate and redundancy
  • building blocks must be equally usable within templates and manual use
  • minimize need for spec section override (eg provide pre/post slots for minor customization needs)
  • spec override must be possible for individual sections
  • no magic, what happens must be easily inspectable (rpmspec --parse etc)
@pmatilai pmatilai added the RFE label Feb 26, 2020
@ignatenkobrain
Copy link
Contributor

Sometimes build can involve multiple buildsystems, would be nice to have that covered.

@pmatilai
Copy link
Member Author

pmatilai commented Feb 26, 2020

The intention here is to make simple things simple while keeping arbitrary things possible, multiple build systems within a project falls into the "arbitrary" category in my books. However those cases will still benefit from having the interface standardized.

@jasontibbitts
Copy link

Wow, this is quite interesting and somewhat similar to things I've brainstormed about for a number of years now I think that this has the possibility to simplify packaging for a significant portion of at least the Fedora packaging set.

However, one problem we've struggled with is that when you hide too much, it becomes difficult for people to understand what to do when a package doesn't fit the mold. Would it be possible for this to simply define defaults for %build or %install or whatnot which would be used if those sections aren't present in the specfile? That way it would be simpler to handle that one package that needs a file removed after %make_install without having to completely switch away from using the templates.

@pmatilai
Copy link
Member Author

pmatilai commented Feb 27, 2020

Would it be possible for this to simply define defaults for %build or %install or whatnot which would be used if those sections aren't present in the specfile? That way it would be simpler to handle that one package that needs a file removed after %make_install without having to completely switch away from using the templates.

That's exactly the idea, sorry if it wasn't clear from the description. But note that in addition to being able to override any single section, I'm suggesting new pre/post sections for each to minimize the need to do override the entire section. So in order to remove that one pesky unwanted file, you wouldn't revert back to manual %install at all, you'd just add

%install(post)
rm -f /stupid/file

FWIW, I've been thinking and talking about this since at least 2013 too, just haven't gotten around to describe it in writing, much less implement.

@nim-nim
Copy link

nim-nim commented Mar 31, 2020

FYI I’ve converged on this pattern for my own packaging macros

%foometa → munge upstream metadata into rpm metadata
%foopkg -a → create package headers
%fooprep -a → prep actions
%foo_generate_buildrequires -a → dynbr actions
%foobuild -a → build
%fooinstall -a → install
%foocheck -a → check
%foofiles -a → create files section

https://pagure.io/fonts-rpm-macros/
https://pagure.io/go-rpm-macros/

You need to remember, that a spec file may match several build patterns at once (because upstream is shipping a complex project with multiple components of different kinds), and that the result, will be split over multiple subpackages (because the usual result of automating, is enforcing technical component boundaries, not social project boundaries).

Example of multipattern project:
https://src.fedoraproject.org/rpms/golang-x-image/blob/5301a8411cb2d76351fcf83ccf8550d86c9cb215/f/golang-x-image.spec

pmatilai added a commit to pmatilai/rpm that referenced this issue Aug 17, 2023
Remove endless boilerplate to perform the same steps in each
package by just declaring which kind of buildsystem the package uses
using the new Autobuild: spec tag.

Autobuild macros are just regular parametric macros which can be invoked
manually from specs too, which should help with reuse and handling
complicated cases.

As such , this will only work for simple and/or "perfect" upstream projects
of course. In reality many/most packages need further tweaking in %install
or otherwise. Augmenting those (one way or the other) needs to be implemented
to make this real-world usable.

Add automake upstream amhello-1.0.tar.gz as an test-case of a rather
hands-free autobuild.

Fixes: rpm-software-management#1087
@pmatilai pmatilai self-assigned this Aug 17, 2023
@voxik
Copy link
Contributor

voxik commented Aug 17, 2023

Looking at the PR and thinking how I would use it for Rubygems, I wonder if something like Autobuild: rubygems would also generate something like BuildRequires: rubygems-devel to pull in the associated /usr/lib/rpm/buildsystem/rubygems. But given that the rubygems-devel cannot be deferred, it would need some nomenclature or virtual provides or what not.

@pmatilai
Copy link
Member Author

Oh, that's a very good point! We'll need to add some kind of hook to allow for that.

@voxik
Copy link
Contributor

voxik commented Aug 17, 2023

On related note, will the autobuild macros be required to build SRPM? I hope that is not the case, similarly as e.g. the BRs are not required.

@pmatilai pmatilai added this to the 4.20.0 milestone Aug 23, 2023
@pmatilai
Copy link
Member Author

pmatilai commented Aug 24, 2023

The current autobuild macros relate to the executed scripts which aren't involved in SRPM creation so from that POV no.

The notion that buildrequires are not required for creating an SRPM is rather thin ice though, as the spec needs to be parseable to create an SRPM, and arbitrarily large chunks of the spec could come from macros in the buildrequires. If we add BuildRequires creation to autobuild, and then those macros are not present during SRPM creation, the buildrequires will be missing from the SRPM...

pmatilai added a commit to pmatilai/rpm that referenced this issue Aug 25, 2023
Remove endless boilerplate to perform the same steps in each
package by just declaring which kind of buildsystem the package uses
using the new Autobuild: spec tag.

Autobuild macros are just regular parametric macros which can be invoked
manually from specs too, which should help with reuse and handling
complicated cases.

As such , this will only work for simple and/or "perfect" upstream projects
of course. In reality many/most packages need further tweaking in %install
or otherwise. Augmenting those (one way or the other) needs to be
implemented to make this real-world usable.

The implementation looks more complicated than one might expect because
we want the full spec processing to take place on these parts, rather
than just macro expansion. That covers things like the special facilities
of %prep and their side-effects, %if-conditionals, possible error
handling and so on.

Add automake upstream amhello-1.0.tar.gz as an test-case of a rather
hands-free autobuild.

Fixes: rpm-software-management#1087
pmatilai added a commit to pmatilai/rpm that referenced this issue Aug 25, 2023
Remove endless boilerplate to perform the same steps in each
package by just declaring which kind of buildsystem the package uses
using the new Autobuild: spec tag.

Autobuild macros are just regular parametric macros which can be invoked
manually from specs too, which should help with reuse and handling
complicated cases.

As such , this will only work for simple and/or "perfect" upstream projects
of course. In reality many/most packages need further tweaking in %install
or otherwise. Augmenting those (one way or the other) needs to be
implemented to make this real-world usable.

The implementation looks more complicated than one might expect because
we want the full spec processing to take place on these parts, rather
than just macro expansion. That covers things like the special facilities
of %prep and their side-effects, %if-conditionals, possible error
handling and so on.

Add automake upstream amhello-1.0.tar.gz as an test-case of a rather
hands-free autobuild.

Fixes: rpm-software-management#1087
@pmatilai pmatilai changed the title Implement build system templating in spec files RFE: Declarative build system support Sep 12, 2023
@pmatilai pmatilai added the handsfree Packaging automation and convenience label Sep 14, 2023
pmatilai added a commit to pmatilai/rpm that referenced this issue Oct 20, 2023
Allows %build, %install, %check, %clean and %generate_depends to be
augmented arbitrary number of times by appending or prepending to them.
The main use-case is to support automatic population of these sections
(declarative builds) while still allowing packagers to easily tweak them,
but could also be useful for complicated conditional specs and such.

Related: rpm-software-management#1087
pmatilai added a commit to pmatilai/rpm that referenced this issue Oct 20, 2023
Allows %build, %install, %check, %clean and %generate_depends to be
augmented arbitrary number of times by appending or prepending to them.
The main use-case is to support automatic population of these sections
(declarative builds) while still allowing packagers to easily tweak them,
but could also be useful for complicated conditional specs and such.

%prep is missing from the list because it's way too special at the
moment, it'll gain this capability when rpm-software-management#2205 is fixed.

Related: rpm-software-management#1087
pmatilai added a commit to pmatilai/rpm that referenced this issue Oct 20, 2023
Allows %build, %install, %check, %clean and %generate_depends to be
augmented arbitrary number of times by appending or prepending to them.
The main use-case is to support automatic population of these sections
(declarative builds) while still allowing packagers to easily tweak them,
but could also be useful for complicated conditional specs and such.

%prep is missing from the list because it's way too special at the
moment, it'll gain this capability when rpm-software-management#2205 is fixed.

Related: rpm-software-management#1087
pmatilai added a commit to pmatilai/rpm that referenced this issue Oct 27, 2023
Allows %prep, %conf, %build, %install, %check, %clean and %generate_depends
to be augmented arbitrary number of times by appending or prepending to
them. The main use-case is to support automatic population of these
sections (declarative builds) while still allowing packagers to easily
tweak them, but could also be useful for complicated conditional specs
and such.

Related: rpm-software-management#1087
pmatilai added a commit that referenced this issue Oct 27, 2023
Allows %prep, %conf, %build, %install, %check, %clean and %generate_depends
to be augmented arbitrary number of times by appending or prepending to
them. The main use-case is to support automatic population of these
sections (declarative builds) while still allowing packagers to easily
tweak them, but could also be useful for complicated conditional specs
and such.

Related: #1087
pmatilai added a commit to pmatilai/rpm that referenced this issue Oct 27, 2023
Remove endless boilerplate to perform the same steps in each
package by just declaring which kind of buildsystem the package uses
using the new Autobuild: spec tag.

Autobuild macros are just regular parametric macros which can be invoked
manually from specs too, which should help with reuse and handling
complicated cases.

As such , this will only work for simple and/or "perfect" upstream projects
of course. In reality many/most packages need further tweaking, but this
can now be easily done with the new append/prepend modes of the build
scriptlets.

The implementation looks more complicated than one might expect because
we want the full spec processing to take place on these parts, rather
than just macro expansion. That covers things like the special facilities
of %prep and their side-effects, %if-conditionals, possible error
handling and so on.

Add automake upstream amhello-1.0.tar.gz as an test-case of a rather
hands-free autobuild. Pretending it's a noarch package is ugly, but
handling arch-specifity in the test-suite is uglier.

Fixes: rpm-software-management#1087
pmatilai added a commit to pmatilai/rpm that referenced this issue Oct 27, 2023
Remove endless boilerplate to perform the same steps in each
package by just declaring which kind of buildsystem the package uses
using the new Autobuild: spec tag.

Autobuild macros are just regular parametric macros which can be invoked
manually from specs too, which should help with reuse and handling
complicated cases.

As such , this will only work for simple and/or "perfect" upstream projects
of course. In reality many/most packages need further tweaking, but this
can now be easily done with the new append/prepend modes of the build
scriptlets.

The implementation looks more complicated than one might expect because
we want the full spec processing to take place on these parts, rather
than just macro expansion. That covers things like the special facilities
of %prep and their side-effects, %if-conditionals, possible error
handling and so on.

Add automake upstream amhello-1.0.tar.gz as an test-case of a rather
hands-free autobuild. Pretending it's a noarch package is ugly, but
handling arch-specifity in the test-suite is uglier.

Fixes: rpm-software-management#1087
pmatilai added a commit to pmatilai/rpm that referenced this issue Oct 27, 2023
Remove endless boilerplate to perform the same steps in each
package by just declaring which kind of buildsystem the package uses
using the new Autobuild: spec tag.

Autobuild macros are just regular parametric macros which can be invoked
manually from specs too, which should help with reuse and handling
complicated cases.

As such , this will only work for simple and/or "perfect" upstream projects
of course. In reality many/most packages need further tweaking, but this
can now be easily done with the new append/prepend modes of the build
scriptlets.

The implementation looks more complicated than one might expect because
we want the full spec processing to take place on these parts, rather
than just macro expansion. That covers things like the special facilities
of %prep and their side-effects, %if-conditionals, possible error
handling and so on.

Add automake upstream amhello-1.0.tar.gz as an test-case of a rather
hands-free autobuild with added distro specific doc.

Fixes: rpm-software-management#1087
@pmatilai
Copy link
Member Author

pmatilai commented Nov 6, 2023

To recoup the very useful discussion and ideas from the now withdrawn draft PR:
To make things properly declarative, overriding sections should not be a part of the plan at all. Instead there should be a way to declare independent build options one by one. And the "auto" in the name needs to go.

What I'll be looking into now is:

  • BuildSystem: a singleton tag to declare the used build system for the package (tag name open to speculation still, Build is kinda tempting too)
  • BuildOption(section): a repeatable tag to declare options one by one to pass to the build system for a given section
  • BuildOption: without parentheses is equal to BuildOption(conf) which is by far the most common place needing options

This nicely allows grouping options along with other related conditionals, eg

%if %{with foo}
BuildRequires: libfoo-devel
BuildOption: --enable-foo
%endif

Support for a buildsystem is implemented by defining macros that describe the required for each relevant section. Said macros are responsible for passing the options from the BuildOption tags to the buildsystem as appropriate.

Be sure to check out the #2620 draft for examples and pros/cons of alternatives etc.

pmatilai added a commit to pmatilai/rpm that referenced this issue Nov 21, 2023
Remove endless boilerplate to perform the same steps in each
package by just declaring which kind of buildsystem the package uses
using the new BuildSystem: spec tag.

Buildsystem macros are just regular parametric macros which can be invoked
manually from specs too, which should help with reuse and handling
complicated cases.

As such, this will only work for simple and/or "perfect" upstream projects
of course. In reality many/most packages need further tweaking, but this
can now be easily done with the new append/prepend modes of the build
scriptlets, and declaratively passed options to specific sections.

Add automake upstream amhello-1.0.tar.gz as an test-case of a rather
hands-free build with added distro specific doc.

Fixes: rpm-software-management#1087
pmatilai added a commit to pmatilai/rpm that referenced this issue Nov 21, 2023
Remove endless boilerplate to perform the same steps in each
package by just declaring which kind of buildsystem the package uses
using the new BuildSystem: spec tag.

Buildsystem macros are just regular parametric macros which can be invoked
manually from specs too, which should help with reuse and handling
complicated cases.

As such, this will only work for simple and/or "perfect" upstream projects
of course. In reality many/most packages need further tweaking, but this
can now be easily done with the new append/prepend modes of the build
scriptlets, and declaratively passed options to specific sections.

Add automake upstream amhello-1.0.tar.gz as an test-case of a rather
hands-free build with added distro specific doc.

Fixes: rpm-software-management#1087
@pmatilai
Copy link
Member Author

The above specification is now implemented in #2774, more or less.

pmatilai added a commit to pmatilai/rpm that referenced this issue Dec 11, 2023
Remove endless boilerplate to perform the same steps in each
package by just declaring which kind of buildsystem the package uses
using the new BuildSystem: spec tag.

Buildsystem macros are just regular parametric macros which can be invoked
manually from specs too, which should help with reuse and handling
complicated cases.

As such, this will only work for simple and/or "perfect" upstream projects
of course. In reality many/most packages need further tweaking, but this
can now be easily done with the new append/prepend modes of the build
scriptlets, and declaratively passed options to specific sections.

Add automake upstream amhello-1.0.tar.gz as an test-case of a rather
hands-free build with added distro specific doc.

Fixes: rpm-software-management#1087
pmatilai added a commit to pmatilai/rpm that referenced this issue Jan 4, 2024
Remove endless boilerplate to perform the same steps in each
package by just declaring which kind of buildsystem the package uses
using the new BuildSystem: spec tag.

Buildsystem macros are just regular parametric macros which can be invoked
manually from specs too, which should help with reuse and handling
complicated cases.

As such, this will only work for simple and/or "perfect" upstream projects
of course. In reality many/most packages need further tweaking, but this
can now be easily done with the new append/prepend modes of the build
scriptlets, and declaratively passed options to specific sections.

Add automake upstream amhello-1.0.tar.gz as an test-case of a rather
hands-free build with added distro specific doc.

Fixes: rpm-software-management#1087
pmatilai added a commit to pmatilai/rpm that referenced this issue Jan 11, 2024
Remove endless boilerplate to perform the same steps in each
package by just declaring which kind of buildsystem the package uses
using the new BuildSystem: spec tag.

Buildsystem macros are just regular parametric macros which can be invoked
manually from specs too, which should help with reuse and handling
complicated cases.

As such, this will only work for simple and/or "perfect" upstream projects
of course. In reality many/most packages need further tweaking, but this
can now be easily done with the new append/prepend modes of the build
scriptlets, and declaratively passed options to specific sections.

Add automake upstream amhello-1.0.tar.gz as an test-case of a rather
hands-free build with added distro specific doc.

Fixes: rpm-software-management#1087
dmnks pushed a commit to dmnks/rpm that referenced this issue Jan 23, 2024
Remove endless boilerplate to perform the same steps in each
package by just declaring which kind of buildsystem the package uses
using the new BuildSystem: spec tag.

Buildsystem macros are just regular parametric macros which can be invoked
manually from specs too, which should help with reuse and handling
complicated cases.

As such, this will only work for simple and/or "perfect" upstream projects
of course. In reality many/most packages need further tweaking, but this
can now be easily done with the new append/prepend modes of the build
scriptlets, and declaratively passed options to specific sections.

Add automake upstream amhello-1.0.tar.gz as an test-case of a rather
hands-free build with added distro specific doc.

Fixes: rpm-software-management#1087
@LecrisUT
Copy link

LecrisUT commented Mar 25, 2024

Found out about this new feature. How does one go about constructing such BuildSystem, do they just define a %buildsystem_<buildsystem>_conf macros?

I am considering the case of MPI packaging and it would be a neat approach to for looping all mpi variants. One thing that would be needed is to expand BuildOption(section) for specific variant, e.g.: BuildOption(conf-serial).

Alternatively, would the BuildOption work with shell/macro commands, e.g.:

# Using env variable
BuildOption(conf): $([[ -z "$MPI_SUFFIX" ]] && echo "-DUSE_MPI=ON" || echo "-DUSE_MPI=OFF")
# Using macro
BuildOption(conf): -DUSE_MPI=%{?mpi_variant:ON}%{?!mpi_variant:OFF}

The former would work even if the macros %configure macro is expanded with shell for loops, but the latter is more manageable.

@pmatilai
Copy link
Member Author

It's documented here: https://rpm-software-management.github.io/rpm/manual/buildsystem.html#supporting-new-build-systems

But closed tickets are not a good place for questions, please open a new thread in https://github.com/rpm-software-management/rpm/discussions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
handsfree Packaging automation and convenience RFE
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

6 participants