From b5dd2004e32a61401dc44389abd0ac54016d888e Mon Sep 17 00:00:00 2001 From: Toby Murray Date: Thu, 13 Aug 2026 11:30:40 -0400 Subject: [PATCH] fix(cmake): key the GUI merge on the GUI target, not on TouchGFX una_app_build_app() lists what the merge step must wait for, and adds the GUI ELF only when TOUCHGFX_PATH is defined. That asks whether the app uses TouchGFX. What it needs to know is whether una_app_build_gui() built a GUI ELF. The two matched while TouchGFX was the only way to draw one. Since cb1ae1f1 (2025-09-29) the SDK also ships the CustomGUI entry point, which needs only a Gui class taking the kernel and a run(), and leaves the app to own the message loop. An app using it builds a GUI ELF and sets no TOUCHGFX_PATH, so the merge target never depends on that ELF: the generated makefile lists Service.elf alone. The ELF is still built, because add_executable puts it in all. What is missing is the ordering, so app_merging.py races the post-build step that packs Tmp/*.gui. "make App" fails outright with "Missing .gui file", which is required for every type but Glance, and a full parallel make succeeds or fails depending on scheduling order. Both outcomes were observed on one tree. Glances are why that file is optional, and they are unaffected: a glance app has no GUI ELF by design. Its service asks the kernel for the glance geometry, sends a list of SDK::Glance controls with RequestGlanceUpdate, and the kernel draws them, so there is no app framebuffer and no GUI process to wait for. if(TARGET) asks CMake the question directly. TOUCHGFX_PATH stays in the condition for apps that call una_app_build_app() before una_app_build_gui(), where the target does not exist yet and add_custom_target resolves DEPENDS at generate time. Verified in the CI image with a CustomGUI app that names the SDK entry point by path and sets none of TOUCHGFX_PATH, TOUCHGFX_LIBS or GUI_*: the merge target gains GUI.elf as a prerequisite and "make App" merges, where on upstream/main the prerequisite is absent and the same command fails. Workout's .uapp is byte-identical across the change (404484 bytes). --- cmake/una-app.cmake | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmake/una-app.cmake b/cmake/una-app.cmake index 0332c15c..6d8b6163 100644 --- a/cmake/una-app.cmake +++ b/cmake/una-app.cmake @@ -331,9 +331,13 @@ function(una_app_build_app) ) endforeach() - # Final app merging + # Final app merging. The merge needs the GUI ELF packed first, so ask whether + # one was built rather than whether TouchGFX built it: a CustomGUI app sets no + # TOUCHGFX_PATH, and keying on that left app_merging.py racing the packer. + # TOUCHGFX_PATH stays for apps calling this before una_app_build_gui(), where + # the target does not exist yet and DEPENDS resolves at generate time. set(APP_DEPENDS ${APP_NAME}Service.elf) - if(DEFINED TOUCHGFX_PATH) + if(TARGET ${APP_NAME}GUI.elf OR DEFINED TOUCHGFX_PATH) list(APPEND APP_DEPENDS ${APP_NAME}GUI.elf) endif() set(APP_AUTOSTART_FLAG "")