Build and Run
Install the dependencies, build the two example applications, and run them on your desktop in an SDL2 window - no target hardware needed.
Both examples shipped with the LVGL Safe preview (v0.1.0) run on your desktop in an SDL2 window, so you can evaluate the library before any target hardware is involved.
1. What you need
| CMake | 3.16 or newer |
| A C99 compiler (or newer) | GCC or Clang |
| SDL2 development files | the simulator backend the examples draw into |
| The LVGL Safe package | already unpacked as a sibling folder, e.g. lvgl_safe-0.1.0-linux-x86_64/ (holding include/ and lib/) |
Installing the tools and dependencies
On Debian-based distributions (Debian / Ubuntu) using the apt package manager:
sudo apt install cmake build-essential libsdl2-devWindows builds use the MSYS2 mingw-w64 GCC toolchain (https://www.msys2.org/). Install the packages once from an MSYS2 shell:
pacman -S --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake \
mingw-w64-x86_64-ninja mingw-w64-x86_64-SDL2Note: If you are using VSCode follow these instructions to set up MSYS2 mingw-w64 and come back to this guide when installing the needed packages.
Python is not needed to build the examples. It is only needed if you want to convert your own images and fonts - see Assets.
2. Build and run
The LVGL Safe repository ships an ubuntu and a windows preset, so cmake --preset <name> and cmake --build --preset <name> configure and build the same way regardless
of platform.
Using the bundled CMake presets
On Debian-based distributions (Debian / Ubuntu), in the repository root:
cmake --preset ubuntu
cmake --build --preset ubuntuOn Windows from a regular Windows shell (PowerShell or cmd), in the repository root:
cmake --preset windows
cmake --build --preset windowsThat configures both examples and produces two binaries:
./build/<platform>/examples/basic_example/basic_example
./build/<platform>/examples/lvgl_safe_api_tour/lvgl_safe_api_tourThe top-level CMakeLists.txt looks for lvgl_safe-x.y.z-<platform>/
subdirectories next to it and imports the library through the CMake config package each one ships
(lib/cmake/lvgl_safe/). Only the subdirectory whose name matches the host
platform (linux, windows) is considered, so the same command resolves to the right
static library. To use a copy kept somewhere else instead, point at the directory that contains include/ and
lib/. For Ubuntu:
cmake --preset ubuntu -DLS_PACKAGE_PREFIX=/path/to/lvgl_safe-0.1.0-linux-x86_64A successful configure prints the version and location it resolved:
-- Found LVGL Safe 0.1.0 in /path/to/lvgl_safe
-- SDL2 target for examples: SDL2::SDL2Linking your own application against the library is the same two lines the examples use (see examples/basic_example/CMakeLists.txt) - every font and image is a generated C file you list alongside your own sources:
add_executable(my_app main.c fonts/my_font.c images/my_image.c)
target_link_libraries(my_app PRIVATE lvgl_safe::lvgl_safe ${LS_SDL2_LIBRARY})Compile-time configuration
Features are selected in a single header, ls_conf.h (in each platform package's include/) -
for example LS_USE_INDEV, LS_USE_RENDER_TEXT or LS_USE_RENDER_IMAGE_ROTATED.
Note on
ls_conf.h: the shippedls_conf.his authoritative, and the copies in the example folders are identical to it. Its values are already compiled into the static library and baked into the struct layouts ininclude/, so it must not be edited - every feature of the preview library is enabled as shipped.
3. The two examples
We suggest trying the examples in this order.
lvgl_safe_api_tour - what the library can do
A deck of eleven screens, one topic per screen, at 1024x600. Click the arrows in the
footer to move through it; the deck wraps around in both directions. The UP/DOWN keys
move the keyboard focus - most screens have only the footer's language button to
focus, but the ls_button and event-callback screens have several.
It covers every widget type in v0.1.0 - rectangle, label, arc, button, image button, image - and all four extension points: the input event callback, custom hit testing, a per-widget render hook, and a whole-screen render hook. Nothing is hidden behind a helper function, so each screen doubles as reference code for the topic it names.
The whole deck is translated. The footer button cycles English, German and French, and
every string on screen follows it, because the labels are bound to an
ls_translation_t rather than to a literal. The text itself lives in
examples/lvgl_safe_api_tour/translations.c - one row per
string, three languages per row - so main.c holds the layout and the logic and none
of the wording. The only strings it builds itself are the ones that are not language
at all, like the 01 / 11 slide counter.
Start here to see the capabilities. → examples/lvgl_safe_api_tour/main.c
basic_example - how an application is put together
One display, two screens, one widget of each basic kind, and a few callbacks, at 800x480. Every element carries a dimmed tag naming its widget type, so what you see on screen maps directly onto the code.
STEP +10 and RESET drive a single application variable; the readout and the arc both follow it, and the switch shows and hides the arc. The arrow icons move between the two screens - the second screen reads the same variable, which shows that application state is not owned by a screen.
This is the file to copy from when starting your own application. It is laid out to show the general shape of every LVGL Safe program: give the display a framebuffer you own, init a screen, create widgets onto it, configure them by writing struct fields, then loop over input, render, and flush.
Two properties worth noticing as you read: every widget is a caller-owned static
struct created once at start-up - nothing is allocated at runtime and nothing is ever
destroyed - and every fallible call returns an ls_error_code_t that is checked at
the call site.
See → examples/basic_example/main.c
For a line-by-line walkthrough of that shape, see Your first program.
4. If something goes wrong
| Symptom | Cause |
|---|---|
No unpacked LVGL Safe package for '<platform>' found in ... | no lvgl_safe-x.y.z-<platform>/ subdirectory was found for the host platform - extract the matching package as a sibling of CMakeLists.txt (not directly into the repository root), or pass -DLS_PACKAGE_PREFIX=<path> |
... does not look like an unpacked LVGL Safe package | the path given to -DLS_PACKAGE_PREFIX is not the directory holding include/ and lib/ (lib/cmake/lvgl_safe/lvgl_safeConfig.cmake was not found there) |
| SDL2 not found at configure time | install the SDL2 development package, not just the runtime |
| A widget draws nothing, no error | its width/height are still 0, common.hidden is set, or it is a button in a checked state that was never given a color and opacity - those five states default to transparent |
ls_render() returns 3 (LS_ERROR_CODE_INVALID_CONFIGURATION) | some widget on the active screen is missing a required source: a label with no font, an image with no src, or an image button whose current state's src_* is NULL. One such widget fails the whole frame |
| A widget was configured but nothing changed | the fields were set before ls_<widget>_create(), which resets the struct - always configure after creating |
Last updated on
Delivery
Everything that ships with LVGL Safe - the product and compliance documentation your certification effort draws on, plus the delivery and support documentation around it.
Your First Program
A complete LVGL Safe application in one file - framebuffer, display, screen, widgets, and the main loop you own.