Audacity on CentOS 7.5

Screen shot of Audacity 2.2.2

For those of you who are not aware, Audacity is one of the most successful end user Free Libre Open Source Software projects out there. It’s not just free in that you do not have to pay for it, it is free in the true sense – freedom. You can have access to the source code, modify it if you need to, and distribute the modified version as long as you also distribute the source to your version, all without needing to pay royalties. Donations are always very appreciated when you can afford it, but are not a condition of using the software, modifying the software, and redistribution your modified version. With Free Libre Open Source Software, you do not have to be wealthy to stand upon the shoulders of others, social class is all but taken out of the equation.

Audacity is an audio editor, and a damn good one that runs on just about every desktop operating system out there.

Part of why it runs on just about every operating system, for the Graphical Interface it uses something called wxWidgets that make it easy (or at least less painful) to port the software to other operating systems and it still will have the look and feel of a native application on that operating system. In a nutshell, you write the code using wxWidgets and then it is compiled against a wxWidgets library that is built against the native GUI toolkits for the operating system.

On Linux, there are many different GUI toolkits but GTK – the “GIMP ToolKit” – a graphical toolkit originally developed for the GNU Image Manipulation Project (a bitmap image editor). So on Linux, Audacity builds against wxGTK. It might actually build against wxGTK on other platforms too, GTK itself is available just about anywhere.

Anyway, I am not an audio professional (though I did sleep at a Holiday Inn Express last night) by sometimes I do edit audio as a hobby, and I love Audacity.

I use the CentOS 7 distribution as my desktop. It’s a very stable Enterprise Linux distribution, and I run it on my servers (this blog runs on CentOS 7) so running it as my desktop OS lets me run the same exact server software on my desktop for development purposes.

Awhile back, Audacity stopped working so well. It became very unstable, with the GUI buttons often just vanishing from view. It was kind of an embarrassing thorn in my side because I run media.librelamp.com which is a software repository for modern multimedia application on CentOS 7. I compiled it, and it was broken, and I wasn’t sure how to fix it.

The advantage of CentOS 7 is the software is very stable. The disadvantage is that it is not very modern. The multimedia stack is something that should be modern. I ran that website to let people have the best of both worlds – a stable operating system with a modern multimedia stack, but my packaging of Audacity didn’t works.

Audacity and wxWidgets

It turns out the problem was actually wxGTK. That library is not part of CentOS itself, it is provided for CentOS 7 by EPEL, which is part of the Fedora Project.

Unlike CentOS, libraries and applications within CentOS are updated more frequently and wxGTK was one of those that was updated, causing the Audacity breakage. Audacity prior to 2.1.2 does not properly work with wxWidgets 3 and wxGTK in EPEL was updated, and I rebuilt Audacity against the updates. It was either rebuild Audacity against the updates or maintain older wxGTK myself, but I only like old software when an Enterprise distribution maintains it. Since wxGTK is not part of CentOS 7, the newer version is what I had to work with.

So update Audacity to a version that works with wxWidgets 3.

Well, that wasn’t quite so easy.

The C++11 Standard

CentOS 7 being an enterprise distribution, it’s version of GCC (The GNU Compiler Collection) was not the latest even when CentOS 7 was brand spanking new. CentOS 7 is not brand spanking new.

The version of GCC it comes with is GCC 4.8.5 which while it does implement much of the C++11 standard, it does not do it as well as modern C++ compilers do. Newer versions of Audacity required GCC 4.9 as a minimum version.

You can install more modern compilers on CentOS 7 using the Software Collections (SCLs) but I do not like to use those, I have not found them to be easy to use with the mock build system and because my Internet connection is very slow, each repository I add really bloats how much I have to mirror to have a mock build system that is fast. I only like to mirror CentOS 7 itself and EPEL and the small repositories I maintain.

So I decided I needed to create my own packaging of a newer GCC that I could use to build C++ software that uses the C++11 standard.

Audacity isn’t the only one, current version of VLC Media Player (another highly successful end user Free Libre Open Source Software project) also uses C++11 and does not compile with GCC 4.8.5.

GCC 5.5.0

While I could have gone with GCC 6 or 7, I chose 5.5.0 because it is the latest release in the GCC 5 Release Series. What I needed was C++11 support and the GCC 5 series does that quite well and is very mature. I am not a C++ developer, I do not need the more bleeding edge standards (like C++14 and even newer), I needed C++11 so I chose the 5 series because it meets that need and at this point has most of the bugs worked out. Stability is always preferable to bleeding edge to me.

To get my goal of having a newer GCC for a mock build system, I need to packages GCC 5.5.0 as RPMs that would install in a CentOS 7 environment. My intent was NOT to create GCC 5.5.0 RPMs for developer use, but for a build system.

So I grabbed the source from http://www.netgull.com/gcc/releases/ (one of many mirrors) and started working on an RPM package for it.

Initially my intent was to have it install within /usr in parallel with the GCC 4.9.5 that is part of CentOS 7, so with the configure switches, I set a prefix of awel- so that the binaries would not conflict. I would use the environmental variables CC=awel-gcc and CXX=awel-c++ when I wanted to use GCC 5.5.0 instead of 4.9.5.

That turned out to not be a mistake, though not a fatal one. Due to a need for a compatibility libstdc++ package for end users to install, I ended up using a prefix with /opt instead – specifically, /opt/gnu as the install prefix.

Using /opt/gnu was also a mistake, but only a cosmetic one. I should have used /opt/gcc55.

The reason, due to incompatibilities I’ll discuss later, some libraries that end users need to have to run software I build with GCC 5.5.0 need to be installed within that prefix, and /opt/gnu can give the false impression it is GNU software when it is not. /opt/gcc55 would have been better, as it would make it clear that it was software compiled with GCC 5.5.0.

It would take a lot of time to redo things so since I am not being paid for this and the mistakes are just cosmetic, I am leaving them for now. If I ever need a version of GCC beyond the 5.5.x series, I’ll do it without setting a prefix to the binaries and with a prefix named after the version of GCC.

I do not need to create 32-bit binaries so when I compiled GCC 5.5.0 I did so without multilib support, and I only need C and C++ but I did also compiled Objective C and Objective C++ support just so I don’t need to redo it if I do need them. Other languages that can be built like Fortran, ADA, and Go – I didn’t bother. Those four languages were enough, and GCC takes a long time to compile because it has to first use the system compiler (GCC 4.9.5 in my case) to compile a stripped down version of 5.5.0 that it then uses to compile itself. Multilib and additional languages just really adds to the time involved.

Getting the needed configure a working GCC 5.5.0 was the easy part, getting it packages in RPM appropriately to use it in the mock build system, that took me several days. There are still improvements I can make to the packaging.

Build System Tools

GCC is just the compiler collection. To actually build software with it, helper tools are needed. Had I been able to use a prefix of /usr as I had originally hoped, I could just use the helper tools that are part of CentOS 7. However the helper tools really need to be built with the same prefix as the compiler, so I needed some base tools with /opt/gnu as the prefix.

GNU Auto Tools

These are the core auto-tools needed to build software on a UNIX-like operating system:

  • M4 – A Macro processor
  • libtool – A tool for dealing with linking libraries
  • autoconf – A tool for generating configure scripts
  • automake – A tool for generating make files

Once I had GCC built, I could build those in the mock build system with the GCC RPMs and that is what I did. I went with the latest for each except for libtool. The issue with libtool, I could build the latest (2.4.6) but make check produced many failures. I suspect most if not all of the failures were due to missing dependencies in the test scripts, likely Perl modules, and could be corrected just by specifying them to be installed in the build system when building libtool. However, 2.4.2 passed all the tests so for now I just went with that.

The perl-Scaler-List-Utils package in CentOS 7 was too old to build the latest Automake, but just barely too old, so I built a newer version of that Perl modules (using the CentOS GCC 4.8.5 as the rest of binary Perl in CentOS 7 is built with it) just for the build system so that I could build the latest Automake. That Perl module is the only part of the GCC 5.5.0 repository that was not built with GCC 5.5.0. Things like updated Perl modules I need are more of an update to the CentOS 7 base than part of the GCC 5.5.0 tool chain.

Additional Tools

This list may grow, though likely not much, and I only will build with GCC 5.5.0 what I absolutely need to.

In addition to the Autotools, I needed GNU GetText. Using GetText from the CentOS 7 base would be good enough, however Gettext installs a lot of macro files into ${prefix}/share/autoconf so building GetText with an install prefix of /opt/gnu means autoconf can find them without needing to be specifically told where they are.

I also needed the test suite CppUnit test framework built with GCC 5.5.0 to run unit tests on C++ code built with the C++ compiler from GCC 5.5.0.

End Results

Here are the source RPMs for what is currently in my GCC 5.5.0 build toolchain: http://awel.domblogger.net/7/gcc/src/repoview/

The Perl src.rpm is just the CentOS src.rpm with the version slightly bumped. The CppUnit src.rpm is from Fedora but modified to have /opt/gnu as the install prefix and to compile using GCC 5.5.0.

The other source RPMs I wrote myself, though I consulted a Fedora GCC spec file for the GCC 5.5.0 src.rpm (though I did many things differently) and I consulted CentOS RPMs for description for the others.

These are not intended to create RPMs to install on an end user system, they are just for my mock build system. So with the exception of CppUnit where there were already sub-packages and GCC where I made subpackages, subpackages were not created.

The binary RPMs: http://awel.domblogger.net/7/gcc/gcc55/repoview/

Those in the letter group A that have a prefix of awel-gcc55- in the package name are build system only. The two in the letter group C with a prefix a compat- are for users to install who want to use applications I compile with GCC 5.5.0 (right now just Audacity). And again, the Perl module in the letter group P is just a custom update to the CentOS 7.5 base these packages are used with, so that I could build the latest Automake.

The Fun – Building Audacity

So now that I have a repository with GCC 5.5.0 I should just be able to build the latest Audacity with it, right?

Wrong. It took a lot more work than that.

The mock build environment I use for building CentOS 7 media applications uses CentOS 7 base, CentOS 7 updates, EPEL, and my media.librelamp.com repository.

C++11 Incompatibilies

Audacity uses the C++11 standard, which is not a new standard – it’s just that CentOS 7 has an old compiler. Audacity also has a lot of build dependencies.

GCC 4.9.5 was able to compile some C++11 code but it did so in a not-compatible was with GCC 5.5.0.

This first became evident with the Vamp Plugin SDK. This dependency is provided by EPEL and is a new enough version. But it gave really strange C++11 build errors.

Vamp Plugin SDK

When googling these errors, it seems similar errors happen a lot with people with people trying to build Audacity with Xcode on MacOS and I bet the reason behind it is similar.

The reason behind it I finally found on a Debian mailing list: Debian bug 791307.

GCC 4.x Series has some C++11 support but uses a different ABI for it than GCC 5.x Series. Since EPEL uses GCC 4.8.5, that’s what they built their Vamp Plugin SDK with. Since that SDK uses C++11 it uses the older ABI resulting in the GCC 5.x freaking out when compiling software that links against it.

In that case, what I did was take a source RPM from Fedora, updated the version to latest, and built it in my GCC 5.5.0 build environment producing packages that work for compiling Audacity.

Since I built the GCC 5.5.0 version of the Vamp Plugin SDK to replace the EPEL build, that means it will likely break any EPEL software that uses it for the same incompatible ABI reason. I honestly can not tell you what in EPEL uses it, I just do not know.

If you use my media repository and the rebuilt Vamp Plugin SDK package breaks something, let me know and I’ll see what I can do. But note that for free, while I will try, it can’t be high priority for me to do quickly. The solution will likely be rebuilding what broke with GCC 5.5.0.

My Vamp Plugin source RPM: http://awel.domblogger.net/7/media/src/repoview/vamp-plugin-sdk.html

FLAC

There are actually two issues with FLAC in CentOS 7. The first issue, it is not new enough for current version of Audacity, meaning that even if the second issue did not exist, you would not be able to build Audacity with FLAC support in CentOS 7.

That issue I already solved, I already had an updated version of FLAC in my media repository.

The second issue is the same as Vamp Plugin SDK. FLAC uses C++11 and that results in ABI incompatibility when FLAC was built with GCC 4.8.5 but Audacity is being built with GCC 5.5.0.

To solve this, I could not replace the FLAC built with GCC 4.8.5 or it would literally break everything in CentOS 7 that links against the FLAC library and that’s a lot of software.

There were three options:

  1. Build Audacity without FLAC support. Not acceptable.
  2. Build FLAC with GCC 5.5.0 for the build system and static link it to Audacity. Acceptable, but I don’t like static linked libs.
  3. Build FLAC with GCC 5.5.0 and install it in a different prefix than /usr so it does not conflict.

The third is what I did, naming the package gcc-flac. I installed in /opt/gnu which is the prefix being used for the GCC 5.5.0 build environment. That’s when I realized /opt/gnu wasn’t the best choice for a prefix, /opt/gcc55 would have been better. Oh well. If and when I need an even newer GCC that is what I will do.

With a FLAC compiled with GCC 5.5.0, that issue went away.

My FLAC source RPM: http://awel.domblogger.net/7/media/src/repoview/flac.html

Note that the spec files used builds against stock GCC by default, and only builds against GCC 5.5.0 when an argument is passed to define a macro. That lets me have a single spec file for both the updated FLAC I already was maintaining, and the differently named FLAC that is built with GCC 5.5.0.

Are there negative side effects of having two different libraries with identical API and shared object version number but different ABI?

Maybe, I honestly do not know, but so far it seems that the Linux library loader does the right thing and loads the right library as needed when both are installed. When only one is installed and an application wants a library with the same name and SO version but the only one available has the wrong ABI, it seems to core dump.

So when creating the RPM, I made the GCC 5.5.0 version require the same version and release of the GCC 4.8.5 version just to make sure that the GCC 5.5.0 version is never the only version installed. The GCC 4.8.5 version however can be the only one installed (but Audacity then will not work).

wxGTK3

Like Vamp Plugin SDK and FLAC, wxGTK3 uses C++11 and has thus the version in EPEL has the same ABI incompatibility issues when building Audacity with GCC 5.5.0.

To resolve it, I took the Fedora source RPM for wxGTK3 3.0.4 and rebuilt it using a prefix of /opt/gnu with GCC 5.5.0.

But the Fedora (and EPEL) source RPM is actually broken.

It uses the same spec file to build wxGTK3 against both Gtk3 and Gtk2 but the Gtk2 build requires the Gtk2 port of Webkit which was pulled from Fedora/EPEL for security reasons.

So I ripped the Gtk2 build out of it. I also removed the /etc/alternatives stuff out, since it is not needed with the install in the custom prefix.

Theoretically I should do the same thing I did with FLAC where one spec file builds identical versions for both ABIs but I have not done that yet.

The source RPM: http://awel.domblogger.net/7/media/src/repoview/gcc55-wxGTK3.html

Anyway, with a wxGTK3 built against GCC 5.5.0, all the Audacity build issues were solved and I could finally build Audacity 2.2.2.

By the way, wxGTK3 demonstrated just how important running make check is. Initially the spec file happily compiled it, but the CppUnit tests failed. The issue, at least with GCC 5.5.0 their configure script does the wrong thing and sets the std=c++0x flag when it should set the std=gnu+11 flag. According to the GCC documentation, for 5.5.0 std=gnu+11 is the default when not specified, so wxGTK3 is definitely doing the wrong thing.

The unit test failures however alerted me to the issue allowing me to set it manually in the spec file, after which point the unit tests all passed.

RPM and ABI

RPM is not smart enough to figure out ABI dependencies. The Linux loader seems to be, but RPM is not. So the Audacity RPM has to specifically explicitly require the dependencies, or the yum package manager will not pull them in and Audacity will segfault. This is what I did:

# RPM can't figure these out so we have to explicitly require them
Requires:       gcc55-flac-libs
Requires:       gcc55-wxBase3 gcc55-wxGTK3 gcc55-wxGTK3-gl
Requires:       vamp-plugin-sdk

In the future, I will add Provides: gcc55(flac) or something like that for Audacity to require.

Audacity Build Notes

From the Audacity build log:

configure: Using SYSTEM libraries for EXPAT
configure: Using SYSTEM libraries for FFMPEG
configure: Using SYSTEM libraries for LAME
configure: Using SYSTEM libraries for LIBFLAC
configure: Using SYSTEM libraries for LIBID3TAG
configure: Using SYSTEM libraries for LIBMAD
configure: Using LOCAL libraries for LIBNYQUIST
configure: Using LOCAL libraries for LIBSBSMS
configure: Using SYSTEM libraries for LIBSNDFILE
configure: Using SYSTEM libraries for LIBSOUNDTOUCH
configure: Using SYSTEM libraries for LIBSOXR
configure: Using SYSTEM libraries for LIBTWOLAME
configure: Using SYSTEM libraries for LIBVAMP
configure: Using SYSTEM libraries for LIBVORBIS
configure: Using LOCAL libraries for LV2
configure: Using LOCAL libraries for PORTAUDIO
configure: Using LOCAL libraries for PORTSMF
configure: Using LOCAL libraries for PORTMIDI
configure: Using LOCAL libraries for WIDGETEXTRA

The libraries labeled SYSTEM are dynamically linked. The libraries labeled LOCAL are from source directories inside Audacity, which is not my preference.

For LIBNYQUIST, LIBSBSMS, PORTSMF, and WIDGETEXTRA – I do not believe EPEL provides them, so I would have to package them and include them in my media repository. However if Audacity is the only app I build that uses them, then me packaging them just for Audacity really isn’t any different than Audacity bundling them. Other than a smaller update for a bug fix.

For PORTAUDIO – EPEL does have it, but Audacity depends upon a patch that is not in upstream portaudio and it will not build without it, so until either the patch goes upstream or audacity alters how it uses portaudio, the bundled fork of portaudio is necessary.

For LV2 and PORTMIDI there are libraries in EPEL but the Audacity configure script does not recognize them. I have not yet begun to investigate why not.

Source

My source RPM for audacity (which I originally forked from Fedora years ago): http://awel.domblogger.net/7/media/src/repoview/audacity.html

Presently I also have the older source RPM for 2.1.2 there if the GCC C++11 binary incompatility stuff scares you, but building it results in an Audacity that is a pain to use.

Installing

The easiest way to install – just follow the instructions at https://media.librelamp.com/

My media repository also has FFmpeg, VLC, and current GStreamer.

Audacity and the mentioned dependencies are the only packages that currently are built with GCC 5.5.0 but I likely will be building VLC 3.0.3 soon, and it too needs a newer GCC than CentOS 7 has and I may run into some similar C++11 ABI issues there too. In fact I expect I will with Qt5 in which case I will not build VLC 3.0.3 as no effing way am I maintaining Qt5 packages nor am I willing to static link (but static linked VLC 3.0.3 can be found if 2.2.6 is not good enough for you).

1 thought on “Audacity on CentOS 7

  1. I’m in the process of redoing it all with a prefix of /opt/gcc55 for the libraries compiled with GCC 5.5.0. That’s cleaner with the binary ABI issue, don’t mix ABIs in /usr/lib64.

    Audacity will install in /usr/bin but it’s not a library.

Leave a Reply

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

Anonymity protected with AWM Pluggable Unplugged