forked from quentin/quentin.dufour.io
201 lines
5.9 KiB
Markdown
201 lines
5.9 KiB
Markdown
---
|
||
layout: post
|
||
slug: build-a-rpm-package-and-publish-it-on-copr
|
||
status: published
|
||
sitemap: true
|
||
title: Build a RPM package and publish it on Copr
|
||
description: They said it was easy
|
||
categories:
|
||
- linux
|
||
tags:
|
||
- fedora
|
||
- copr
|
||
- rpm
|
||
---
|
||
|
||
*Disclaimer: I'm not an expert in linux packaging, some part could be considered as bad practises. Moreover, there are billions different ways of building packages. I am only proposing one in this article.*
|
||
|
||
### Setup
|
||
|
||
First of all, we will need some tools:
|
||
|
||
```bash
|
||
sudo dnf install git rpmdevtools rpm-build
|
||
```
|
||
|
||
RPM is a bit special, as it needs its own folder and can't build elsewhere. It's a bit annoying when you manage your packages in different repositories. We will see one way to get around this problem.
|
||
|
||
First, create a git repository for your RPMs:
|
||
|
||
```bash
|
||
mkdir my-rpms && cd my-rpms
|
||
git init
|
||
```
|
||
|
||
We will create one folder for each RPM and initialize with the essence of a RPM: a spec file. For now, let's start with only one, `chez-scheme` which is a real example:
|
||
|
||
```bash
|
||
mkdir chez-scheme && cd chez-scheme
|
||
rpmdev-newspec --macros chez-scheme.spec
|
||
```
|
||
|
||
You should have generated the following file:
|
||
|
||
```conf
|
||
Name: chez-scheme
|
||
Version:
|
||
Release: 1%{?dist}
|
||
Summary:
|
||
|
||
License:
|
||
URL:
|
||
Source0:
|
||
|
||
BuildRequires:
|
||
Requires:
|
||
|
||
%description
|
||
|
||
|
||
%prep
|
||
%autosetup
|
||
|
||
%build
|
||
%configure
|
||
%make_build
|
||
|
||
|
||
%install
|
||
rm -rf %{buildroot}
|
||
%make_install
|
||
|
||
|
||
%files
|
||
%license add-license-file-here
|
||
%doc add-docs-here
|
||
|
||
%changelog
|
||
* Sun May 20 2018 Quentin Dufour <quentin@dufour.io>
|
||
-
|
||
```
|
||
|
||
So, now we must fill this file. You can use the Fedora Packaging Guidelines guide to find help for the different macro (lines starting with a percent). You can also take some inspiration from existing `.spec` files like [meshlab.spec](https://src.fedoraproject.org/rpms/meshlab/blob/master/f/meshlab.spec) or [chez-scheme.spec](https://github.com/superboum/rpm/blob/master/chez-scheme/chez-scheme.spec).
|
||
|
||
### Sources and patches
|
||
|
||
We will consider the case where a source tarball is provided, but you need to patch it.
|
||
You can easily retrieve a tarball from any github or gitlab project, for a given release, like:
|
||
|
||
```
|
||
Source0: https://github.com/cisco/ChezScheme/archive/v%{version}.tar.gz
|
||
```
|
||
|
||
By templating the link, it will be easier to upgrade the package.
|
||
|
||
To create the patches, you have different options. You can either clone the repository, do the modification in a specific branch or commit, then generate a patch:
|
||
|
||
```bash
|
||
git checkout -b v9.5-patches
|
||
git commit -m "A first patch"
|
||
git commit -m "A second patch"
|
||
git format-patch v9.5
|
||
```
|
||
|
||
|
||
Another way is to download and extract the tarball, create a copy and use diff:
|
||
|
||
```bash
|
||
tar xf v9.5.tar.gz
|
||
cp -r v9.5 v9.5-src
|
||
# modify v9.5
|
||
diff -Naur v9.5-src v9.5 > some-modification.patch
|
||
```
|
||
|
||
We will use `patch -p0` for git patches as they don't include the main folder and `patch -p1` for diff patches as they include the main folder.
|
||
|
||
We will put these patches in our git repository, next to our `.spec` file:
|
||
|
||
```
|
||
rpm
|
||
└── chez-scheme
|
||
├── chez-scheme.spec
|
||
├── chez-scheme-symlink.patch
|
||
└── chez-scheme-xlocale.patch
|
||
|
||
```
|
||
|
||
Now, if we want to build, we will have to type the following commands:
|
||
|
||
```bash
|
||
spectool -g -R ./chez-scheme.spec # Download sources
|
||
cp *.patch ~/rpmbuild/SOURCES # Copy patches
|
||
rpmbuild -ba ./chez-scheme.spec # Build RPM
|
||
```
|
||
|
||
There are some tools like rpkg, fedpkg or tito that should do most of the steps for you.
|
||
Unfortunately, they are not very flexible. rpkg and fedpkg never download the source directly, but from a mirror, and fails with a 404. If I want to push my source to this mirror, it fails with an unauthorized error. These packages seem to be aimed at distribution maintainers. tito, for its part, doesn't handle correctly patches and sources. It consider that everything should be embedded in a single git repository.
|
||
|
||
So, we will need an home made solution.
|
||
|
||
### make srpm
|
||
|
||
Fortunately, copr propose different solutions. One is to build your `.srpm` locally and send it to copr, but we can even avoid this step and only give a git repository to copr. We will build our own builder with a Makefile, which is supported by Copr!
|
||
|
||
Copr will call a Makefile located in `<git_root>/.copr` from the folder of our package (`<git_root>/chez-scheme`) and call:
|
||
|
||
```bash
|
||
make -f <git_root>/.copr/Makefile srpm outdir="<outdir>" spec="<spec_path>"
|
||
```
|
||
|
||
Your folder structure should now look like this:
|
||
|
||
```
|
||
rpm
|
||
├── chez-scheme
|
||
│ ├── chez-scheme.spec
|
||
│ ├── chez-scheme-symlink.patch
|
||
│ └── chez-scheme-xlocale.patch
|
||
└─── .copr
|
||
└── Makefile
|
||
|
||
```
|
||
|
||
Copr proposes a simple Makefile in its documentation. I'm proposing a bit more complex one that use only `rpmbuild`:
|
||
|
||
```makefile
|
||
rpmbuild_src = $(shell rpmbuild --eval '%{_sourcedir}')
|
||
.PHONY: prepare srpm rpm
|
||
|
||
prepare:
|
||
dnf -y install rpmdevtools rpm-build
|
||
cp *.patch $(rpmbuild_src)
|
||
spectool -g -R $(spec)
|
||
|
||
srpm: prepare
|
||
rpmbuild -bs --define "_srcrpmdir $(outdir)" $(spec)
|
||
|
||
rpm: prepare
|
||
rpmbuild -bb --define "_rpmdir $(outdir)" $(spec)
|
||
```
|
||
|
||
The `rpm` target will not be used by Copr but it can be convenient to locally test your package build before sending it to Copr.
|
||
|
||
### Use Copr
|
||
|
||
Now you just need to commit + push your repository and use the [Copr web interface](http://copr.fedorainfracloud.org/) to create a new project, add a package and trigger a build !
|
||
|
||
After that, your users can just enable the copr repository on their system and install your package:
|
||
|
||
```
|
||
sudo dnf copr enable superboum/chez-scheme
|
||
sudo dnf install chez-scheme
|
||
```
|
||
|
||
You can configure some webhooks to rebuild your packages for each git commit.
|
||
And that's all!
|
||
|
||
### Sources
|
||
|
||
* [Fedora Packaging Guidelines](https://fedoraproject.org/wiki/Packaging:Guidelines)
|
||
* [Spectool](https://pagure.io/spectool)
|
||
* [Copr documentation](https://docs.pagure.org/copr.copr/user_documentation.html)
|