From Fedora Project Wiki

Revision as of 20:49, 2 April 2020 by Sergiodj (talk | contribs) (Download tarball)

Introduction

This is a guide for the Fedora GDB package maintainer. The reason we have a specific document for the package (which builds on top of the existing official Fedora packaging documentation) is because we carry several local patches along with the project's official codebase.

Warning.png
This guide is not meant to cover everything related to general package maintenance. Its purpose is to cover specific scenarios that can happen when maintaining Fedora GDB. It is strongly recommended that you also read Package_maintenance_guide in order to obtain more information about packaging.

Getting ready

You will need to install some packages before we start.

dnf install fedpkg rpm-build

You will also need to configure Kerberos authentication in order to use fedpkg. See Infrastructure/Kerberos for details.

I personally like to use the following bash function when building the package. It guarantees that the full build will happen at the current directory, instead of ~/rpmbuild/ or something else.

# Function for building an RPM at $PWD.
function rpmbuildlocal
{
  MAKEFLAGS= rpmbuild \
    --define "_topdir $PWD" \
    --define "_builddir $PWD" \
    --define "_rpmdir $PWD" \
    --define "_sourcedir $PWD" \
    --define "_specdir $PWD" \
    --define "_srcrpmdir $PWD" \
    --define "_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm" \
    "$@"; rmdir &>/dev/null BUILDROOT;
}

Cloning the repository

The Fedora GDB repository is located at [1]. You can clone it by doing:

fedpkg clone gdb

After this, you will see a gdb directory, where you can use git switch to switch to a specific release branch. The master branch is always the Rawhide distribution; the other branches start with the letter f and a number, which correspond to the Fedora release.

If you are like me and prefers to have each branch in its own directory, you can do that using:

fedpkg clone --branches gdb

You should see several directories named like f28/, f29/, f30/, etc. If you choose this approach, you will have to manually clone every time Fedora branches. For example, supposing that Fedora branches f30, you will have to do:

fedpkg clone --branch f30 gdb && mv gdb f30

Downloading the sources

Fedora stores the source files (i.e., the tarballs) for the package in a separate cache. This means that when you clone the repository, you will not automatically obtain the tarballs necessary to build the package. In order to do that, you should execute:

fedpkg sources

The command should be executed inside the cloned directory. If you used the --branches option when cloning, then you should enter the directory related to the Fedora version you are working on.

Satisfying the build-dependencies

You can do:

rpmbuildlocal -bs --with testsuite gdb.spec
sudo dnf builddep gdb-*.src.rpm

Notice the --with testsuite option. This will generate a source RPM whose list of dependencies includes the packages needed to run GDB's testsuite.

Dealing with patches

Because we have several local patches, it is necessary to understand how to handle them in a way that doesn't cause too many conflicts.

To help with the job, Fedora GDB carries two shell scripts that automate the process of applying patches to and extracting patches from a tree.

Applying patches to a repository

You should use the script called generate-git-repo-from-patches.sh for this task. It requires one argument, REPOSITORY, which points to a cloned upstream GDB git repo. All it does is enter the directory, checkout a specific commit (the one pointed by the file _git_upstream_commit, itearate over the list of local patches and apply them sequentially.

If you already have a cloned upstream GDB repository, you can do:

git clone git://sourceware.org/git/binutils-gdb.git --reference=/path/to/local/gdb/repo new-fedora-release
./generate-git-repo-from-patches.sh binutils-gdb

I like calling the cloned directory new-fedora-release, but that's just a personal preference.

Extracting patches from a repository

You should use the script called generate-patches-from-git-repo.sh for this task. It takes two arguments:

  • REPOSITORY, the directory where you cloned the upstream GDB git repository (and where the local patches are applied). This argument is required.
  • COMMIT_OR_TAG_OR_BRANCH, which is the commit/tag/branch against which the rebase was performed. If no rebase was performed (e.g., if you just backported a patch a placed it on top of the others), you don't need to provide this argument.

Mandatory patch header

When extracting the patches, the script automatically generates the *.patch files, along with other two files: _gdb.spec.patch.include (which contains the %patch directives), and _gdb.spec.Patch.include (which contains the Patch: directives).

In order to generate the patches, the script must know how to name them. The script must also know if there should be any comment on top of the Patch: directive for each patch. The way we do that is by having two mandatory headers in the commit message:

  • The first line (subject) of the commit message must be the patch filename. The convention is to use gdb-rhbzNNNNNN-short-desc.patch.
  • The first line(s) of the commit body can be the comment that will be placed on top of the Patch: directive. It must start with two semicolons ;;.

An example of a proper commit message would be:

gdb-rhbz1553104-s390x-arch12-test.patch

;; [s390x] Backport arch12 instructions decoding (RH BZ 1553104).
;; =fedoratest

Preparing a new release

There are a few ways to prepare a new release, depending on what you want to do.

Case 1: Backport an upstream fix (no rebase)

Update origin and cherry-pick the patch

If you just want to backport an upstream fix, but don't want to rebase the code, then you would:

cd new-fedora-release
git fetch origin
git cherry-pick --no-commit 0a1b2c3d

It's a good idea to use --no-commit because it lets you revert the changes made to the ChangeLog files. They are not needed (because they are already listed in the commit message), and can easily cause conflicts in the future. You can do that by using the git checkout command, by the way.

Once everything is fine, you can commit the changes:

git commit

Remember to add the necessary headers (i.e., patch filename + comments) when editing the commit message.

Generate the backported patch and update gdb.spec

After that, you can generate the backported patch:

cd ..
./generate-patches-from-git-repo.sh new-fedora-release
Note.png
Notice how the second argument was omitted when invoking the script. We don't need it because we are not rebasing.

Run a git status if you would like to see which files were added/changed, and then edit the gdb.spec file. Since this does not involve a rebase, all you have to do is:

  • Bump the Release: number. If you are using Emacs, you can do a C-c C-r.
  • Write a %changelog entry. If you are using Emacs, you can get a template ready by doing C-c C-w. I mention which bug has been fixed by the backport, and who authored the patch. For example:
* Thu Feb 13 2020 Sergio Durigan Junior <sergiodj@redhat.com> - 9.1-3
- Fix 'Recursive call to 'missing_rpm_list_print' when pagination is
  on and missing RPM list is big' (RHBZ 1801974, Sergio Durigan
  Junior).

Case 2: Rebase Rawhide GDB

Update origin and start the rebase

The rebasing process is a bit more involved. It starts just like the previous case:

cd new-fedora-release
git fetch origin

But then you have to decided the upstream commit you will rebase against. In 99.9% of the cases, my approach was to pick the most recent commit by GDB Administrator (which is the bot that automatically updates the upstream version date every night). So just do a git log --author=gdbadmin and pick the first commit that shows up. For example, let's say the commit is 0a2b3c4d. You would then do:

git rebase 0a2b3c4d

This will start a rebase process, of course. Beware, due to the high number of local patches, you will most certainly see a few conflicts that will need to be solved by hand.

When I'm rebasing and there's a conflict, I find it useful to do a quick compilation of the tree in order to make sure that I solved everything correctly. Because we're dealing with Fedora GDB (and not upstream GDB), the compilation command differs a little bit. Here's what I use (assuming you're inside the new-fedora-release directory):

mkdir build-test && cd build-test
../configure \
  --disable-binutils \
  --disable-ld \
  --disable-gold \
  --disable-gas \
  --disable-sim \
  --disable-gprof \
  --with-system-readline \
  --with-separate-debug-dir=/usr/lib/debug \
  CFLAGS='-D_GLIBCXX_DEBUG -g3 -O0' \
  CXXFLAGS='-D_GLIBCXX_DEBUG -g3 -O0' \
  --enable-targets=s390-linux-gnu,powerpc-linux-gnu,arm-linux-gnu,aarch64-linux-gnu,amd64-linux-gnu
make -j10

Every time there's a conflict and I solve it, I just go inside build-test and do a make -j10 to check if the code is compiling correctly. If you want, you can also run some testcase and check for regressions. This is a good idea, but of course a more formal/correct way to do a regression testing is to run the full testsuite inside a Fedora Rawhide VM (more on that later).

Regenerate the patches and update gdb.spec

Once the rebase is done, you need to regenerate the patches that were affected by it. The way to do this is by invoking:

cd ..
./generate-patches-from-git-repo.sh new-fedora-release 0a2b3c4d
Note.png
Notice how we have to provide the second argument containing the commit against which the rebase happened.

Again, it's a good idea to perform a git status in order to check which files have been changed/deleted.

You will also need to update gdb.spec. The instructions are very similar to the ones that were given in case above:

  • Bump the Release: number. If you are using Emacs, you can do a C-c C-r.
  • Write a %changelog entry. If you are using Emacs, you can get a template ready by doing C-c C-w. If a patch has been automatically updated by the rebase process, I don't mention it in the changelog. However, if a patch has been dropped/upstreamed (yay!) or if I had to manually adjust it in order to make it usable again, I put a line saying what I did. This makes it easier later to follow the progress of the patch upstreaming effort.

Case 3: When there is a new upstream GDB release

TODO

Case 4: When Fedora is branched

TODO

Upload the new upstream GDB tarball (when rebasing)

Warning.png
You only need to do this step when you're rebasing Fedora GDB.

After the rebase is completed, it's time to upload the new upstream GDB tarball to the lookaside cache. If you've followed the steps above, you will remember that you chose to rebase Fedora GDB against one of the GDB Administrator commits. The reason I suggest you to do that is because that commit also triggers the generation of the official upstream GDB snapshot tarball, which can be uploaded as the base for the new Fedora GDB release.

The snapshots can be found at:

  • [2] for upstream's master branch.
  • [3] for branch snapshots (for example, gdb-9.1-branch).

After you've downloaded the corresponding tarball, you have to upload it to Fedora's lookaside cache:

fedpkg upload gdb-VERSION.tar.xz

After the upload, you will notice that two files will have been modified: sources and .gitignore. I prefer to edit these files and remove the entry for the old tarball, to keep them clean and concise.

Don't forget to git add these files if you edit them.

Testing Fedora GDB

It is really important to test every release to make sure no regressions are introduced. I personally like to maintain 3 VMs ready to test Fedora GDB:

  • fedora-rawhide
  • fedora-stable
  • fedora-oldstable

Before every test, you should run a dnf upgrade and reboot the VM to make sure it's running the latest software available in the distro. This is especially important for the rawhide VM, because of how fast changes are introduced there.

Prepare the VM for first use

Inside the VM, it isn't necessary to configure Kerberos authentication to clone the Fedora GDB repository. You can use fedpkg's -a option, which allows you to clone the repository anonymously:

fedpkg clone -a gdb

Since we're not going to do any development in the VM, you can clone without using --branches and just git switch to the desired branch.

You should also download the sources. This step is only necessary because you have to build an initial source RPM in order to be able to install all of the build dependencies necessary to build and test Fedora GDB.

cd gdb
fedpkg sources

Then, generate a source RPM:

rpmbuildlocal -bs --with testsuite gdb.spec

And install the build deps:

dnf builddep gdb-*.src.rpm

This should be enough to build and test GDB.

Testing a new release

TODO

Committing & pushing the changes

If everything went well, you should now commit and push your changes to the Fedora GDB repository. Make sure you add all of the necessary files before committing. For example, gdb.spec will need to be added by hand.

The convention is to use the %changelog entry as the commit message, and there is a handy fedpkg that can extract it for you:

fedpkg clog

This will generate a file named clog, which you can use to make the commit:

git commit -F clog

After that, you can push:

git push

Building the new release

If the push went well, you can now build an official release. To do that, simply:

fedpkg build

You should see the progress of the command as the builds are completed. You can safely interrupt the program if you want; the builds will keep running on Koji.

Prepare an update (for released Fedoras)

If you're building a new Fedora GDB for a Fedora distribution that has already been released, then you will also need to create an update request to make sure that the new release will be shipped to users.

Warning.png
This process is not necessary if you are preparing a new release for Rawhide or for an unreleased (but branched) Fedora.

To do that, you should issue the following command:

fedpkg update