The first two parts of this series were about building LVGL. It learned to fetch its own dependencies, and then to write down what it linked against so other projects could pick it up. Both still expect you to compile LVGL yourself.
On Ubuntu you no longer have to. LVGL now publishes prebuilt packages, so it installs like anything else on the system. Here is the whole thing, from a clean Ubuntu to a window on screen.
From a Clean Ubuntu to a Running Window#
1. Install the build tooling
apt update
apt install software-properties-common build-essential pkg-configbashsoftware-properties-common provides add-apt-repository, and build-essential gives you a compiler.
2. Add the LVGL PPA
add-apt-repository ppa:lvgl/lvglbash3. Install an LVGL package
apt install liblvgl-sdl2-dev
# or, for a package with every backend:
# apt install liblvgl-full-2d-devbashThat one command also brings in SDL2 and everything else this build of LVGL needs. There is no separate hunt for -dev packages,
and the full list of published packages is below.
4. Write the application
This is the same program from part two. Only the way LVGL got onto the machine is different.
#include <lvgl/lvgl.h>
int main(void)
{
lv_init();
lv_display_t * disp = lv_sdl_window_create(800, 600);
if(!disp) {
return 1;
}
lv_sdl_mouse_create();
lv_obj_t * button = lv_button_create(lv_screen_active());
lv_obj_t * label = lv_label_create(button);
lv_label_set_text_static(label, "Click Me!");
lv_obj_center(button);
while(1) {
lv_timer_handler();
lv_sleep_ms(5);
}
return 0;
}c5. Compile and run
# --static pulls in Requires.private and Libs.private too
gcc main.c -o main $(pkg-config --cflags --static --libs lvgl)bashNo LVGL checkout nor LVGL build. pkg-config or CMake hands the compiler the include path and the full list of link flags, and the window opens.
Full List of Published Packages#
The packages live in a PPA at ppa:lvgl/lvgl. Packaging LVGL is hard because people want contradictory things: some want a lean install,
others want most features enabled so they can get started quickly and try things out. For this first round, we went with the latter: beefy
configurations with most features on, even though an end project would likely disable a chunk of them.
There are 8 packages, split by which display backend(s) they enable:
liblvgl-sdl2-dev: SDL2 desktop backend, 2D onlyliblvgl-sdl2-3d-dev: SDL2 desktop backend, with 3Dliblvgl-drm-dev: DRM backend, 2D onlyliblvgl-drm-3d-dev: DRM backend, with 3Dliblvgl-wayland-dev: Wayland backend, 2D onlyliblvgl-wayland-3d-dev: Wayland backend, with 3Dliblvgl-full-2d-dev: SDL2, DRM, and Wayland together, 2D onlyliblvgl-full-3d-dev: SDL2, DRM, and Wayland together, with 3D
The backend is the only thing that changes between packages, jpeg and png image decoders, GStreamer, and the rest of the feature set are enabled across the board.
Each of those 8 packages is a different build of LVGL, so each links against a different set of libraries.
For a package to work, it has to declare those libraries correctly in two places: to apt, so the right runtime libraries get pulled in, and to pkg-config,
so your own compiler links against them. Both lists come straight from the files LVGL generates during its build. Every .deb ships its own lvgl.pc and CMake config,
installed into the standard system paths, so once a package is on your machine, pkg-config finds it with nothing extra to set up.
Check out part two of the series if you're interested in how pkg-config and CMake config files are created.
Switching backends only touches step 3 and the display you create. Install liblvgl-wayland-dev instead, call lv_wayland_window_create() in place of lv_sdl_window_create(), and the compile line stays exactly the same, because each package carries its own dependency list.
How It Works#
Three things had to line up for those five steps to work.
A .deb is a package. It holds a compiled library or program, its headers, and a list of the other packages it needs.
apt is the tool that installs .deb files, and when it does, it reads that list and installs everything on it too, which is why
step 3 pulled in SDL2 without being asked. A PPA, short for Personal Package Archive, is a place on
Ubuntu's Launchpad service where a project can host its own packages, and add-apt-repository in step 2 is how you point apt at one.
The main Ubuntu archive can't carry everything, and the versions it does carry are often behind. A PPA is how a project gets its own current builds to users directly.
Wrap Up#
Looking back over the three parts, each one leans on the one before it. Resolving dependencies automatically is what made it possible to record exactly what LVGL links against.
Recording that is what made it possible to generate correct pkg-config and CMake files. And those files are what let a .deb install cleanly and link on a different machine.
Give the PPA a try, and if a package misbehaves or you'd like to see another configuration published, open an issue at github.com/lvgl/lvgl/issues.


