Rust: PDFs — Build and Install Pango and Associated Libraries
At the conclusion of the last article, we mentioned that we would explore Pango, along with its associated libraries: GNU FriBidi and CairoGraphics. In this article, we describe how to build and install them on both Ubuntu and Windows, and verify the installation using the native CLI tool included with Pango.
🦀 Index of the Complete Series.
![]() |
|---|
| Rust: PDFs — Build and Install Pango and Associated Libraries |
We will first describe how to build and install Pango on Ubuntu 🐧, and then on Windows 🪟.
This process assumes that HarfBuzz has already been built and installed, as described in the
first article.
Originally, I planned to discuss the Rust code as well. I have already completed the study code, but this article became too long. For now, I want to capture as much detail as possible so that if I need to repeat the process later, the information will be readily available.
🙏 Please note that Pango depends on HarfBuzz. On Windows 🪟, the default
Pango build process will include its own HarfBuzz build. We must explicitly
instruct it to use our existing HarfBuzz build and installation instead.
❶ Ubuntu: Build and Install Pango and Associated Libraries
💥 Please note: At the time of writing this section, I recalled that my earlier research
suggested Pango and its associated libraries may already be included with the
Ubuntu distribution. However, I did not verify this. I proceeded with building and installing
them manually, and afterward encountered a Pango version conflict
as discussed. 🙏 If you are following
this article, I recommend reading this section in full before deciding whether you need to
perform the build and installation yourself.
⓵ Upgrade the Meson Build Tool
In the
first article, we installed Meson. However, building
Pango requires a newer version. The following commands install the latest
Meson in the user path, without modifying the system Python:
$ sudo apt remove meson
$ sudo apt install pipx
$ pipx ensurepath
$ pipx install meson
$ pipx ensurepath
Running meson --version reports 1.10.0. I am not certain how
this change would affect the HarfBuzz build and installation described in
the first
article, should I need to repeat that process.
● The first pipx ensurepath command reports:
Success! Added /home/behai/.local/bin to the PATH environment variable.
Consider adding shell completions for pipx. Run 'pipx completions' for instructions.
You will need to open a new terminal or re-login for the PATH changes to take effect.
Otherwise pipx is ready to go! ✨ 🌟 ✨
● After successful completion, the pipx install meson command suggests
running pipx ensurepath again:
installed package meson 1.10.0, installed using Python 3.12.3
These apps are now globally available
- meson
These manual pages are now globally available
- man1/meson.1
⚠️ Note: '/home/behai/.local/bin' is not on your PATH environment variable. These apps will not be globally accessible until your PATH is updated. Run `pipx ensurepath` to automatically add it, or manually
modify your PATH in your shell's config file (i.e. ~/.bashrc).
done! ✨ 🌟 ✨
● The second pipx ensurepath command reports:
/home/behai/.local/bin has been been added to PATH, but you need to open a new terminal or re-login for this PATH change to take effect.
You will need to open a new terminal or re-login for the PATH changes to take effect.
Otherwise pipx is ready to go! ✨ 🌟 ✨
⓶ Build and Install Pango and Associated Libraries
⑴ Install Development Packages
The following commands install all required development packages to build
Pango:
$ sudo apt-get update
$ sudo apt-get install meson ninja-build pkg-config \
gcc g++ ragel gtk-doc-tools \
libglib2.0-dev libfreetype6-dev libfontconfig1-dev \
libcairo2-dev libfribidi-dev libharfbuzz-dev
To confirm, run:
$ ls -l /usr/lib/x86_64-linux-gnu/pkgconfig/ | more
You should see entries such as:
cairo*.pc, freetype2.pc, fribidi.pc, glib-2.0.pc, gobject-2.0.pc, harfbuzz-*.pc, harfbuzz.pc, harfbuzz-subset.pc
⑵
Build Pango From Source and Install
● Download the latest tarball from GNOME:
$ wget https://download.gnome.org/sources/pango/1.56/pango-1.56.4.tar.xz
$ tar xf pango-1.56.4.tar.xz
$ cd pango-1.56.4
$ meson setup build --prefix=/usr/local
This command produces a long output. The final lines include:
...
pango 1.56.4
Font backends
Fontconfig : true
DirectWrite : false
CoreText : false
Features
Cairo : true
Thai : false
Sysprof : false
Toolchain
Compiler : gcc
Linker : ld.bfd
Build
Debugging : true
Optimization : 2
Introspection: false
Documentation: false
Man pages : false
Tests : true
Examples : true
Directories
prefix : /usr/local
includedir : /usr/local/include
libdir : /usr/local/lib/x86_64-linux-gnu
datadir : /usr/local/share
Subprojects
glib : YES
gvdb : YES (from glib)
User defined options
prefix : /usr/local
Found ninja-1.11.1 at /usr/bin/ninja
💥 Observation: In the Subprojects section,
HarfBuzz is not listed. This suggests it is using the build and installation
from the first
article. If so, it raises the question of why the libharfbuzz-dev package
was required as described. Most likely,
the dev package ensures headers and pkg-config files are available for detection.
$ ninja -C build
$ sudo ninja -C build install
The output of ninja -C build is lengthy and includes many warnings.
The output of sudo ninja -C build install is also long, but appears clean.
After installation, you should find pango.pc in
/usr/local/lib/x86_64-linux-gnu/pkgconfig:
$ ls -l /usr/local/lib/x86_64-linux-gnu/pkgconfig/pango.pc
You should also have the pango-view executable:
$ sudo find / -iname pango-view
Output:
find: ‘/proc/5116’: No such file or directory
/home/behai/pango-1.56.4/build/utils/pango-view
/usr/local/bin/pango-view
⓷ Resolving Pango Version Conflict
/usr/local/bin/pango-view should be in the user path:
$ which pango-view
Checking the version:
$ pango-view --version
reports:
pango-view (pango) 1.56.4
Linked Pango library has a different version: 1.52.1
During configuration, the target version
was pango 1.56.4. Observation: the linked version
1.52.1 likely comes with the Ubuntu distribution
as noted earlier. It is a system-installed shared
library located in /usr/lib/x86_64-linux-gnu/:
$ ls -l /usr/lib/x86_64-linux-gnu/libpango*-1.0.so*
lrwxrwxrwx 1 root root 24 Mar 31 2024 /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0 -> libpango-1.0.so.0.5200.1
-rw-r--r-- 1 root root 433912 Mar 31 2024 /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0.5200.1
lrwxrwxrwx 1 root root 29 Mar 31 2024 /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 -> libpangocairo-1.0.so.0.5200.1
-rw-r--r-- 1 root root 67712 Mar 31 2024 /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.5200.1
lrwxrwxrwx 1 root root 27 Mar 31 2024 /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 -> libpangoft2-1.0.so.0.5200.1
-rw-r--r-- 1 root root 108536 Mar 31 2024 /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.5200.1
lrwxrwxrwx 1 root root 27 Mar 31 2024 /usr/lib/x86_64-linux-gnu/libpangoxft-1.0.so.0 -> libpangoxft-1.0.so.0.5200.1
-rw-r--r-- 1 root root 38904 Mar 31 2024 /usr/lib/x86_64-linux-gnu/libpangoxft-1.0.so.0.5200.1
We configured pango 1.56.4
to install under /usr/local:
ls -l /usr/local/lib/x86_64-linux-gnu/libpango*-1.0.so*
lrwxrwxrwx 1 root root 17 Dec 15 11:34 /usr/local/lib/x86_64-linux-gnu/libpango-1.0.so -> libpango-1.0.so.0
lrwxrwxrwx 1 root root 24 Dec 15 11:34 /usr/local/lib/x86_64-linux-gnu/libpango-1.0.so.0 -> libpango-1.0.so.0.5600.4
-rwxr-xr-x 1 root root 1659184 Dec 15 11:34 /usr/local/lib/x86_64-linux-gnu/libpango-1.0.so.0.5600.4
lrwxrwxrwx 1 root root 22 Dec 15 11:34 /usr/local/lib/x86_64-linux-gnu/libpangocairo-1.0.so -> libpangocairo-1.0.so.0
lrwxrwxrwx 1 root root 29 Dec 15 11:34 /usr/local/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 -> libpangocairo-1.0.so.0.5600.4
-rwxr-xr-x 1 root root 245784 Dec 15 11:34 /usr/local/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0.5600.4
lrwxrwxrwx 1 root root 20 Dec 15 11:34 /usr/local/lib/x86_64-linux-gnu/libpangoft2-1.0.so -> libpangoft2-1.0.so.0
lrwxrwxrwx 1 root root 27 Dec 15 11:34 /usr/local/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 -> libpangoft2-1.0.so.0.5600.4
-rwxr-xr-x 1 root root 454288 Dec 15 11:34 /usr/local/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0.5600.4
lrwxrwxrwx 1 root root 20 Dec 15 11:34 /usr/local/lib/x86_64-linux-gnu/libpangoxft-1.0.so -> libpangoxft-1.0.so.0
lrwxrwxrwx 1 root root 27 Dec 15 11:34 /usr/local/lib/x86_64-linux-gnu/libpangoxft-1.0.so.0 -> libpangoxft-1.0.so.0.5600.4
-rwxr-xr-x 1 root root 165104 Dec 15 11:34 /usr/local/lib/x86_64-linux-gnu/libpangoxft-1.0.so.0.5600.4
At runtime, the dynamic linker ld searches
library paths in this order:
-
/lib,/usr/lib(system defaults) -
Any paths in
/etc/ld.so.confandld.so.cache -
/usr/local/libif configured
Because /usr/lib/x86_64-linux-gnu/ precedes
/usr/local/lib/x86_64-linux-gnu/, pango-view links against
pango 1.52.1 instead of pango 1.56.4. We need to instruct the
linker to prefer /usr/local/lib/x86_64-linux-gnu/.
As a temporary measure, update LD_LIBRARY_PATH for the current session:
$ export LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH
$ pango-view --version
It should now report pango-view (pango) 1.56.4.
To make this change permanent, use
ldconfig.
Create /etc/ld.so.conf.d/local.conf containing:
/usr/local/lib/x86_64-linux-gnu
Then update the system’s library cache so /usr/local libraries are preferred:
$ sudo ldconfig
Verify with ldd:
$ ldd /usr/local/bin/pango-view | grep pango
You should see output similar to:
libpango-1.0.so.0 => /usr/local/lib/x86_64-linux-gnu/libpango-1.0.so.0 (0x000078a9b3e33000)
libpangoft2-1.0.so.0 => /usr/local/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 (0x000078a9b3e16000)
libpangoxft-1.0.so.0 => /usr/local/lib/x86_64-linux-gnu/libpangoxft-1.0.so.0 (0x000078a9b3e0b000)
libpangocairo-1.0.so.0 => /usr/local/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 (0x000078a9b3df7000)
After starting a fresh ssh session, pango-view should now report
pango-view (pango) 1.56.4.
⓸ Test Pango Installation with pango-view
We can use pango-view to verify that Pango and its associated
libraries are functioning correctly:
$ pango-view --no-display --text="Hello, 世界" --font="NotoSansTC-Regular 16" --output=hello.png
This should produce a small hello.png file containing the rendered text.
Note that pango-view does not support PDF generation.
❷ Windows: Build and Install Pango and Associated Libraries
⓵ Environment — the 64-bit Developer Command Prompt for
Visual Studio 2022
💡 Important 💥 The steps that follow rely on an up-to-date installation of
Visual Studio 2022 on Windows. I have not tested this process with later versions of
Visual Studio, so I cannot comment on compatibility beyond 2022.
To access the 64-bit Developer Command Prompt for Visual Studio 2022 (or for your installed version),
open a Windows Terminal session, launch a new Command Prompt, and run the following batch file:
"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
You should see output similar to the following—note the x64 architecture:
**********************************************************************
** Visual Studio 2022 Developer Command Prompt v17.14.18
** Copyright (c) 2025 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'
We covered this environment setup in detail in the first article.
⓶ Build and Install GNU FriBidi
The build process needs to know where to find vcpkg:
set PKG_CONFIG=C:\PF\vcpkg\installed\x64-windows\tools\pkgconf\pkgconf.exe
set PKG_CONFIG_PATH=C:\PF\vcpkg\installed\x64-windows\lib\pkgconfig
I am using the C:\PF\ directory as the root folder, as before:
c:
cd\PF
Download the source and prepare to build:
git clone https://github.com/fribidi/fribidi.git
cd fribidi
mkdir build
Then build:
meson setup build --buildtype=release --default-library=both -Ddocs=false
cd build
meson compile
Finally, install:
meson install --destdir ../dist
● The meson setup build... step should not take long. The output is short, ending with:
...
fribidi 1.0.16
User defined options
buildtype : release
default_library: both
docs : false
Found ninja-1.12.1 at "C:\Program Files\Meson\ninja.EXE"
● The meson compile command also produces a short output.
● The meson install... command should complete quickly, with minimal output.
After installation, we should have the following files:
C:\PF\fribidi\dist\bin\[fribidi.exe, fribidi-0.dll]
C:\PF\fribidi\dist\include\fribidi\*.h
C:\PF\fribidi\dist\lib\[fribidi.lib, libfribidi.a]
C:\PF\fribidi\dist\lib\pkgconfig\fribidi.pc
⓷ Build and Install Cairo-1.18.4
The build process needs to know where to find vcpkg:
set PKG_CONFIG=C:\PF\vcpkg\installed\x64-windows\tools\pkgconf\pkgconf.exe
set PKG_CONFIG_PATH=C:\PF\vcpkg\installed\x64-windows\lib\pkgconfig
● Download https://cairographics.org/releases/cairo-1.18.4.tar.xz
● Extract and copy the entire cairo-1.18.4\ directory from the archive to
C:\PF\cairo-1.18.4\
● Change to C:\PF\cairo-1.18.4\
⑵ Build Cairo From Source and Install
🦀 The working directory is C:\PF\cairo-1.18.4\. Run the following commands:
meson setup build --buildtype=release --default-library=shared -Dtests=disabled -Dpng=enabled -Dzlib=enabled -Dglib=enabled
meson compile -C build
meson install -C build --destdir ../dist
● The first command meson setup build... produces long output. The final lines include:
...
Build targets in project: 51
cairo 1.18.4
Surface Backends
Image : YES
Recording : YES
Observer : YES
Mime : YES
Tee : YES
Xlib : NO
Xlib Xrender : NO
Quartz : NO
Quartz-image : NO
XCB : NO
Win32 : YES
CairoScript : YES
PostScript : YES
PDF : YES
SVG : YES
Font Backends
User : YES
FreeType : NO
Fontconfig : NO
Win32 : YES
Win32 DWrite : YES
Quartz : NO
Functions
PNG functions : YES
X11-xcb : NO
XCB-shm : NO
Features and Utilities
cairo-trace: : NO
cairo-script-interpreter: YES
API reference : NO
Subprojects
pixman : YES
User defined options
buildtype : release
default_library : shared
glib : enabled
png : enabled
tests : disabled
zlib : enabled
Found ninja-1.12.1 at "C:\Program Files\Meson\ninja.EXE"
● The second command meson compile -C build produces a large number of
warnings, but no errors.
● The third command meson install -C build --destdir ../dist produces only
minimal output and completes fairly quickly.
After installation, we should have the following files:
C:\PF\cairo-1.18.4\dist\bin\cairo-2.dll
C:\PF\cairo-1.18.4\dist\bin\cairo-gobject-2.dll
C:\PF\cairo-1.18.4\dist\bin\cairo-script-interpreter-2.dll
C:\PF\cairo-1.18.4\dist\bin\pixman-1-0.dll
C:\PF\cairo-1.18.4\dist\include\cairo
C:\PF\cairo-1.18.4\dist\include\pixman-1
C:\PF\cairo-1.18.4\dist\include\cairo\cairo-deprecated.h
C:\PF\cairo-1.18.4\dist\include\cairo\cairo-dwrite.h
C:\PF\cairo-1.18.4\dist\include\cairo\cairo-features.h
C:\PF\cairo-1.18.4\dist\include\cairo\cairo-gobject.h
C:\PF\cairo-1.18.4\dist\include\cairo\cairo-pdf.h
C:\PF\cairo-1.18.4\dist\include\cairo\cairo-ps.h
C:\PF\cairo-1.18.4\dist\include\cairo\cairo-script-interpreter.h
C:\PF\cairo-1.18.4\dist\include\cairo\cairo-script.h
C:\PF\cairo-1.18.4\dist\include\cairo\cairo-svg.h
C:\PF\cairo-1.18.4\dist\include\cairo\cairo-tee.h
C:\PF\cairo-1.18.4\dist\include\cairo\cairo-version.h
C:\PF\cairo-1.18.4\dist\include\cairo\cairo-win32.h
C:\PF\cairo-1.18.4\dist\include\cairo\cairo.h
C:\PF\cairo-1.18.4\dist\include\pixman-1\pixman-version.h
C:\PF\cairo-1.18.4\dist\include\pixman-1\pixman.h
C:\PF\cairo-1.18.4\dist\lib\cairo-gobject.lib
C:\PF\cairo-1.18.4\dist\lib\cairo-script-interpreter.lib
C:\PF\cairo-1.18.4\dist\lib\cairo.lib
C:\PF\cairo-1.18.4\dist\lib\pixman-1.lib
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\cairo-dwrite-font.pc
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\cairo-gobject.pc
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\cairo-pdf.pc
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\cairo-png.pc
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\cairo-ps.pc
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\cairo-script-interpreter.pc
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\cairo-script.pc
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\cairo-svg.pc
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\cairo-tee.pc
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\cairo-win32-font.pc
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\cairo-win32.pc
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\cairo.pc
C:\PF\cairo-1.18.4\dist\lib\pkgconfig\pixman-1.pc
⓸ Using Our Own HarfBuzz Library
As mentioned at the beginning, by default the
Pango build process will include its own HarfBuzz
build. We need to explicitly instruct it to use our existing HarfBuzz
build and installation instead.
⓹ Build and Install Pango
The build process needs to know where to find
vcpkg
and all dependent libraries. For example, to use our own HarfBuzz
build, we must include C:\PF\harfbuzz\dist\lib\pkgconfig\ in
the PKG_CONFIG_PATH environment variable:
set PKG_CONFIG=C:\PF\vcpkg\installed\x64-windows\tools\pkgconf\pkgconf.exe
set PKG_CONFIG_PATH=C:\PF\vcpkg\installed\x64-windows\lib\pkgconfig;C:\PF\harfbuzz\dist\lib\pkgconfig;C:\PF\fribidi\dist\lib\pkgconfig;C:\PF\cairo-1.18.4\dist\lib\pkgconfig
I am using the C:\PF\ directory as the root folder, as before:
c:
cd\PF
Download the source and prepare to build:
git clone https://gitlab.gnome.org/GNOME/pango.git
cd pango
Then build:
meson setup build --buildtype=release --default-library=shared -Dintrospection=disabled
meson compile -C build
Finally, install:
meson install -C build --destdir ../dist
● The meson setup build... step should not take long. The output is moderately
lengthy, ending with:
...
pango 1.57.1
Font backends
Fontconfig : false
DirectWrite : true
CoreText : false
Features
Cairo : true
Thai : false
Sysprof : false
Toolchain
Compiler : msvc
Linker : link
Build
Debugging : false
Optimization : 3
Introspection : false
Documentation : false
Man pages : false
Tests : true
Examples : true
Directories
prefix : c:/
includedir : c:/include
libdir : c:/lib
datadir : c:/share
User defined options
buildtype : release
default_library: shared
introspection : disabled
Found ninja-1.12.1 at "C:\Program Files\Meson\ninja.EXE"
● The meson compile... command produces moderately long output with warnings,
but no errors.
● The meson install... command completes quickly, with minimal output. After installation,
we should have the following files:
C:\PF\pango\dist\bin\pango-1.0-0.dll
C:\PF\pango\dist\bin\pango-list.exe
C:\PF\pango\dist\bin\pango-segmentation.exe
C:\PF\pango\dist\bin\pango-view.exe
C:\PF\pango\dist\bin\pangocairo-1.0-0.dll
C:\PF\pango\dist\bin\pangowin32-1.0-0.dll
C:\PF\pango\dist\include\pango-1.0\pango\pango-*.h
C:\PF\pango\dist\include\pango-1.0\pango\pango.h
C:\PF\pango\dist\include\pango-1.0\pango\pangocairo.h
C:\PF\pango\dist\include\pango-1.0\pango\pangowin32.h
C:\PF\pango\dist\lib\pango-1.0.lib
C:\PF\pango\dist\lib\pangocairo-1.0.lib
C:\PF\pango\dist\lib\pangowin32-1.0.lib
C:\PF\pango\dist\lib\pkgconfig\pango.pc
C:\PF\pango\dist\lib\pkgconfig\pangocairo.pc
C:\PF\pango\dist\lib\pkgconfig\pangowin32.pc
⓺ Test Pango Installation with pango-view
Check the version of pango-view.exe:
C:\PF\pango\dist\bin\pango-view.exe --version
This reports pango-view (pango) 1.57.1, which matches the version built above.
As on Ubuntu 🐧, we use pango-view
to verify that Pango and its associated libraries are functioning correctly.
We need to ensure that all required DLLs are available in the PATH. Run the following once:
set PATH=C:\PF\harfbuzz\dist\bin\;%PATH%
set PATH=C:\PF\vcpkg\installed\x64-windows\bin\;%PATH%
set PATH=C:\PF\pango\dist\bin;C:\PF\cairo-1.18.4\dist\bin;C:\PF\fribidi\dist\bin;%PATH%
Then run pango-view:
C:\PF\pango\dist\bin\pango-view.exe --no-display --text="Hello, 世界" --font="Arial Unicode MS 16" --output=hello.png
This should produce a small hello.png file containing the rendered text,
just as on Ubuntu 🐧.
While much of the information in this article was supplied by AIs, it still takes considerable effort to implement the instructions. I could not find any post that documents this process, so I decided to write it down for myself first and foremost. I hope it also proves useful to anyone else who happens to be on the same path.
As mentioned earlier, I have already completed the study Rust code that uses
Pango and its associated libraries. I originally planned to discuss it here,
but the article became too long, and I felt a bit exhausted writing it. We will cover
the code in the next article.
Thanks for reading! As always—stay curious, stay safe 🦊
✿✿✿
Feature image sources:
- https://www.omgubuntu.co.uk/2024/03/ubuntu-24-04-wallpaper
- https://in.pinterest.com/pin/337277459600111737/
- https://ur.wikipedia.org/wiki/%D9%81%D8%A7%D8%A6%D9%84:HarfBuzz.svg
- https://en.wikipedia.org/wiki/Pango
