First off, let me be very clear up-front: normally, I write my blog articles to be approachable by readers of varying levels of technical background (or none at all). This will not be one of those. This will be a deep dive into the very bowels of the sausage factory.
This blog post is a continuation of the Introduction to building modules in Fedora entry I wrote last month. It will assume a familiarity with all of the concepts discussed there.
Analyzing a more complicated module
Last time, we picked an extremely simple package to create. The talloc
module needed to contain only a single RPM, since all the dependencies necessary both at build-time and runtime were available from the existing base-runtime
, shared-userspace
and common-build-dependencies
packages.
This time, we will pick a slightly more complicated example that will require exploring some of the concepts around building with package dependencies. For this purpose, I am selecting the sscg
package (one of my own and discussed previously on this blog in the article “Self-Signed SSL/TLS Certificates: Why they are terrible and a better alternative“).
We will start by analyzing sscg
‘s dependencies. As you probably recall from the earlier post, we can do this with dnf repoquery
:
dnf repoquery --requires sscg.x86_64 --resolve
Which returns with:
glibc-0:2.25-6.fc26.i686 glibc-0:2.25-6.fc26.x86_64 libpath_utils-0:0.2.1-30.fc26.x86_64 libtalloc-0:2.1.9-1.fc26.x86_64 openssl-libs-1:1.1.0f-4.fc26.x86_64 popt-0:1.16-8.fc26.x86_64
and then also get the build-time dependencies with:
dnf repoquery --requires --enablerepo=fedora-source --enablerepo=updates-source sscg.src --resolve
Which returns with:/home/sgallagh/modulebuild/builds/module-talloc-master-20170526153440/results/module-build-macros-mock-stderr.log
gcc-0:7.1.1-3.fc26.i686 gcc-0:7.1.1-3.fc26.x86_64 libpath_utils-devel-0:0.2.1-30.fc26.i686 libpath_utils-devel-0:0.2.1-30.fc26.x86_64 libtalloc-devel-0:2.1.9-1.fc26.i686 libtalloc-devel-0:2.1.9-1.fc26.x86_64 openssl-devel-1:1.1.0f-4.fc26.i686 openssl-devel-1:1.1.0f-4.fc26.x86_64 popt-devel-0:1.16-8.fc26.i686 popt-devel-0:1.16-8.fc26.x86_64
So let’s start by narrowing down the set of dependencies we already have by comparing them to the three foundational modules. The base-runtime module provides gcc
, glibc
, openssl-libs
, openssl-devel
, popt
, and popt-devel
. The shared-userspace module provides libpath_utils
and libpath_utils-devel
as well, which leaves us with only libtalloc
as an unsatisfied dependency. Wow, what a convenient and totally unexpected outcome when I chose this package at random! Kidding aside, in most real-world situations this would be the point at which we would start recursively going through the leftover packages and seeing what their dependencies are. In this particular case, we know from the previous article that libtalloc
is self-contained, so we will only need to include sscg
and libtalloc
in the module.
As with the libtalloc
example, we need to now clone the dist-git repositories of both packages and determine the git hash that we intend to use for building the sscg
module. See the previous blog post for details on this.
Creating a module with internal dependencies
Now let’s set up our git repository for our new module:
mkdir sscg && cd sscg touch sscg.yaml git init git add sscg.yaml git commit -m "Initial setup of the module"
And then we’ll edit the sscg.yaml
the same way we did for the libtalloc
module:
document: modulemd version: 1 data: summary: Simple SSL certificate generator description: A utility to aid in the creation of more secure "self-signed" certificates. The certificates created by this tool are generated in a way so as to create a CA certificate that can be safely imported into a client machine to trust the service certificate without needing to set up a full PKI environment and without exposing the machine to a risk of false signatures from the service certificate. stream: '' version: 0 license: module: - GPLv3+ references: community: https://github.com/sgallagher/sscg documentation: https://github.com/sgallagher/sscg/blob/master/README.md tracker: https://github.com/sgallagher/sscg/issues dependencies: buildrequires: base-runtime: f26 shared-userspace: f26 common-build-dependencies: f26 perl: f26 requires: base-runtime: f26 shared-userspace: f26 api: rpms: - sscg profiles: default: - sscg components: rpms: libtalloc: rationale: Provides a hierarchical memory allocator with destructors. Dependency of sscg. ref: f284a27d9aad2c16ba357aaebfd127e4f47e3eff buildorder: 0 sscg: rationale: Purpose of this module. Provides certificate generation helpers. ref: d09681020cf3fd33caea33fef5a8139ec5515f7b buildorder: 1
There are several changes from the libtalloc example in this modulemd, so let’s go through them one at a time.
The first you may notice is the addition of perl
in the buildrequires:
dependencies. This is actually a workaround at the moment for a bug in the module-build-service where not all of the runtime requirements of the modules specified as buildrequires:
are properly installed into the buildroot. It’s unfortunate, but it should be fixed in the near future and I will try to remember to update this blog post when it happens.
You may also notice that the api
section only includes sscg
and not the packages from the libtalloc
component. This is intentional. For the purposes of this module, libtalloc
satisfies some dependencies for sscg
, but as the module owner I do not want to treat libtalloc as a feature of this module (and by extension, support its use for anything other than the portions of the library used by sscg
). It remains possible for consumers of the module to link against it and use it for their own purposes, but they are doing so without any guarantee that the interfaces will remain stable or even be present on the next release of the module.
Next on the list is the addition of the entirely-new profiles
section. Profiles are a way to indicate to the package manager (DNF) that some packages from this module should automatically be installed when the module is activated if a certain system profile is enabled. The ‘default’ profile will take effect if no other profile is explicitly set. So in this case, the expectation if a user did dnf module install sscg
would be to activate this module and install the sscg
package (along with its runtime dependencies) immediately.
Lastly, under the RPM components there is a new option, buildorder
. This is used to inform the MBS that some packages are dependent upon others in the module when building. In our case, we need libtalloc
to be built and added into the buildroot before we can build sscg
or else the build will fail and we will be sad. By adding buildorder
, we tell the MBS: it’s okay to build any of the packages with the same buildorder
value concurrently, but we should not attempt to build anything with a higher buildorder
value until all of those lower have completed. Once all packages in a buildorder
level are complete, the MBS will generate a private buildroot repository for the next buildorder to use which includes these packages. If the buildorder
value is left out of the modulemd file, it is treated as being buildorder: 0
.
At this point, you should be able to go ahead and commit this modulemd file to git and run mbs-build local
successfully. Enjoy!