Skip to content

Commit c26cbdf

Browse files
authored
Merge pull request #225 from TheTom/fix-ui-assets-partial-dist
ui: don't trust a partial dist dir (fixes 'missing loading.html' build abort on Termux/sharp failure)
2 parents 471fb4e + c09b7c8 commit c26cbdf

1 file changed

Lines changed: 69 additions & 9 deletions

File tree

scripts/ui-assets.cmake

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,53 @@ set(STAMP_FILE "${UI_BINARY_DIR}/.ui-stamp")
2424
set(UI_CPP "${UI_BINARY_DIR}/ui.cpp")
2525
set(UI_H "${UI_BINARY_DIR}/ui.h")
2626

27+
# A dist directory is only usable if it holds the COMPLETE asset set that
28+
# llama-ui-embed requires. A partial dist -- e.g. an npm PWA-assets build that
29+
# died in the native `sharp` step (common on Termux / very new Node), leaving
30+
# only index.html -- must not be trusted, or llama-ui-embed aborts the whole
31+
# build with "missing required asset(s): loading.html ...". Treat an incomplete
32+
# dist as unusable so provisioning falls through to the HF download instead of
33+
# hard-failing. Mirrors the required-asset list in tools/ui/embed.cpp.
34+
function(dist_is_complete dir out_var)
35+
set(${out_var} FALSE PARENT_SCOPE)
36+
if(NOT EXISTS "${dir}/index.html")
37+
return()
38+
endif()
39+
file(GLOB_RECURSE _files RELATIVE "${dir}" "${dir}/*")
40+
set(_have_loading FALSE)
41+
set(_have_manifest FALSE)
42+
set(_have_sw FALSE)
43+
set(_have_build FALSE)
44+
set(_have_version FALSE)
45+
set(_have_bundle_js FALSE)
46+
set(_have_bundle_css FALSE)
47+
set(_have_workbox FALSE)
48+
foreach(_f ${_files})
49+
get_filename_component(_b "${_f}" NAME)
50+
if(_b STREQUAL "loading.html")
51+
set(_have_loading TRUE)
52+
elseif(_b STREQUAL "manifest.webmanifest")
53+
set(_have_manifest TRUE)
54+
elseif(_b STREQUAL "sw.js")
55+
set(_have_sw TRUE)
56+
elseif(_b STREQUAL "build.json")
57+
set(_have_build TRUE)
58+
elseif(_b STREQUAL "version.json")
59+
set(_have_version TRUE)
60+
elseif(_b MATCHES "^bundle.*\\.js$")
61+
set(_have_bundle_js TRUE)
62+
elseif(_b MATCHES "^bundle.*\\.css$")
63+
set(_have_bundle_css TRUE)
64+
elseif(_b MATCHES "^workbox.*\\.js$")
65+
set(_have_workbox TRUE)
66+
endif()
67+
endforeach()
68+
if(_have_loading AND _have_manifest AND _have_sw AND _have_build AND _have_version
69+
AND _have_bundle_js AND _have_bundle_css AND _have_workbox)
70+
set(${out_var} TRUE PARENT_SCOPE)
71+
endif()
72+
endfunction()
73+
2774
function(npm_build_should_skip out_var)
2875
set(${out_var} FALSE PARENT_SCOPE)
2976

@@ -271,9 +318,15 @@ endfunction()
271318
# 1. Priority 1: pre-built assets supplied in tools/ui/dist
272319
# ---------------------------------------------------------------------------
273320
if(EXISTS "${SRC_DIST_DIR}/index.html")
274-
message(STATUS "UI: using pre-built assets from ${SRC_DIST_DIR}")
275-
emit_files("${SRC_DIST_DIR}")
276-
return()
321+
dist_is_complete("${SRC_DIST_DIR}" SRC_DIST_OK)
322+
if(SRC_DIST_OK)
323+
message(STATUS "UI: using pre-built assets from ${SRC_DIST_DIR}")
324+
emit_files("${SRC_DIST_DIR}")
325+
return()
326+
else()
327+
message(STATUS "UI: ${SRC_DIST_DIR} has index.html but is missing required assets "
328+
"(partial or failed UI build); ignoring it and trying npm/HF instead")
329+
endif()
277330
endif()
278331

279332
# ---------------------------------------------------------------------------
@@ -305,10 +358,7 @@ if(NOT provisioned AND HF_ENABLED)
305358
endif()
306359
endif()
307360

308-
set(have_assets FALSE)
309-
if(EXISTS "${DIST_DIR}/index.html")
310-
set(have_assets TRUE)
311-
endif()
361+
dist_is_complete("${DIST_DIR}" have_assets)
312362
if(stamp_ok AND have_assets)
313363
message(STATUS "UI: HF stamp '${stamped}' matches version, skipping HF fetch")
314364
set(provisioned TRUE)
@@ -328,8 +378,18 @@ endif()
328378
# 4. Fallback: warn about stale or missing assets, then emit whatever we have
329379
# ---------------------------------------------------------------------------
330380
if(NOT provisioned)
331-
if(EXISTS "${DIST_DIR}/index.html")
332-
message(WARNING "UI: provisioning failed; embedding stale assets from ${DIST_DIR}")
381+
dist_is_complete("${DIST_DIR}" DIST_COMPLETE)
382+
if(DIST_COMPLETE)
383+
message(WARNING "UI: provisioning failed; embedding stale (but complete) assets from ${DIST_DIR}")
384+
elseif(EXISTS "${DIST_DIR}/index.html")
385+
# A partial dist would make llama-ui-embed abort the build. Drop it so we
386+
# degrade to a no-embedded-UI binary with a clear message instead.
387+
message(WARNING "UI: provisioning failed and ${DIST_DIR} is incomplete; "
388+
"building WITHOUT an embedded UI. For an offline build, extract a "
389+
"complete pre-built UI (from a llama.cpp release at "
390+
"https://github.com/ggml-org/llama.cpp/releases) into tools/ui/dist, "
391+
"or configure with -DBUILD_UI=OFF to always use the HF-downloaded UI.")
392+
file(REMOVE_RECURSE "${DIST_DIR}")
333393
else()
334394
message(WARNING "UI: no assets available - building without an embedded UI. "
335395
"In a disconnected environment, download the pre-built UI "

0 commit comments

Comments
 (0)