From e9c53785442355c6fbed11c8aaedf12953090269 Mon Sep 17 00:00:00 2001 From: Otto Liljalaakso Date: May 03 2024 10:08:41 +0000 Subject: Add simpler Banner package to packaging tutorial Packaging tutorial's approach of packaging GNU Hello has suffered from certain complexities in GNU Hello package. The package is quite old and uses some tooling from the GNU project that are not very widely used any more, such as Texinfo. Also, the package is old and thus suffers from e.g. having a file that is not UTF-8 encoded. To avoid immediately exposing tutorial readers to these quirks, make GNU Hello part 2 of the tutorial and add a simpler package, Banner, as part 1. This way the reader can reach a complete specfile, compliant with Fedora guidelines, quicker, and still get a feeling for resolving packaging quirks in the second part. In the future, basing the first tutorial on real packages should probably be switched to hosting dedicated "test project", which avoid any quirks and can be packaged to Fedora requirements using only Fedora's set of RPM macros. Such package should also avoid GNU Autotools and be based on CMake or Meson, which are simpler to understand and more widespread today. --- diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index faf0474..f879fb6 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -11,8 +11,9 @@ ** xref:New_Package_Process_for_Existing_Contributors.adoc[for Existing Contributors] ** xref:New_Package_Process_for_New_Contributors.adoc[for New Contributors] -* Creating RPM packages -** xref:Packaging_Tutorial_GNU_Hello.adoc[Packaging Tutorial: GNU Hello] +* Packaging Tutorial +** xref:Packaging_Tutorial_1_banner.adoc[Packaging Tutorial 1: banner] +** xref:Packaging_Tutorial_2_GNU_Hello.adoc[Packaging Tutorial 2: GNU Hello] * xref:Package_Review_Process.adoc[Package Review Process] diff --git a/modules/ROOT/pages/Packaging_Tutorial_1_banner.adoc b/modules/ROOT/pages/Packaging_Tutorial_1_banner.adoc new file mode 100644 index 0000000..ed33aaf --- /dev/null +++ b/modules/ROOT/pages/Packaging_Tutorial_1_banner.adoc @@ -0,0 +1,540 @@ +include::{partialsdir}/attributes.adoc[] + += Packaging Tutorial 1: banner + +This tutorial demonstrates RPM packaging +by packaging the https://github.com/pronovic/banner[banner] program. +It is a simple program with a simple +https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html[GNU Autotools] build script. + +For comprehensive information on how to create RPM files, +refer to https://rpm-software-management.github.io/rpm/manual/[RPM Reference Manual]. +If you plan to create an RPM package for the Fedora repository, +follow the process for xref:Joining_the_Package_Maintainers.adoc[Joining the Package Maintainers], +including following the various Fedora guidance. + +This tutorial is intended to be run on a Fedora {MAJOROSVER} system. +It should, however, work also for other Fedora releases. +Just replace strings like `f{MAJOROSVER}` with your release number. +Because this tutorial uses Fedora specific features that may not available in other environments, +Fedora downstreams such as CentOS Stream or Red Hat Enterprise Linux may or may not work. + +The tutorial proceeds in step by step manner, +with most steps editing the package's specfile. +The final resulting specfile is listed in the end, +so in case there is any unclarity how a particular change should be applied, +you can peek there. + +[#dev_env] +== Installing Packager Tools + +Follow xref:Installing_Packager_Tools.adoc[Installing Packager Tools]. + +[#building] +== Creating the package directory + +In Fedora, package build instructions are organized in so called _dist-git_ repositories. +There is a separate repository for each package. +We mimic this system by creating a new directory for this tutorial. +In dist-git, the repository name matches the package name. +Fedora's rules for naming packages are written in https://docs.fedoraproject.org/en-US/packaging-guidelines/Naming/[Naming Guidelines]. +For banner, package should simply be named `banner`. +This is also the name of Fedora's https://packages.fedoraproject.org/pkgs/banner/banner/[official banner package]. + +---- +$ mkdir banner && cd banner +---- + +[#inside_spec] +== Inside a Spec File + +RPM packages are configured by `.spec` files. +Tools such was `rpmdev-newspec` can be used to generate empty specfiles for different purposes. +For this tutorial, just create a file called `banner.spec` and paste the following minimal specfile. +It does not work yet, but we will try to build it and fix errors as we encounter them. + +[source, rpm-spec] +---- +Name: banner +Version: 1.3.6 +Release: %autorelease +Summary: Prints a short string to the console in very large letters +License: GPL-2.0-only +URL: https://github.com/pronovic/banner +Source: https://github.com/pronovic/banner/releases/download/BANNER_V%{version}/banner-%{version}.tar.gz + +%description +This is a classic-style banner program similar to the one found in Solaris or +AIX in the late 1990s. It prints a short string to the console in very large +letters. + +%prep +%autosetup + +%build +%configure +%make_build + +%install +%make_install + +%files + +%changelog +%autochangelog +---- + +The specfile starts with a set of _tags_, such as `Name:` and `Version:`, +followed by _sections_ such as `%description` and `%prep`. +Each tag fits into a single line, whereas each section continues until the next one starts. + +Note that, confusingly, in addition to marking the section names, +the percent sign `%` also marks RPM _macros_. +Thus `%autosetup`, `%configure`, `%make_build`, `%make_install` and `%autochangelog` are not sections. + +=== Tags + +`Version` contains the version number of the packaged software. + +`Release` numbers specfile updates, package rebuilds and other work within Fedora. +The value used here, `%autorelease`, is part of https://docs.pagure.org/fedora-infra.rpmautospec/index.html[rpmautospec], +which is https://fedoraproject.org/wiki/Changes/Rpmautospec_by_Default[recommended for Fedora packages]. +It ties `Release` to package's Git history. +As we do not have a Git repository, `%autorelease` will evaluate to the default value of 1. + + +Often, `Summary` can be copied from the upstream README. +The first letter should be uppercase to avoid `rpmlint` complaints. + +`License` describes the license of the resulting binary package using a SPDX license identifier. +It must follow Fedora's https://docs.fedoraproject.org/en-US/legal/license-field/[licensing guidelines]. +In practice, determining the correct value often means inspecting the license notifications in individual source files. +Upstream developers may also need to be asked for clarifications or corrections. +In this tutorial, we just take the upstream's word that the license is the GNU Public License, version 2. + +`URL` points to upstream project's website, +which in this case is the GitHub repo's page. + +`Source` defines the upstream sources used when building the package. +Usually, as in this case, it is a url pointing to a tarball released by the upstream, +but it can also be a local file. +There can be multiple `Source` tags if needed. + +=== Sections + +`%description` can often be copied from upstream README. + +`%prep` contains a shell script for preparing the sources for building. +It is often just the single macro `%autosetup`, +which, in this case, simply extracts the source. + +`%build` contains a shell script for the required build steps, +such as compiling sources to binaries. +Since banner's buildsystem is https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html[Autotools], +building it involves running `configure` and `make`. +Macros `%configure` and `%make_build` invoke these commands using Fedora's compilation flags and other configuration. + +`%install` contains a shell script to copy the results from `%build` into an initially empty _build root_ directory. +As banner is using Autotools, macro `%make_install` is used. + +`%files` lists the content of the resulting package. +Mostly, the files come from the build root created in the `%install`, +but documentation and license files can also be added directly from the sources. +This section is left empty for now, to be filled later. + +The `+%changelog+` documents the changes in each new package version and release. +Changelog data can be displayed by `+rpm --query --changelog PACKAGE_NAME+`, +which can be useful, for instance, to find out if specific bug and security patches are included. +Its value,`+%autochangelog+`, also comes from `rpmautospec`. +It populates the changelog from Git commit messages. +As we do not have a Git repository, the changelog will be empty. + +Lines which are not needed can be commented out with the hash `#`. + +You can find more information in the RPM Reference Manual's section https://rpm-software-management.github.io/rpm/manual/spec.html[Spec file format]. + +== Downloading source + +We need the source code defined by the `Source` tag, often referred to as the _upstream_ source. +This is most easily achieved by using the `spectool` command: + +---- +$ spectool -g banner.spec +---- + +You should now have the file listed in `Source` in your working directory: + +---- +$ ls *.tar.gz +banner-1.3.6.tar.gz +---- + +== Building the Package + +We are ready for the first run to build source, binary and debugging packages. +This, and many other tasks, are done with the `fedpkg` tool. +The production builds for Fedora are built +in the https://koji.fedoraproject.org[Koji] build system, +which in turn uses https://rpm-software-management.github.io/mock/[Mock] +to manage isolated build environments. +To get as close to a production build as is locally possible, +we use the `fedpkg mockbuild` command +which also invokes Mock: + +[subs="attributes+"] +---- +$ fedpkg --release f{MAJOROSVER} mockbuild +---- + +The build environment created by Mock is very basic. +It does not include a C compiler by default, so the build will fail. +The reason is explained in the output: + +---- +checking whether the C compiler works... no +configure: error: in `/builddir/build/BUILD/banner-6': +configure: error: C compiler cannot create executables +See `config.log' for more details + +RPM build errors: +error: Bad exit status from /var/tmp/rpm-tmp.R4Tf16 (%build) + Bad exit status from /var/tmp/rpm-tmp.R4Tf16 (%build) +---- + +Additional build tools are defined +by adding `BuildRequires:` rows to the specfile. +In Fedora, GCC is the standard compiler, so we need to add a row for `gcc`. +Autotools also uses `make`, so a row should be added for it, too. +Add these lines after `Source`: + +[source, rpm-spec] +---- +BuildRequires: gcc +BuildRequires: make +---- + +Run a mockbuild again. + +== Installing files + +The next thing rpm will complain about are unpackaged files, +i.e. the files that would be installed in the system, +but were not declared as belonging to the package. +We need to declare them in the `%files` section. +Fixing these errors is an iterative process. +After declaring a missing file in the specfile, run `fedpkg` again, +then declare the next missing file and so on. + +We will go through the file list one by one. + +=== Executable + +---- +Installed (but unpackaged) file(s) found: +/usr/bin/banner +---- + +This is the executable binary program. +`/usr/bin`, like many other system directories, have a +xref:packaging-guidelines::RPMMacros.adoc#macros_installation[default rpm macro] defined. +The macros should always be used when available, +so the executable is listed in `%files` as follows: + +[source, rpm-spec] +---- +%files +%{_bindir}/banner +---- + +=== Man pages + +---- +Installed (but unpackaged) file(s) found: +/usr/share/man/man1/banner.1.gz +---- + +The Packaging Guidelines have a dedicated section for +xref:packaging-guidelines::index.adoc#_manpages[Manpages]. +Following its instructions, manpages are list as follows: + +[source, rpm-spec] +---- +%{_mandir}/man1/banner.1.* +---- + +At this point, mockbuild completes successfully, +but there are still more files that we should add to the package. + +=== License file + +Every package must install its license, tagged with `%license` directive. +In banner's case, as well as for many other projects, +the license file is located at the source tarball's top level, +and perhaps not copied to the buildroot during installation at all. +Regardless, it can be installed to the standard license directory +by using a relative path: + +[source, rpm-spec] +---- +%files +%license COPYING +---- + +=== Additional documentation === + +Often, package sources contain documentation +that could be useful for the end users as well. +These can be installed and marked as documentation with the `%doc` directive. +Similarly to `%license`, +relative paths can be used to include files directly from the source tarball +rather than from the buildroot: + +[source, rpm-spec] +---- +%doc AUTHORS ChangeLog NEWS README.md +---- + +== Checking the result with rpmlint + +Next you should check for conformance with RPM design rules, +by running `rpmlint` on specfile, source rpm and binary rpm. +Command `fedpkg lint` does this: + +[subs="attributes+"] +---- +$ fedpkg --release f{MAJOROSVER} lint +---- + +If all is good, there should be no warnings or errors. +For tutorial's sake, we intentionally left a mistake in the previous steps: + +---- + banner.x86_64: E: zero-length /usr/share/doc/banner/NEWS +---- + +Descriptions of various error codes can be queried with `rpmlint -e `. +In this case, the unnecessary zero-length file must be removed. +Change the docs line to + +---- +%doc AUTHORS ChangeLog README.md +---- + +Run `fedpkg mockbuild` and `fedpkg lint` again and observe that the warning is fixed. + +== Complete specfile + +Here is the final version of `banner.spec`: + +[source, rpm-spec] +---- +Name: banner +Version: 1.3.6 +Release: %autorelease +Summary: Prints a short string to the console in very large letters +License: GPL-2.0-only +URL: https://github.com/pronovic/banner +Source: https://github.com/pronovic/banner/releases/download/BANNER_V%{version}/banner-%{version}.tar.gz +BuildRequires: gcc +BuildRequires: make + +%description +This is a classic-style banner program similar to the one found in Solaris or +AIX in the late 1990s. It prints a short string to the console in very large +letters. + +%prep +%autosetup + +%build +%configure +%make_build + +%install +%make_install + +%files +%{_bindir}/banner +%{_mandir}/man1/banner.1.* +%license COPYING +%doc AUTHORS ChangeLog README + +%changelog +%autochangelog +---- + +With this specfile, +you should be able to successfully complete the build process, +and create the source and binary RPM packages. + +== Checking the result + +Having a working specfile and rpms built from it, +the result can be checked. +Before checking the result by installing the package, +let us do some simple checks. +The RPM Package Manager `rpm` can be used for this. + +=== Files + +List the files contained in the package: + +[subs="attributes+"] +---- +$ rpm --query --package --list results_banner/6/1.fc{MAJOROSVER}/banner-1.3.6-1.fc{MAJOROSVER}.x86_64.rpm +/usr/bin/banner +/usr/lib/.build-id +/usr/lib/.build-id/01 +/usr/lib/.build-id/01/360ae02508eaa0a77d216953b8b658a1e90b10 +/usr/share/doc/banner +/usr/share/doc/banner/AUTHORS +/usr/share/doc/banner/ChangeLog +/usr/share/doc/banner/README +/usr/share/licenses/banner +/usr/share/licenses/banner/COPYING +/usr/share/man/man1/banner.1.gz +---- + +You can see that all the files listed in the specfile `%files` section are included. +Also, under `+/usr/lib/.build-id+`, there is an automatically generated file. +It is actually a symlink, +mapping a build id to the `banner` binary for debugging purposes. + +=== Requires + +List the package's runtime dependencies with the following command: + +[subs="attributes+"] +---- +$ rpm --query --package --requires results_banner/1.3.6/1.fc{MAJOROSVER}/banner-1.3.6-1.fc{MAJOROSVER}.x86_64.rpm +libc.so.6()(64bit) +libc.so.6(GLIBC_2.2.5)(64bit) +libc.so.6(GLIBC_2.3)(64bit) +libc.so.6(GLIBC_2.3.4)(64bit) +libc.so.6(GLIBC_2.34)(64bit) +libc.so.6(GLIBC_2.4)(64bit) +rpmlib(CompressedFileNames) <= 3.0.4-1 +rpmlib(FileDigests) <= 4.6.0-1 +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(PayloadIsZstd) <= 5.4.18-1 +rtld(GNU_HASH) +---- + +To check which packages in Fedora repositories provide these dependencies, +you can use `dnf repoquery`: + +[subs="attributes+"] +---- +$ dnf -C repoquery --whatprovides 'libc.so.6()(64bit)' +glibc-0:2.38-16.fc{MAJOROSVER}.x86_64 +glibc-0:2.38-7.fc{MAJOROSVER}.x86_64 +---- + +You will see that the only dependency of _banner_ is `glibc`, +which provides symbols in `libc.so.6` as well as `rtld(GNU_HASH)`. + +The `rpmlib` requires are special. +These specify various rpm features used in the rpm package itself, +constraining the version of `+rpm+` that can be used to install the package. + +=== Provides + +Conversely, to check what capabilities the package provides, you can do: + +[subs="attributes+"] +---- +$ rpm --query --package --provides results_banner/1.3.6/1.fc{MAJOROSVER}/banner-1.3.6-1.fc{MAJOROSVER}.x86_64.rpm +banner = 1.3.6-1.fc{MAJOROSVER} +banner(x86-64) = 1.3.6-1.fc{MAJOROSVER} +---- + +The provides of this package are very simple. +It simply provides its own name, +in plain and architecture specific forms. + +=== Installing + +As a final check, the package can be installed and ran: + +[subs="attributes+"] +---- +$ sudo dnf -C -y install ./results_banner/1.3.6/1.fc{MAJOROSVER}/banner-1.3.6-1.fc{MAJOROSVER}.x86_64.rpm +$ banner success + + ##### # # ##### ##### ####### ##### ##### +# # # # # # # # # # # # # +# # # # # # # # + ##### # # # # ##### ##### ##### + # # # # # # # # +# # # # # # # # # # # # # + ##### ##### ##### ##### ####### ##### ##### .. +---- + +To clean up your system, undo the installation: + +---- +$ sudo dnf -C -y history undo last +---- + +== Building in Fedora infrastructure + +Even though the package is not part of Fedora distribution yet, +a xref:Using_the_Koji_Build_System.adoc#scratch_builds[scratch build] can be performed +to ensure that the package builds successfully in Fedora's Koji build system, +and that it builds successfully for all architectures supported by Fedora. +Such build is started by passing a source rpm package to `fedpkg scratch-build`. + +Note that Koji uses Kerberos for authentication. +See xref:Installing_Packager_Tools.adoc#kerberos_ticket[Acquiring Kerberos Ticket] for details. + +[subs="attributes+"] +---- +$ fedpkg --release f{MAJOROSVER} scratch-build --srpm results_banner/1.3.6/1.fc{MAJOROSVER}/banner-1.3.6-1.fc{MAJOROSVER}.src.rpm +Building banner-1.3.6-1.fc{MAJOROSVER}.src.rpm for f{MAJOROSVER}-candidate +Created task: 92465688 +Task info: https://koji.fedoraproject.org/koji/taskinfo?taskID=92465688 +Watching tasks (this may be safely interrupted)... +---- + +You can open the task info link in a browser to view build progress, logs and results. +The command line program also reports on progress as it happens. +Successful execution looks something like this: + +[subs="attributes+"] +---- +92465688 build (f{MAJOROSVER}-candidate, banner-1.3.6-1.fc{MAJOROSVER}.src.rpm): free +92465688 build (f{MAJOROSVER}-candidate, banner-1.3.6-1.fc{MAJOROSVER}.src.rpm): free -> open (buildvm-ppc64le-25.iad2.fedoraproject.org) + 92465698 rebuildSRPM (noarch): open (buildvm-s390x-24.s390.fedoraproject.org) + 92465745 buildArch (banner-1.3.6-1.fc{MAJOROSVER}.src.rpm, x86_64): free + 92465748 buildArch (banner-1.3.6-1.fc{MAJOROSVER}.src.rpm, s390x): open (buildvm-s390x-19.s390.fedoraproject.org) + 92465746 buildArch (banner-1.3.6-1.fc{MAJOROSVER}.src.rpm, aarch64): open (buildvm-a64-26.iad2.fedoraproject.org) + 92465747 buildArch (banner-1.3.6-1.fc{MAJOROSVER}.src.rpm, ppc64le): open (buildvm-ppc64le-11.iad2.fedoraproject.org) + 92465744 buildArch (banner-1.3.6-1.fc{MAJOROSVER}.src.rpm, i686): open (buildhw-x86-12.iad2.fedoraproject.org) + 92465698 rebuildSRPM (noarch): open (buildvm-s390x-24.s390.fedoraproject.org) -> closed + 1 free 5 open 1 done 0 failed + 92465745 buildArch (banner-1.3.6-1.fc{MAJOROSVER}.src.rpm, x86_64): free -> open (buildhw-x86-06.iad2.fedoraproject.org) + 92465745 buildArch (banner-1.3.6-1.fc{MAJOROSVER}.src.rpm, x86_64): open (buildhw-x86-06.iad2.fedoraproject.org) -> closed + 0 free 5 open 2 done 0 failed + 92465748 buildArch (banner-1.3.6-1.fc{MAJOROSVER}.src.rpm, s390x): open (buildvm-s390x-19.s390.fedoraproject.org) -> closed + 0 free 4 open 3 done 0 failed + 92465746 buildArch (banner-1.3.6-1.fc{MAJOROSVER}.src.rpm, aarch64): open (buildvm-a64-26.iad2.fedoraproject.org) -> closed + 0 free 3 open 4 done 0 failed + 92465744 buildArch (banner-1.3.6-1.fc{MAJOROSVER}.src.rpm, i686): open (buildhw-x86-12.iad2.fedoraproject.org) -> closed + 0 free 2 open 5 done 0 failed +92465688 build (f{MAJOROSVER}-candidate, banner-1.3.6-1.fc{MAJOROSVER}.src.rpm): open (buildvm-ppc64le-25.iad2.fedoraproject.org) -> closed + 0 free 1 open 6 done 0 failed + 92465747 buildArch (banner-1.3.6-1.fc{MAJOROSVER}.src.rpm, ppc64le): open (buildvm-ppc64le-11.iad2.fedoraproject.org) -> closed + 0 free 0 open 7 done 0 failed + +92465688 build (f{MAJOROSVER}-candidate, banner-1.3.6-1.fc{MAJOROSVER}.src.rpm) completed successfully +---- + +== References + +* https://rpm-software-management.github.io/rpm/manual/[RPM Reference Manual] + +* https://fedoraproject.org/wiki/Using_Mock_to_test_package_builds[Using Mock to test package builds] + +* xref:Using_the_Koji_Build_System.adoc[Using the Koji build system] + +* https://www.redhat.com/sysadmin/create-rpm-package[How to create a Linux RPM package] diff --git a/modules/ROOT/pages/Packaging_Tutorial_2_GNU_Hello.adoc b/modules/ROOT/pages/Packaging_Tutorial_2_GNU_Hello.adoc new file mode 100644 index 0000000..7c53687 --- /dev/null +++ b/modules/ROOT/pages/Packaging_Tutorial_2_GNU_Hello.adoc @@ -0,0 +1,454 @@ +include::{partialsdir}/attributes.adoc[] + += Packaging Tutorial 2: GNU Hello +:page-aliases: quick-docs::creating-rpm-packages.adoc +:page-aliases: Packaging_Tutorial_GNU_Hello.adoc + +This tutorial demonstrates RPM packaging +by packaging the https://www.gnu.org/software/hello/[GNU Hello] program. +While the program itself is simple, +it also comes with many peripheral components of a FOSS project: +configuration/build/install environment, documentation, internationalization,etc. + +This tutorial is the second part of Fedora packaging tutorial. +It follows the same basic structure as xref:Packaging_Tutorial_1_banner.adoc[part 1]. +If you have not completed it yet, please do so before continuing with this tutorial. + +The steps in this part are similar to part 1. +However, GNU Hello has more quirks than Banner does, so some workarounds and custom steps are needed. +Each package's quirks are unique, +so these are best viewed as examples of the kind of problems that may arise when packaging. + +[#dev_env] +== Installing Packager Tools + +Follow xref:Installing_Packager_Tools.adoc[Installing Packager Tools]. + +[#building] +== Creating the package directory + +For GNU Hello, the package can simply be named `hello`. +This is also the name of Fedora's https://packages.fedoraproject.org/pkgs/hello/hello/[official GNU Hello package]. + +---- +$ mkdir hello && cd hello +---- + +[#inside_spec] +== Inside a Spec File + +Create a file called `hello.spec` and paste the following minimal specfile. +This already has `BuildRequires` tags for `gcc` and `make`, +since that topic was already covered in part 1. +Similarly, `%files` section already includes the resulting binary, man pages, documentation and license file. +For GNU Hello, all these files are very similar to corresponding files in Banner, +and were thus already covered in part 1. + +Also, for reasons that are too complex to explain in a tutorial, +in some situations `texinfo` package is also needed, +and so a `BuildRequires` line is added for it. + +[source, rpm-spec] +---- +Name: hello +Version: 2.10 +Release: %autorelease +Summary: Produces a familiar, friendly greeting +License: GPL-3.0-or-later +URL: https://www.gnu.org/software/hello/ +Source: http://ftp.gnu.org/gnu/hello/hello-%{version}.tar.gz +BuildRequires: gcc +BuildRequires: make +BuildRequires: texinfo + +%description +The GNU Hello program produces a familiar, friendly greeting. Yes, this is +another implementation of the classic program that prints "Hello, world!" when +you run it. + +%prep +%autosetup + +%build +%configure +%make_build + +%install +%make_install + +%files +%{_bindir}/hello +%{_mandir}/man1/hello.1.* +%doc AUTHORS ChangeLog NEWS README THANKS TODO +%license COPYING + +%changelog +%autochangelog +---- + +== Downloading source + +Download sources and check that you now have them: + +---- +$ spectool -g hello.spec +$ ls *.tar.gz +hello-2.10.tar.gz +---- + +== Building the Package + +[subs="attributes+"] +---- +$ fedpkg --release f{MAJOROSVER} mockbuild +---- + +This command fails because of unpackaged files. + +== Installing files + +As in part 1, we will go through the file list one by one. +Run `fedpkg --release f{MAJOROSVER} mockbuild` again after each change to see the progress. + +=== Texinfo pages + +---- +Installed (but unpackaged) file(s) found: +/usr/share/info/dir +/usr/share/info/hello.info.gz +---- + +These are https://www.gnu.org/software/texinfo/[Texinfo] pages. +Texinfo is a documentation system like man pages, but much less common. +Texinfo pages are handled much in the same way as man pages. +The directory is defined by the default macro `+{_infodir}+`, +so the Texinfo manual can be added as follows: + +[source, rpm-spec] +---- +%files +⋮ +%{_infodir}/hello.info.* +---- + +The `+dir+` file generated by GNU Hello build script indexes all texinfo pages in your system. +Because the installed pages differ among systems, the file cannot be prebuilt and packaged. +Instead it needs to be created and updated when the package is installed. +The update is automatically performed by RPM triggers in `+info+` binary package of +https://src.fedoraproject.org/rpms/texinfo[texinfo source package]. + +To prevent from installing the `dir` file, +remove it from the _buildroot_ at the end of the `%install` section with `rm` command. + +However, GNU Hello build script only generates the `dir` file +if `info` package is installed during the build. +Blindly removing the file would raise an error if +the `hello` package were built on a system without `info` package. +To handle both cases, delete the file if it exists: + +[source, rpm-spec] +---- +%install +⋮ +test -f %{buildroot}/%{_infodir}/dir && rm %{buildroot}/%{_infodir}/dir +---- + +=== Translations + +---- +Installed (but unpackaged) file(s) found: +/usr/share/locale/bg/LC_MESSAGES/hello.mo +/usr/share/locale/ca/LC_MESSAGES/hello.mo +/usr/share/locale/da/LC_MESSAGES/hello.mo +⋮ +---- + +Since our program uses translations and internationalization, +we are seeing a lot of undeclared i18n files. +The xref:packaging-guidelines::index.adoc#handling_locale_files[recommended method] +to declare them is: + +. Add the required build dependency with `+BuildRequires: gettext+`. +. Find the filenames in the `+%install+` step with `+%find_lang %{name}+`. +. Install the files with `+%files -f %{name}.lang+`. + +After these changes, build succeeds. + +== Running tests + +GNU Hello, like many other projects, +includes an automated test suite in the sources. +If at all possible, +the test suite should be run during the rpm build. +This helps ensuring that a working build was produced. +This is done by adding the test suite invocation +to specfile `+%check%+` section, +which comes after `+%install+` in order. +In GNU Hello's case: + +[source, rpm-spec] +---- +%check +make check +---- + +Run a mockbuild again +and check the output to ensure that the tests were actually run. +Something like this should be somewhere in the output: + +---- +============================================================================ +Testsuite summary for GNU Hello 2.10 +============================================================================ +# TOTAL: 5 +# PASS: 4 +# SKIP: 1 +# XFAIL: 0 +# FAIL: 0 +# XPASS: 0 +# ERROR: 0 +============================================================================ +---- + +== Fixing automagic == + +Now the package successfully builds. +But that does not mean that the `.spec` file is correct. + +=== Listing all build-time dependencies === + +If you carefully read a build output, +you can discover lines which mention `sed` command: + +---- ++ /usr/bin/make -O -j4 V=1 VERBOSE=1 +rm -f lib/arg-nonnull.h-t lib/arg-nonnull.h && \ +sed -n -e '/GL_ARG_NONNULL/,$p' \ +---- + +Therefore you need to add this line close to other BuildRequires lines: + +[source, rpm-spec] +---- +BuildRequires: sed +---- + +Similarly, studying `configure` script in the unpackaged sources, +which is executed by `%configure` macro, +reveals it's a `/bin/sh` script: + +---- +$ head configure +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for GNU Hello 2.10. +---- + +Thus you also should record this dependency on `bash`: + +[source, rpm-spec] +---- +BuildRequires: bash +---- + +Why on `bash`? +Because `/bin/sh` program is provided by `bash` package: + +---- +$ rpm --queryformat '%{name}\n' --query --file /bin/sh +bash +---- + +Specifying all used dependencies helps +to make the `.spec` file resilient against changes in the build environment. +If e.g. `sed` package were removed from the environment, +this GNU Hello package would fail to build. + +=== Listing all build options === + +The GNU Hello build script, `configure` has many build options +which enable or disable optional features. +Their nondefault forms can be listed with `--help` option: + +---- +$ ./configure --help +`configure' configures GNU Hello 2.10 to adapt to many kinds of systems. + +Usage: ./configure [OPTION]... [VAR=VALUE]... +⋮ +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --disable-nls do not use Native Language Support + --disable-rpath do not hardcode runtime library paths +---- + +Some of them are already specified within `%configure` and `%make_build` +macros. The rest of the options, if they are important for the built package, +should be explicitly written in the `.spec` file to prevent from their +sudden and unnoticed changes. Either because a new Hello version changes the +default, or because a package which they depend on appears of disappears from +the build environment. + +Therefore modify `%configure` invocation in `%build` section like this: + + +[source, rpm-spec] +---- +%configure --enable-nls --disable-rpath +---- + +== Checking the result with rpmlint + +Check with `fedpkg lint` reveals a problem: + +[subs="attributes+"] +---- +$ fedpkg --release f{MAJOROSVER} lint +hello.x86_64: W: file-not-utf8 /usr/share/doc/hello/THANKS +---- + +In order to ensure a pure utf-8 installation, the file needs to be converted in `%prep`. +This can be done with the `iconv` utility which is provided by `glibc-common` package, +and `mv` tool from `coreutils`: + +---- +BuildRequires: coreutils +BuildRequires: glibc-common +⋮ +%prep +⋮ +mv THANKS THANKS.old +iconv --from-code=ISO-8859-1 --to-code=UTF-8 --output=THANKS THANKS.old +---- + +Run `fedpkg lint` again and observe that the warning is fixed. + +== A Complete hello.spec File + +Here is the final version of `hello.spec`: + +[source, rpm-spec] +---- +Name: hello +Version: 2.10 +Release: %autorelease +Summary: Produces a familiar, friendly greeting + +License: GPL-3.0-or-later +URL: http://ftp.gnu.org/gnu/%{name} +Source: http://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.gz + +BuildRequires: bash +BuildRequires: coreutils +BuildRequires: gcc +BuildRequires: gettext +BuildRequires: glibc-common +BuildRequires: make +BuildRequires: sed +BuildRequires: texinfo + +%description +The GNU Hello program produces a familiar, friendly greeting. Yes, this is +another implementation of the classic program that prints "Hello, world!" when +you run it. + +%prep +%autosetup +mv THANKS THANKS.old +iconv --from-code=ISO-8859-1 --to-code=UTF-8 --output=THANKS THANKS.old + +%build +%configure --enable-nls --disable-rpath +%make_build + +%install +%make_install +test -f %{buildroot}/%{_infodir}/dir && rm %{buildroot}/%{_infodir}/dir +%find_lang %{name} + +%check +make check + +%files -f %{name}.lang +%{_mandir}/man1/hello.1.* +%{_infodir}/hello.info.* +%{_bindir}/hello +%doc AUTHORS ChangeLog NEWS README THANKS TODO +%license COPYING + +%changelog +%autochangelog +---- + +With this `.spec` file, +you should be able to successfully complete the build process, +and create the source and binary RPM packages. + +== Checking the result + +You can now check the result with `rpm`, like was done in part 1. + +=== Files + +List the files contained in the package: + +[subs="attributes+"] +---- +$ rpm --query --package --list results_hello/2.10/1.fc{MAJOROSVER}/hello-2.10-1.fc{MAJOROSVER}.x86_64.rpm +/usr/bin/hello +/usr/lib/.build-id +/usr/lib/.build-id/39 +/usr/lib/.build-id/39/c97ecb15c6292ce23e8b00e15e6e72a61e5072 +/usr/share/doc/hello +/usr/share/doc/hello/AUTHORS +⋮ +/usr/share/doc/hello/TODO +/usr/share/info/hello.info.gz +/usr/share/licenses/hello +/usr/share/licenses/hello/COPYING +/usr/share/locale/bg/LC_MESSAGES/hello.mo +⋮ +/usr/share/locale/zh_TW/LC_MESSAGES/hello.mo +/usr/share/man/man1/hello.1.gz +---- + +You can see that all the files listed in the specfile `%files` section are included, +including the automatically processed locale files. +Also the `.build-id` file is there, just like in part 1. + +=== Requires and Provides + +You can list list the package's runtime dependencies and the capabilities it provides +with the following two commands. +The output is similar to corresponding output in part 1. + +[subs="attributes+"] +---- +$ rpm --query --package --requires results_hello/2.10/1.fc{MAJOROSVER}/hello-2.10-1.fc{MAJOROSVER}.x86_64.rpm +$ rpm --query --package --provides results_hello/2.10/1.fc{MAJOROSVER}/hello-2.10-1.fc{MAJOROSVER}.x86_64.rpm +---- + +=== Installing + +As a final check, the package can be installed and ran: + +[subs="attributes+"] +---- +$ sudo dnf -C -y install ./results_hello/2.10/1.fc{MAJOROSVER}/hello-2.10-1.fc{MAJOROSVER}.x86_64.rpm +$ hello --greeting="Hello, rpm!" +Hello, rpm! +---- + +To clean up your system, undo the installation: + +---- +$ sudo dnf -C -y history undo last +---- diff --git a/modules/ROOT/pages/Packaging_Tutorial_GNU_Hello.adoc b/modules/ROOT/pages/Packaging_Tutorial_GNU_Hello.adoc deleted file mode 100644 index a9cb176..0000000 --- a/modules/ROOT/pages/Packaging_Tutorial_GNU_Hello.adoc +++ /dev/null @@ -1,773 +0,0 @@ -include::{partialsdir}/attributes.adoc[] - -= Packaging Tutorial: GNU Hello -:page-aliases: quick-docs::creating-rpm-packages.adoc - -This tutorial demonstrates RPM packaging -by packaging the https://www.gnu.org/software/hello/[GNU Hello] program. -While the program itself is simple, -it also comes with most of the usual peripheral components of a FOSS project: -configuration/build/install environment, -documentation, -internationalization, -etc. -However, it does not include RPM packaging information, -therefore it is a reasonable vehicle to practice building RPMs on. - -For comprehensive information on how to create RPM files, -refer to https://rpm-software-management.github.io/rpm/manual/[RPM Reference Manual]. -If you plan to create an RPM package for the Fedora repository, -follow the process for xref:Joining_the_Package_Maintainers.adoc[Joining the Package Maintainers], -including following the various Fedora guidance. - -This tutorial is intended to be run on a Fedora {MAJOROSVER} system. -It should, however, work also for other Fedora releases. -Just replace strings like `f{MAJOROSVER}` with your release number. -Fedora downstreams such as CentOS Stream or Red Hat Enterprise Linux are unlikely to work, -because this tutorial uses Fedora specific and very recent tools and features. -In particular, https://docs.pagure.org/fedora-infra.rpmautospec/[rpmautospec] is unlikely to be available. - -The tutorial proceeds in step by step manner, -with most steps editing the package's specfile. -The final resulting specfile is listed in the end, -so in case there is any unclarity how a particular change should be applied, -you can peek there. - -[#dev_env] -== Installing Packager Tools - -Follow xref:Installing_Packager_Tools.adoc[Installing Packager Tools]. - -[#building] -== Creating the package directory - -In Fedora, package build instructions are organized in so called dist-git repositories. -There is a separate repository for each package. -We mimic this system by creating a new directory for this tutorial. -In dist-git, the repository name matches the package name. -Fedora's rules for naming packages are written in https://docs.fedoraproject.org/en-US/packaging-guidelines/Naming/[Naming Guidelines]. -For GNU Hello, package can simply be named `hello`. -This is also the name of Fedora's https://packages.fedoraproject.org/pkgs/hello/hello/[official GNU Hello package]. - ----- -$ mkdir hello && cd hello ----- - -[#inside_spec] -== Inside a Spec File - -RPM packages are configured by `.spec` files. -Tools such was `rpmdev-newspec` can be used to generate empty specfiles for different purposes. -For this tutorial, just create a file called `hello.spec` and paste the following minimal specfile. -It does not work yet, but we will try to build it and fix errors as we encounter them. - -[source, rpm-spec] ----- -Name: hello -Version: 2.10 -Release: %autorelease -Summary: Produces a familiar, friendly greeting -License: GPL-3.0-or-later -URL: https://www.gnu.org/software/hello/ -Source: http://ftp.gnu.org/gnu/hello/hello-%{version}.tar.gz - -%description -The GNU Hello program produces a familiar, friendly greeting. Yes, this is -another implementation of the classic program that prints "Hello, world!" when -you run it. - -%prep -%autosetup - -%build -%configure -%make_build - -%install -%make_install - -%files - -%changelog -%autochangelog ----- - -The specfile starts with a set of _tags_, such as `Name:` and `Version:`, -followed by _sections_ such as `%description` and `%prep`. -Each tag fits into a single line, whereas each section continues until the next one starts. - -Note that, confusingly, in addition to marking the section names, -the percent sign `%` also marks RPM _macros_. -Thus e.g. `%autosetup`, `%configure` and `%make_build` are not sections. - -=== Tags - -`+Version+` contains the version number of the packaged software. - -`+Release+` numbers specfile updates, package rebuilds and other work within Fedora. -The value used here, `+%autorelease+`, is part of https://docs.pagure.org/fedora-infra.rpmautospec/index.html[rpmautospec], -which is https://fedoraproject.org/wiki/Changes/Rpmautospec_by_Default[recommended for Fedora packages]. -It ties `+Release+` to package's Git history. -As we do not have a Git repository, `%autorelease` will evaluate to the default value of 1. - - -Often, `+Summary+` can be copied from the upstream README. -The first letter should be uppercase to avoid `+rpmlint+` complaints. - -`+License+` describes the license of the resulting binary package using a SPDX license identifier. -It must follow Fedora's https://docs.fedoraproject.org/en-US/legal/license-field/[licensing guidelines]. -In practice, determining the correct value often means inspecting the license notifications in individual source files. -Upstream developers may also need to be asked for clarifications or corrections. -In this tutorial, we just take the upstream's word that the license is the GNU Public License, version 3 or later. - -`+URL+` points to upstream project's website. - -`+Source+` defines the upstream sources used when building the package. -Usually, as in this case, it is a url pointing to a tarball released by the upstream, -but it can also be a local file. -There can be multiple `+Source+` tags if needed. - -=== Sections - -`+%description+` can often be copied from upstream README. - -`%prep` contains a shell script for preparing the sources for building. -It is often just the single macro `%autosetup`, -which, in this case, simply extracts the source. - -`%build` contains a shell script for the required build steps, -such as compiling sources to binaries. -GNU Hello uses https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html[Autotools] as its buildsystem, -so building involves running `configure` and `make`. -Macros `%configure` and `%make_build` invoke these commands using Fedora's compilation flags and other configuration. - -`%install` contains a shell script to copy the results from `%build` into an initially empty _build root_ directory. -As GNU Hello is using Autotools, macro `%make_install` is used. - -`%files` lists the content of the resulting package. -Mostly, the files come from the build root created in the `%install`, -but documentation and license files can also be added directly from the sources. -This section is left empty for now, to be filled later. - -The `+%changelog+` documents the changes in each new package version and release. -Changelog data can be displayed by `+rpm --query --changelog PACKAGE_NAME+`, -which can be useful, for instance, to find out if specific bug and security patches are included. -Its value,`+%autochangelog+`, also comes from `rpmautospec`. -It populates the changelog from Git commit messages. -As we do not have a Git repository, the changelog will be empty. - -Lines which are not needed can be commented out with the hash `+#+`. - -You can find more information in the RPM Reference Manual's section https://rpm-software-management.github.io/rpm/manual/spec.html[Spec file format]. - -== Downloading source - -We need the source code defined by the `+Source+` tag, often referred to as the _upstream_ source. -This is most easily achieved by using the `spectool` command: - ----- -$ spectool -g hello.spec ----- - -You should now have the file listed in `+Source+` in your working directory: - ----- -$ ls *.tar.gz -hello-2.10.tar.gz ----- - -== Building the Package - -We are ready for the first run to build source, binary and debugging packages. -This, and many other tasks, are done with the `fedpkg` tool. -The production builds for Fedora are built -in the https://koji.fedoraproject.org[Koji] build system, -which in turn uses https://rpm-software-management.github.io/mock/[Mock] -to manage isolated build environments. -To get as close to a production build as is locally possible, -we use the `fedpkg mockbuild` command -which also invokes Mock: - -[subs="attributes+"] ----- -$ fedpkg --release f{MAJOROSVER} mockbuild ----- - -The build environment created by Mock is very basic. -It does not include a C compiler by default, -so the build will fail. -The reason is explained in the output: - ----- -checking whether the C compiler works... no -configure: error: in `/builddir/build/BUILD/hello-2.10': -configure: error: C compiler cannot create executables -See `config.log' for more details -error: Bad exit status from /var/tmp/rpm-tmp.D2nN0w (%build) - Bad exit status from /var/tmp/rpm-tmp.D2nN0w (%build) ----- - -Additional build tools are defined -by adding `+BuildRequires:+` rows to the specfile. -In Fedora, GCC is the standard compiler, -so we need to add a row for `+gcc+`. -GNU Hello also uses `+make+`, so a row should be added for it, too. -Add these lines after `Source`: - -[source, rpm-spec] ----- -BuildRequires: gcc -BuildRequires: make ----- - -For reasons that are too complex to explain in a tutorial, -in some situations `texinfo` package is also needed. -To avoid a possible error, add one more row: - -[source, rpm-spec] ----- -BuildRequires: texinfo ----- - -Run a mockbuild again. -The earlier error should be gone. - -== Installing files - -The next thing rpm will complain about are unpackaged files, -i.e. the files that would be installed in the system, -but were not declared as belonging to the package. -We need to declare them in the `+%files+` section. -Fixing these errors is an iterative process. -After declaring a missing file in the `+.spec+` file, -run `+fedpkg+` again, -then declare the next missing file and so on. - -We will go through the file list one by one. - -=== Executable - ----- -Installed (but unpackaged) file(s) found: -/usr/bin/hello ----- - -This is the executable binary program. -`+/usr/bin+`, like many other system directories, have a -xref:packaging-guidelines::RPMMacros.adoc#macros_installation[default rpm macro] defined. -The macros should always be used when available, -so the executable is listed in `+%files+` as follows: - -[source, rpm-spec] ----- -%files -%{_bindir}/hello ----- - -=== Man pages - ----- -Installed (but unpackaged) file(s) found: -/usr/share/man/man1/hello.1.gz ----- - -The Packaging Guidelines have a dedicated section for -xref:packaging-guidelines::index.adoc#_manpages[Manpages]. -Following its instructions, manpages are list as follows: - -[source, rpm-spec] ----- -%{_mandir}/man1/hello.1.* ----- - -=== Texinfo pages - ----- -Installed (but unpackaged) file(s) found: -/usr/share/info/dir -/usr/share/info/hello.info.gz ----- - -Texinfo pages are handled much in the same way as man pages. -The directory is defined by the default macro `+{_infodir}+`, -so the Texinfo manual can be added as follows: - -[source, rpm-spec] ----- -%{_infodir}/hello.info.* ----- - -The `+dir+` file generated by GNU Hello build script indexes all texinfo pages -in your system. Because the installed pages differ among systems, the file -cannot be prebuilt and packaged. Instead it needs to be created and updated -when the package is installed. The update is automatically performed by rpm -triggers in `+info+` binary package of -https://src.fedoraproject.org/rpms/texinfo[texinfo source package]. - -To prevent from installing the `+dir+` file, remove it from the _buildroot_ at -the end of the `+%install+` section with `+rm+` command. - -However, GNU Hello build script only generates the `+dir+` file if `+info+` -package is installed during the build. Blindly removing the file would raise -an error if the `+hello+` package were built on a system without `+info+` -package. To deal with both cases, delete the file if it exists: - -[source, rpm-spec] ----- -%install -%make_install -test -f %{buildroot}/%{_infodir}/dir && rm %{buildroot}/%{_infodir}/dir ----- - -=== Translations - ----- -Installed (but unpackaged) file(s) found: -/usr/share/locale/bg/LC_MESSAGES/hello.mo -/usr/share/locale/ca/LC_MESSAGES/hello.mo -/usr/share/locale/da/LC_MESSAGES/hello.mo -... ----- - -Since our program uses translations and internationalization, -we are seeing a lot of undeclared i18n files. -The xref:packaging-guidelines::index.adoc#handling_locale_files[recommended method] -to declare them is: - -. Add the required build dependency with `+BuildRequires: gettext+`. -. Find the filenames in the `+%install+` step with `+%find_lang %{name}+`. -. Install the files with `+%files -f %{name}.lang+`. - -=== License file - -Every package must install its license, -tagged with `+%license+` directive. -In GNU Hello's case, as well as for many other projects, -the license file is located at the source tarball's top level, -and perhaps not copied to the buildroot during installation at all. -Regardless, it can be installed to the standard license directory -by using a relative path: - -[source, rpm-spec] ----- -%license COPYING ----- - -=== Additional documentation === - -Often, package sources contain documentation -that could be useful for the end users as well. -These can be installed and marked as documentation with the `+%doc+` directive. -Similarly to `+%license+`, -relative paths can be used to include files directly from the source tarball -rather than from the buildroot: - -[source, rpm-spec] ----- -%doc AUTHORS ChangeLog NEWS README THANKS TODO ----- - -== Running tests - -GNU Hello, like many other projects, -includes an automated test suite in the sources. -If at all possible, -the test suite should be run during the rpm build. -This helps ensuring that a working build was produced. -This is done by adding the test suite invocation -to specfile `+%check%+` section, -which comes after `+%install+` in order. -In GNU Hello's case: - -[source, rpm-spec] ----- -%check -make check ----- - -Run a mockbuild again -and check the output to ensure that the tests were actually run. -Something like this should be somewhere in the output: - ----- -============================================================================ -Testsuite summary for GNU Hello 2.10 -============================================================================ -# TOTAL: 5 -# PASS: 4 -# SKIP: 1 -# XFAIL: 0 -# FAIL: 0 -# XPASS: 0 -# ERROR: 0 -============================================================================ ----- - -== Fixing automagic == - -Now the package succefully builds. But that does not mean that the `.spec` -file is correct. - -=== Listing all build-time dependencies === - -If you carefully read a build output, you can discover lines which mention -`+sed+` command: - ----- -+ /usr/bin/make -O -j4 V=1 VERBOSE=1 -rm -f lib/arg-nonnull.h-t lib/arg-nonnull.h && \ -sed -n -e '/GL_ARG_NONNULL/,$p' \ ----- - -Therefore you need to add this line close to other BuildRequires lines: - -[source, rpm-spec] ----- -BuildRequires: sed ----- - -Smilarly, studying `+configure+` script in the unpackaged sources, which is -executed by `+%configure+` macro, reveals it's a `/bin/sh` script: - ----- -$ head configure -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for GNU Hello 2.10. ----- - -Thus you also should record this dependency on `+bash+`: - -[source, rpm-spec] ----- -BuildRequires: bash ----- - -Why on `+bash+`? Because `+/bin/sh+` program is provided by `+bash+` package: - ----- -rpm --qf '%{name}\n' -qf /bin/sh -bash ----- - -Specifying all used dependencies helps to make the `.spec` file resilient -against changes in the build environment. If e.g. `+sed+` package were removed -from the environment, this GNU Hello package would fail to build. - -=== Listing all build options === - -The GNU Hello build script, `+configure+` has many build options which enables -or disables optional features. Their nondefault forms can be listed with -`+--help+` option: - ----- -$ ./configure --help -`configure' configures GNU Hello 2.10 to adapt to many kinds of systems. - -Usage: ./configure [OPTION]... [VAR=VALUE]... -⋮ -Optional Features: - --disable-option-checking ignore unrecognized --enable/--with options - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-silent-rules less verbose build output (undo: "make V=1") - --disable-silent-rules verbose build output (undo: "make V=0") - --enable-dependency-tracking - do not reject slow dependency extractors - --disable-dependency-tracking - speeds up one-time build - --disable-nls do not use Native Language Support - --disable-rpath do not hardcode runtime library paths ----- - -Some of them are already specified within `+%configure+` and `+%make_build+` -macros. The rest of the options, if they are important for the built package, -should be explicitly written in the `.spec` file to prevent from their -sudden and unnoticed changes. Either because a new Hello version changes the -default, or because a package which they depend on appears of disappears from -the build environment. - -Therefore modify `+%configure+` invocation in `+%build+` section like this: - - -[source, rpm-spec] ----- -%configure \ - --enable-nls \ - --disable-rpath ----- - -== Checking the result with rpmlint - -Next you should check them for conformance with RPM design rules, -by running `rpmlint` on specfile, source rpm and binary rpm. -Command `+fedpkg lint+` does this: - -[subs="attributes+"] ----- -$ fedpkg --release f{MAJOROSVER} lint ----- - -If all is good, there should be no warnings or errors. -In the GNU Hello case, -one warning can be expected: - ----- -hello.x86_64: W: file-not-utf8 /usr/share/doc/hello/THANKS ----- - -Descriptions of various error codes can be queried -with `+rpmlint -e +`. -In this case, in order to ensure a pure utf-8 installation, -the file needs to be converted in `+%prep+`. -This can be done with the `+iconv+` utility which is provided by -`+glibc-common+` package, and `+mv+` tool from `+coreutils+`: - ----- -BuildRequires: coreutils -BuildRequires: glibc-common -⋮ -mv THANKS THANKS.old -iconv --from-code=ISO-8859-1 --to-code=UTF-8 --output=THANKS THANKS.old ----- - -Run `fedpkg lint` again and observe that the warning is fixed. - -== A Complete hello.spec File - -Here is the final version of `hello.spec`: - -[source, rpm-spec] ----- -Name: hello -Version: 2.10 -Release: %autorelease -Summary: Produces a familiar, friendly greeting - -License: GPL-3.0-or-later -URL: http://ftp.gnu.org/gnu/%{name} -Source: http://ftp.gnu.org/gnu/%{name}/%{name}-%{version}.tar.gz - -BuildRequires: bash -BuildRequires: coreutils -BuildRequires: gcc -BuildRequires: gettext -BuildRequires: glibc-common -BuildRequires: make -BuildRequires: sed -BuildRequires: texinfo - -%description -The GNU Hello program produces a familiar, friendly greeting. Yes, this is -another implementation of the classic program that prints "Hello, world!" when -you run it. - -%prep -%autosetup -mv THANKS THANKS.old -iconv --from-code=ISO-8859-1 --to-code=UTF-8 --output=THANKS THANKS.old - -%build -%configure \ - --enable-nls \ - --disable-rpath -%make_build - -%install -%make_install -test -f %{buildroot}/%{_infodir}/dir && rm %{buildroot}/%{_infodir}/dir -%find_lang %{name} - -%check -make check - -%files -f %{name}.lang -%{_mandir}/man1/hello.1.* -%{_infodir}/hello.info.* -%{_bindir}/hello -%doc AUTHORS ChangeLog NEWS README THANKS TODO -%license COPYING - -%changelog -%autochangelog ----- - -With this `.spec` file, -you should be able to successfully complete the build process, -and create the source and binary RPM packages. - -== Checking the result - -Having a working specfile and rpms built from it, -the result can be checked. -Before checking the result by installing the package, -let us do some simple checks. -The RPM Package Manager `rpm` can be used for this. - -=== Files - -List the files contained in the package: - -[subs="attributes+"] ----- -$ rpm --query --package --list results_hello/2.10/1.fc{MAJOROSVER}/hello-2.10-1.fc{MAJOROSVER}.x86_64.rpm -/usr/bin/hello -/usr/lib/.build-id -/usr/lib/.build-id/39 -/usr/lib/.build-id/39/c97ecb15c6292ce23e8b00e15e6e72a61e5072 -/usr/share/doc/hello -/usr/share/doc/hello/AUTHORS -/usr/share/doc/hello/ChangeLog -/usr/share/doc/hello/NEWS -/usr/share/doc/hello/README -/usr/share/doc/hello/THANKS -/usr/share/doc/hello/TODO -/usr/share/info/hello.info.gz -/usr/share/licenses/hello -/usr/share/licenses/hello/COPYING -/usr/share/locale/bg/LC_MESSAGES/hello.mo -... -/usr/share/locale/zh_TW/LC_MESSAGES/hello.mo -/usr/share/man/man1/hello.1.gz ----- - -You can see that all the files listed in the specfile `+%files+` section are included, -including the automatically processed locale files. -Also, under `+/usr/lib/.build-id+`, -there is an automatically generated file. -It is actually a symlink, -mapping a build id to the `+hello+` binary for debugging purposes. - -=== Requires - -List the package's runtime dependencies with the following command: - -[subs="attributes+"] ----- -$ rpm --query --package --requires results_hello/2.10/1.fc{MAJOROSVER}/hello-2.10-1.fc{MAJOROSVER}.x86_64.rpm -libc.so.6()(64bit) -libc.so.6(GLIBC_2.14)(64bit) -libc.so.6(GLIBC_2.2.5)(64bit) -libc.so.6(GLIBC_2.3)(64bit) -libc.so.6(GLIBC_2.3.4)(64bit) -libc.so.6(GLIBC_2.34)(64bit) -libc.so.6(GLIBC_2.4)(64bit) -libc.so.6(GLIBC_2.7)(64bit) -rpmlib(CompressedFileNames) <= 3.0.4-1 -rpmlib(FileDigests) <= 4.6.0-1 -rpmlib(PayloadFilesHavePrefix) <= 4.0-1 -rpmlib(PayloadIsZstd) <= 5.4.18-1 -rtld(GNU_HASH) ----- - -To check which packages in Fedora repositories provide these dependencies, -you can use `dnf repoquery`: - -[subs="attributes+"] ----- -$ dnf -C repoquery --whatprovides 'libc.so.6()(64bit)' -glibc-0:2.34-11.fc{MAJOROSVER}.x86_64 -glibc-0:2.34-7.fc{MAJOROSVER}.x86_64 ----- - -You will see that the only dependency of GNU Hello is `+glibc+`, -which provides symbols in `+libc.so.6+` as well as `+rtld(GNU_HASH)+`. - -The `+rpmlib+` requires are special. -These specify various rpm features used in the rpm package itself, -constraining the version of `+rpm+` that can be used to install the package. - -=== Provides - -Conversely, to check what capabilities the package provides, you can do: - -[subs="attributes+"] ----- -$ rpm --query --package --provides results_hello/2.10/1.fc{MAJOROSVER}/hello-2.10-1.fc{MAJOROSVER}.x86_64.rpm -hello = 2.10-1.fc{MAJOROSVER} -hello(x86-64) = 2.10-1.fc{MAJOROSVER} ----- - -The provides of this package are very simple. -It simply provides its own name, -in plain and architecture specific forms. - -=== Installing - -As a final check, the package can be installed and ran: - -[subs="attributes+"] ----- -$ sudo dnf -C -y install ./results_hello/2.10/1.fc{MAJOROSVER}/hello-2.10-1.fc{MAJOROSVER}.x86_64.rpm -$ hello --greeting="Hello, rpm!" -Hello, rpm! ----- - -To clean up your system, undo the installation: - ----- -$ sudo dnf -C -y history undo last ----- - -== Building in Fedora infrastructure - -Even though the package is not part of Fedora distribution yet, -a xref:Using_the_Koji_Build_System.adoc#scratch_builds[scratch build] can be performed -to ensure that the package builds successfully in Fedora's Koji build system, -and that it builds successfully for all architectures supported by Fedora. -Such build is started by passing a source rpm package to `fedpkg scratch-build`. - -Note that Koji uses Kerberos for authentication. -See xref:Installing_Packager_Tools.adoc#kerberos_ticket[Acquiring Kerberos Ticket] for details. - -[subs="attributes+"] ----- -$ fedpkg --release f{MAJOROSVER} scratch-build --srpm results_hello/2.10/1.fc{MAJOROSVER}/hello-2.10-1.fc{MAJOROSVER}.src.rpm -Building hello-2.10-1.fc{MAJOROSVER}.src.rpm for f{MAJOROSVER}-candidate -Created task: 92465688 -Task info: https://koji.fedoraproject.org/koji/taskinfo?taskID=92465688 -Watching tasks (this may be safely interrupted)... ----- - -You can open the task info link in a browser to view build progress, logs and results. -The command line program also reports on progress as it happens. -Successful execution looks something like this: - -[subs="attributes+"] ----- -92465688 build (f{MAJOROSVER}-candidate, hello-2.10-1.fc{MAJOROSVER}.src.rpm): free -92465688 build (f{MAJOROSVER}-candidate, hello-2.10-1.fc{MAJOROSVER}.src.rpm): free -> open (buildvm-ppc64le-25.iad2.fedoraproject.org) - 92465698 rebuildSRPM (noarch): open (buildvm-s390x-24.s390.fedoraproject.org) - 92465745 buildArch (hello-2.10-1.fc{MAJOROSVER}.src.rpm, x86_64): free - 92465748 buildArch (hello-2.10-1.fc{MAJOROSVER}.src.rpm, s390x): open (buildvm-s390x-19.s390.fedoraproject.org) - 92465746 buildArch (hello-2.10-1.fc{MAJOROSVER}.src.rpm, aarch64): open (buildvm-a64-26.iad2.fedoraproject.org) - 92465747 buildArch (hello-2.10-1.fc{MAJOROSVER}.src.rpm, ppc64le): open (buildvm-ppc64le-11.iad2.fedoraproject.org) - 92465744 buildArch (hello-2.10-1.fc{MAJOROSVER}.src.rpm, i686): open (buildhw-x86-12.iad2.fedoraproject.org) - 92465698 rebuildSRPM (noarch): open (buildvm-s390x-24.s390.fedoraproject.org) -> closed - 1 free 5 open 1 done 0 failed - 92465745 buildArch (hello-2.10-1.fc{MAJOROSVER}.src.rpm, x86_64): free -> open (buildhw-x86-06.iad2.fedoraproject.org) - 92465745 buildArch (hello-2.10-1.fc{MAJOROSVER}.src.rpm, x86_64): open (buildhw-x86-06.iad2.fedoraproject.org) -> closed - 0 free 5 open 2 done 0 failed - 92465748 buildArch (hello-2.10-1.fc{MAJOROSVER}.src.rpm, s390x): open (buildvm-s390x-19.s390.fedoraproject.org) -> closed - 0 free 4 open 3 done 0 failed - 92465746 buildArch (hello-2.10-1.fc{MAJOROSVER}.src.rpm, aarch64): open (buildvm-a64-26.iad2.fedoraproject.org) -> closed - 0 free 3 open 4 done 0 failed - 92465744 buildArch (hello-2.10-1.fc{MAJOROSVER}.src.rpm, i686): open (buildhw-x86-12.iad2.fedoraproject.org) -> closed - 0 free 2 open 5 done 0 failed -92465688 build (f{MAJOROSVER}-candidate, hello-2.10-1.fc{MAJOROSVER}.src.rpm): open (buildvm-ppc64le-25.iad2.fedoraproject.org) -> closed - 0 free 1 open 6 done 0 failed - 92465747 buildArch (hello-2.10-1.fc{MAJOROSVER}.src.rpm, ppc64le): open (buildvm-ppc64le-11.iad2.fedoraproject.org) -> closed - 0 free 0 open 7 done 0 failed - -92465688 build (f{MAJOROSVER}-candidate, hello-2.10-1.fc{MAJOROSVER}.src.rpm) completed successfully ----- - -== References - -* https://rpm-software-management.github.io/rpm/manual/[RPM Reference Manual] - -* https://fedoraproject.org/wiki/Using_Mock_to_test_package_builds[Using Mock to test package builds] - -* xref:Using_the_Koji_Build_System.adoc[Using the Koji build system] - -* https://www.redhat.com/sysadmin/create-rpm-package[How to create a Linux RPM package]