Upgrading QGo to QT5

My Day job has me messing around with QT5. We’rer building various RPMs for different RHEL and CentOS versions, and I wanted to get a little more experience on this. Specifically, I wanted to be able to do trial and error on a package that would not pollute our work stream. I wanted it to be something QT based. And I wanted it to be fun.

So I am working on repackaging QGo for Fedora 34 using QT5. Here’s what I am learning.

There are a number of stages to this process.

  • Work out the compilation issues on my own Fedora 34 machine
  • Upgrade the RPM Spec file to build
  • Work out the Build Dependencies
  • Work out the Run time dependencies.
  • Build the package in a COPR using Fedora build servers
  • And, should I decide to support this, submit the updated package to Koji and propose for Fedora.

We’ll see about this last one later.


clone the code from upstream

git clone https://github.com/pzorin/qgo

Since I’m doing so much stuff with QT, I have most of the QT development packages installed. Thus, building happens to be fairly trivial. Make a place for generated code, run qmake, make.

cd qgo
mkdir fedora
cd fedora
qmake-qt5 ../src/

Now, due to the way the project file is set up, this actually builds in qgo/build

$ ls ../build/
moc  objects  qgo  rcc  ui

the file qgo above is the binary. and I can run it to make sure things work.

Source Archive

I was able to find an old Source RPM (srpm) file hosted on rpmsphere. I was able to download it from here.

If you do an rpm -i of the downloaded file, it iwll install it in your $HOME/rpmbuild tree. I think it will even build this tree for you, although I already had one, so maybe not.

What is in this tree? When you first start out, you will have 2 subdirectories; SPECS and SOURCES. the SPEC file is the build instructions for the RPM build tool, and it is where we’ll spend most of our time. However, the process will actually start in the SOURCES directory. That has a file names qt4-final.tar.gz. We call a tar.gz file a tarball. The file name refers to the git tag in the upstream repository. It is not the greatest of names, as it does not tell you what the source project is. A better option would be qgo-2.0.0.tar.gz. This naming scheme tells what project, and what version of the project it contains.

I need to generate an updated version of the code base. Not a lot has happened in the QGo git repo, but there have been some changes. If I clone the upstream repository, I can generate an updated tarball. This is necessary, as there has not been a released tarball for quite some time.

git archive --format=tar.gz --prefix=qgo-2.0.1/ HEAD > ~/rpmbuild/SOURCES/qgo-2.0.1.tar.gz

I’ve decided that this is going to be 2.0.1. The code is only slightly ahead of the the last release. This is the smallest jump in versioning I can make. The QT5 code does not seem to require any code changes.

The prefix contains a slash at the end. This is non-obvious, but it means that the prefix is a a directory, not just an extension to the file name. So, if this were to get extracted by rpmbuild, it will go into the directory $HOME/rpmbuild/.BUILD/qgo-2.0.1

SPEC file

Once we have an updated tarball, we need to update the SPEC file. This is what it looks like at the start (minus the changelog, which we will see at the end)

Name:           qgo
Version:        2.0.0
#Version:        2.1.0
Release:        1
Summary:        A Go Board and SGF Editor
License:        GPL-2.0+
Group:          Amusements/Games/Board/Other
URL:            https://github.com/pzorin/qgo
Source:         https://github.com/pzorin/qgo/archive/qt4-final.tar.gz
#PATCH-FIX-UPSTREAM fix gcc6 narrowing conversion from int to char inside {}
Patch:          qgo-2.0.0-gcc6.patch
BuildRequires:  qt4-devel
BuildRequires:  alsa-lib-devel
A Go board, sgf editor and client for IGS/NNGS/WINGS based on the Qt
library. Go is an ancient boardgame, very common in Japan, China and
%setup -q -n %{name}-qt4-final
%patch -p1
sed -i 's|$(QTDIR)|%{_libdir}/qt4|' src/src.pro
qmake-qt4 -makefile %{name}.pro QMAKE_CFLAGS="%{optflags} -Wno-format-security" QMAKE_CXXFLAGS="%{optflags} -Wno-format-security"
make %{?_smp_mflags}
make install INSTALL_ROOT=%{buildroot}
cp src/translations/*.qm %{buildroot}%{_datadir}/qgo/languages/

The first step is to update the Version.

< Version:        2.0.0
> Version:        2.0.1

I’m going to modify the sources in two ways. First am going to change the tarball to the one I just generated. I use the rpm variables for name and version, so that I do not have to change this line in the future when the version changes, or if we tweak the name of the package. Second, I drop the gcc patch, as it no longer applies.

< Source:         https://github.com/pzorin/qgo/archive/qt4-final.tar.gz
< #PATCH-FIX-UPSTREAM fix gcc6 narrowing conversion from int to char inside {}
< Patch:          qgo-2.0.0-gcc6.patch
> Source:         https://github.com/pzorin/qgo/archive/%{name}-%{version}.tar.gz

This is actually enough of a change that I want to test what happens. To start, I build using rpmbuild. This is the shortest round trip. However, it does not deal with package dependencies. I’ll come back to that in a bit.

The compilation process takes time. Ideally, when coding I like to make a small change, rerun the process, see what breaks, fix it, and continue. With rpmbuild and native code, that can be frustrating, as it has to get through the whole compile stage, from scratch, only to fail when packaging files.

Here are the additional changes I had to make to the spec file. First, the Build Requires:

< BuildRequires: qt4-devel < BuildRequires: alsa-lib-devel --- > BuildRequires: qt5-qtbase-devel > BuildRequires: qt5-qtmultimedia-devel > BuildRequires: qt5-linguist > Requires: qt5-qtmultimedia

I am not 100% certain I need the multimedia package at run time, but it seems a safe bet; if I need the devel to build, I am going to need the libraries to run. There might be others, but I won’t know until I test it out.

To compile with debug info, I followed advice from a few places that say to replace custom build commands with the rpm macros.

< %setup -q -n %{name}-qt4-final
< %patch -p1
< sed -i 's|$(QTDIR)|%{_libdir}/qt4|' src/src.pro
> %setup -q -n %{name}-%{version}
> sed -i 's|$(QTDIR)|%{_libdir}/qt5|' src/src.pro
< qmake-qt4 -makefile %{name}.pro QMAKE_CFLAGS="%{optflags} -Wno-format-security" QMAKE_CXXFLAGS="%{optflags} -Wno-format-security"
> %{qmake_qt5}  src/src.pro

This block removes the patching and modifications specific to Qt4. It then upgrades the qmake call to the qt5 version, using the macro.

There are couple minor differences in the files produced. I tried to keep parity with previous files. This might be neither necessary nor sufficient, but it is a start:

> mkdir %{buildroot}%{_datadir}/qgo/languages/
< %{_datadir}/mime/text/x-sgf.xml
< %{_datadir}/mimelnk/text/sgf.desktop

The “final” SPEC file is at the end of the article. I’ve included the changelog:

Building with mock

I want to make sure things progress, with each change of the SPEC file. Once rpmbuild -ba succeeds, I am only partially convinced I have a functional SPEC file; I need to check the build is reproducible, and that I have the right build dependencies. For that I use mock. To start, generate a new mock root:

mock -r fedora-34-x86_64 --init

Now, generate an update SRPM and rebuild:

rpmbuild -bs SPECS/qgo.spec
mock -r fedora-34-x86_64 --rebuild ~/rpmbuild/SRPMS/qgo-2.0.1-1.src.rpm

Once I have the BuildRequires at a sufficient level, the build should succeed.

COPR build

I’ve gone through the process to initialize my own copr. To kick off a build I can use the copr-cli

copr-cli build qgo SRPMS/qgo-2.0.1-1.src.rpm

This takes some time to complete.

Uploading package SRPMS/qgo-2.0.1-1.src.rpm
 |################################| 2.8 MB 830.4 kB/s eta 0:00:00Build was added to qgo:
Created builds: 2201850
Watching build(s): (this may be safely interrupted)
  12:32:01 Build 2201850: pending
  12:32:31 Build 2201850: importing
  12:33:01 Build 2201850: running
  12:39:03 Build 2201850: succeeded

Runtime Dependencies

At some point, you need to test the application runs. While I can do that on my desktop, it does not confirm that the RPM correctly reports the other packages that it requires. There are a couple ways to test it out. One way is to fire up a VM, install the new RPM, and see if it runs.

I’ll use the Fedora Cloud Image.

Start the VM:

sudo virt-install --name qt --memory 2000 --noreboot --os-variant detect=on,name=fedora-unknown --cloud-init user-data="/home/ayoung/devel/cloud/cloudinit-user-data.yaml" --disk=size=10,backing_store=/home/ayoung/Downloads/Fedora-Cloud-Base-34-1.2.x86_64.qcow2 --network=network:network

Log in and install the graphical desktop yum group. There are a few options here, but I’m going with the most likely desktop setup.

sudo yum groupinstall "Fedora Workstation"

This installs quite a few packages (1283 today) but this is a one time cost. Once the VM is created, I will snapshot it so I can reset from a known base state. First, though, lets get it to a graphical boot. Execute the two lines after the $s. Note that I am running from a terminal on my desktop, not via the virt-manger console.

$ sudo systemctl set-default graphical.target
Created symlink /etc/systemd/system/default.target → /usr/lib/systemd/system/graphical.target.
$ sudo systemctl start graphical.target

If I now open up the console, I see the Fedora login screen. Go through any initialization orientation for new users.

Shut down the vm and snapshot it.

Was stopping it necessary? Not sure. But it does not hurt. Now fire it back up.

From a terminal, get the IP address of the running VM:

$ sudo virsh domifaddr qt
[sudo] password for ayoung: 
 Name       MAC address          Protocol     Address
 vnet8      52:54:00:0a:08:62    ipv4

Copy the newly built binary RPM up to the server:

scp /var/lib/mock/fedora-34-x86_64/result/qgo-2.0.1-1.x86_64.rpm fedora@

And install:

ssh fedora@
sudo dnf install ./qgo-2.0.1-1.x86_64.rpm

Now, using the Graphical console, fire it up. It runs. I have an SGF file, which is a text representation of a game. The contents is at the end of the article. I’ve also copied it over to the file, so I can try running the graphical portion.

I notice an error “… trying to run program” even though the UI loads. I am fairly certain that is the Gnu G program, which would be the computer opponent in an automated game. But installing that does not make the message go away.

Running qgo from a terminal gives me more logging. I see the message:

Warning: “No decoder available for type ‘audio/mpeg, mpegversion=(int)1, mpegaudioversion=(int)3, layer=(int)3, rate=(int)11025, channels=(int)1, parsed=(boolean)true’.”

This appears to be an issue with the sound production. The click that happens when you place a stone. I’ll look deeper in to this. But I think I am going to call this victory.

The packages I build are in the Cool Other Packages Repo here.

Completed Spec File

Name:           qgo
Version:        2.0.1
Release:        1
Summary:        A Go Board and SGF Editor
License:        GPL-2.0+
Group:          Amusements/Games/Board/Other
URL:            https://github.com/pzorin/qgo
Source:         https://github.com/pzorin/qgo/archive/%{name}-%{version}.tar.gz
BuildRequires:  qt5-qtbase-devel
BuildRequires:  qt5-qtmultimedia-devel
BuildRequires:  qt5-linguist
Requires: qt5-qtmultimedia
A Go board, sgf editor and client for IGS/NNGS/WINGS based on the Qt
library. Go is an ancient boardgame, very common in Japan, China and
%setup -q -n %{name}-%{version}
sed -i 's|$(QTDIR)|%{_libdir}/qt5|' src/src.pro
%{qmake_qt5}  src/src.pro
make %{?_smp_mflags}
make install INSTALL_ROOT=%{buildroot}
mkdir %{buildroot}%{_datadir}/qgo/languages/
cp src/translations/*.qm %{buildroot}%{_datadir}/qgo/languages/
* Wed May 19 2021 Adam Young <ayoung@redhat.com> -2.0.1
- Update to QT5
* Wed Jul 18 2018 Wei-Lun Chao <bluebat@member.fsf.org> - 2.0.0
- Rebuilt for Fedora
* Tue Jun 21 2016 i@marguerite.su
- add patch: qgo-2.0.0-gcc6.patch
  * fix boo#985098
  * fix gcc6 narrowing conversion from int to char inside {}
  * fix gcc6 cannot convert bool to GameData in return
* Sat Mar 14 2015 p.drouand@gmail.com
- Update to version 2.0.0
  * No changelog available
- Remove obsolete patchs
  * qgo-1.5.4-gcc4.3.diff
  * qgo-1.5.4-desktop.diff
- Move to qt4; follow upstream changes
  * Replace qt3-devel require with pkgconfig(QtCore)
  * Remove qt3 require
- Update project Url
- Use download Url as source
- TODO and COPYING don't exit anymore; do not perform %%doc on them
- README has been renamed to README.md
- Copy AUTHORS and COPYING into package doc directory
* Tue Mar 27 2012 jengelh@medozas.de
- Build in parallel with %%_smp_mflags
- Strip redundant sections/tags from specfile
* Fri Mar  5 2010 coolo@novell.com
- fix build with gcc 4.5
* Tue Mar 10 2009 anicka@suse.cz
- install correct desktop file (bnc#483231)
* Fri Nov 16 2007 anicka@suse.cz
- fix deprecated headers
* Mon Jun 18 2007 ltinkl@suse.cz
- update to 1.5.4:
  * fixed : mark issue with teaching games
  * added : blind go
  * added : 2 new translations (latin and simplified chinese)
  * changed : added 'SGF' (uppercase) as file suffix
* Tue Jan 16 2007 meissner@suse.de
* Thu Jan 11 2007 ltinkl@suse.cz
- update to 1.5.3
  * fixed : 9x9 grid display
  * changed : 'remember last dir' set by default
  * changed : made ugly 2D stones available
  * added : IGS 'nmatch' range now in the preferences
* Mon Oct  9 2006 ltinkl@suse.cz
- update to 1.5.2
* Sat Sep  9 2006 anicka@suse.de
- use proper lib (/usr/lib/qt3/lib64 on biarch)
* Wed Aug 30 2006 ltinkl@suse.cz
- initial release (1.5.1)

SGF File for test

PC[Dragon Go Server: https://www.dragongoserver.net/]
PB[Adam Young (admiyo)]
PW[Ken Lind (degnar)]
GC[Game ID: 1363491
Game Type: GO (1:1)
Rated: Y
White Start Rating: 12k (+32%) - Elo rating 932
Black Start Rating: 12k (-24%) - Elo rating 875]
OT[30 days with 1 day extra per move]

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.