Skip to content

Code Generation

Several source files in the EdgeTX tree are not written by hand — they are produced by generator scripts and then committed to git. The build does not run these generators, so if you change one of their inputs you must re-run the generator and commit the regenerated output alongside your change.

Generator Produces Re-run when you change
radio/src/fonts/lvgl/make_fonts.sh radio/src/fonts/lvgl/{std,sml,lrg}/lv_font_*.c a font source, or add a character to the cn/tw/jp/he/ko/ru/ua translations
tools/cfn_sorter.sh radio/src/cfn_sort.cpp a special function name (TR_SF_*) in any translation, or radio/src/dataconstants.h
tools/generate-yaml.sh radio/src/storage/yaml/yaml_datastructs_*.cpp ModelData/RadioData structures

Note

Both translation-driven generators are narrower than they look. cfn_sorter.cpp reads only the 25 TR_SF_* special function names, so editing any other string leaves cfn_sort.cpp untouched. The fonts only change if a translation introduces a character the font does not already contain, and only for the seven languages listed above — the Latin-script translations never affect them.

If you are unsure, just run the generator: it rewrites its output in place, so git status afterwards tells you whether anything actually moved.

Using the development container

All three generators need tooling that is awkward to install by hand — a set of system locales, the lv_font_conv npm package, and a specific libclang version. The EdgeTX development container has all of it preinstalled, and is the reference environment:

docker run -it --rm -v $(pwd):/src -w /src \
  ghcr.io/edgetx/edgetx-dev \
  bash

Everything below can then be run from /src inside that container. If you use the dev container integration in VS Code, the same image is picked up automatically from .devcontainer/devcontainer.json.

LVGL fonts

radio/src/fonts/lvgl/make_fonts.sh regenerates the LVGL font tables for the colour LCD radios, in three sizes (std, sml and lrg — selected at build time by the radio's screen resolution).

radio/src/fonts/lvgl/make_fonts.sh

It reads the TrueType/OpenType sources under radio/src/fonts/ (Roboto, Noto, Arimo and Nanum), the EdgeTX symbol fonts in radio/src/fonts/lvgl/EdgeTX/, and the FontAwesome set that ships inside the LVGL submodule. For the non-Latin languages it also scans the translation headers to work out which glyphs are actually needed, via the get_char_*.py helpers in the same directory.

Requirements:

  • lv_font_convnpm install -g lv_font_conv
  • python3 and gcc (the script compiles a small LZ4 compression helper on the fly)
  • the LVGL submodule — git submodule update --init --recursive

A full run takes a few minutes and rewrites around 150 files.

Warning

If a translation header cannot be read, the script prints WARNING: No characters found ... Skipping and carries on rather than failing. Check the output for that message — an otherwise clean run may simply have skipped a language.

Custom function sort order

tools/cfn_sorter.sh generates radio/src/cfn_sort.cpp, the table that puts the custom function list into alphabetical order for each translated language.

tools/cfn_sorter.sh

It compiles tools/cfn_sorter.cpp once per language (selecting the language with a -DLNG_xx define) and concatenates the results. Sorting uses std::locale, so the matching system locale must exist, or the program aborts at runtime with locale::facet::_S_create_c_locale name not valid.

The dev container and the tools/setup_buildenv_ubuntu*.sh scripts install these already. On any other system, generate them by hand:

apt update && apt install locales
locale-gen zh_CN.UTF-8 cs_CZ.UTF-8 da_DK.UTF-8 de_DE.UTF-8 es_ES.UTF-8 en_US.UTF-8 \
  fi_FI.UTF-8 fr_FR.UTF-8 he_IL.UTF-8 it_IT.UTF-8 ja_JP.UTF-8 ko_KR.UTF-8 \
  nl_NL.UTF-8 pl_PL.UTF-8 pt_PT.UTF-8 ru_RU.UTF-8 sv_SE.UTF-8 zh_TW.UTF-8 uk_UA.UTF-8

The full list is repeated in the comments at the top of the script. Only a C++ compiler and those locales are needed; a run takes a few seconds.

YAML parsers

tools/generate-yaml.sh regenerates the YAML storage parsers. Because it depends on a particular libclang version, it should always be run in the development container:

docker run -it --rm -v $(pwd):/src \
  ghcr.io/edgetx/edgetx-dev \
  /src/tools/generate-yaml.sh

Set FLAVOR to a semicolon-separated list to limit which radios are generated:

docker run -it --rm -v $(pwd):/src \
  -e "FLAVOR=tx16s;nv14;x7;x9d" \
  ghcr.io/edgetx/edgetx-dev \
  /src/tools/generate-yaml.sh

Warning

The script deletes and recreates a build directory in the current working directory, so run it from the repository root and expect any existing build/ to be removed.

See YAML Parser/Generator for how the parsers work, and for what to do when adding a new radio.

Checking your regenerated output

After running a generator, review what changed before committing:

git status --porcelain -- radio/src/fonts/lvgl radio/src/cfn_sort.cpp radio/src/storage/yaml
git diff --stat

An empty result means the committed files were already up to date and there is nothing to commit. Otherwise, commit the regenerated files together with the change that caused them to move.

Tip

Both make_fonts.sh and cfn_sorter.sh leave intermediate files behind (lv_font.inc, lz4_font and tools/a.out) if they are interrupted. They are removed automatically on a successful run, but are safe to delete by hand.