st: libxft with bgra patch in Ubuntu
2021-07-26 (last update on 2023-04-12)
Why to patch libxft?
st, the simple terminal by suckless.org, has a lot of advantages:
- It's very small.
- It's super fast.
- Its code is simple.
- There are many patches (=additional functions) available.
But its biggest problem is that it crashes when you type a color emoji (or it occurs in an e-mail or text file, p.e.). This is not a bug in st but in libxft (which is a dependency of st). Obviously, a crashing terminal emulator is not an option. So you can either choose a font that has no color emojis, or you apply the "bgra patch" (by Maxime Coste) to libxft.
When you use Arch Linux, you are lucky: You can simply install libxft-bgra (AUR). But for others (for example Ubuntu users) it's a little bit more difficult. Here is how to make st work with color emojis in Ubuntu:
Apply the bgra patch to libxft
First, get the libxft source code and fetch the branch with the bgra patch:
cd ~
git clone https://gitlab.freedesktop.org/xorg/lib/libxft.git
cd libxft
# git fetch https://gitlab.freedesktop.org/mawww/libxft.git bgra-glyphs
# git checkout -b mawww/libxft-bgra-glyphs FETCH_HEAD
UPDATE (2022-09): Meanwhile, the bgra patch was merged into master and released in libXft 2.3.5. Checkout the latest release (currently 2.3.7) instead:
git checkout libXft-2.3.7
Then install the packages needed for building and build the patched libxft:
sudo apt install build-essential libtool pkg-config libxrender-dev libfreetype6-dev libfontconfig1-dev xutils-dev
sh autogen.sh --sysconfdir=/etc --prefix=/usr --mandir=/usr/share/man
make
Now, you could install the patched version with sudo make install. But st wouldn't use the newly installed version anyway (because it doesn't find it). This can be fixed but I prefer making st using the patched version and keep the default libxft for other programs as it is.
Build st with the patched libxft linked
If you haven't already cloned the st repository, do it now:
cd ~
git clone git://git.suckless.org/st
cd st
Now tell it where to find the patched libxft version:
diff --git a/config.mk b/config.mk
index c070a4a..4920ec9 100644
--- a/config.mk
+++ b/config.mk
@@ -7,8 +7,8 @@ VERSION = 0.8.4
PREFIX = /usr/local
MANPREFIX = $(PREFIX)/share/man
-X11INC = /usr/X11R6/include
-X11LIB = /usr/X11R6/lib
+X11INC = $(HOME)/libxft/include
+X11LIB = $(HOME)/libxft/src/.libs
PKG_CONFIG = pkg-config
@@ -23,7 +23,7 @@ LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \
# flags
STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600
STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS)
-STLDFLAGS = $(LIBS) $(LDFLAGS)
+STLDFLAGS = -Xlinker -rpath=$(X11LIB) $(LIBS) $(LDFLAGS)
# OpenBSD:
#CPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 -D_BSD_SOURCE
Of course, you'll have to replace $(HOME)/libxft
with the actual path to your patched libxft.
Then do make
. You can check if st uses the patched version of libxft:
▶ ldd ./st
linux-vdso.so.1 (0x00007fffc413f000)
libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007f98204b1000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f98204ac000)
libXft.so.2 => /home/max/libxft/src/.libs/libXft.so.2 (0x00007f9820492000)
...
Now run sudo make install
and you can start your patched st with your usual key binding or by executing st
whereever you start programs.