Auto-download + compile Plover dict during build

CMake configure:
1. Check for pre-compiled dicts/steno_dict.bin (or JAVELIN_DICT_BIN)
2. If missing, download Plover main.json from openstenoproject/plover
3. Run compile_dict.py to produce JSC4 binary
4. Embed via dict_embed.S

Downloaded JSON cached in dicts_src/ — persists across builds via
GH Actions west module cache. Only re-downloads if cache evicted.
This commit is contained in:
afiqzudinhadi 2026-06-23 00:47:15 +08:00
parent 3e4b5a56b0
commit 6eef6d7006
2 changed files with 56 additions and 9 deletions

2
.gitignore vendored
View file

@ -1 +1,3 @@
__pycache__/ __pycache__/
dicts_src/
dicts/*.bin

View file

@ -249,17 +249,62 @@ print(f'Stripped test blocks from {count} files')
${ZMK_BEHAVIOR_SRC} ${ZMK_BEHAVIOR_SRC}
) )
# Dictionary binary embedding. # --- Dictionary binary embedding ---
# Users place compiled dict at dicts/steno_dict.bin (or set # Priority: 1) JAVELIN_DICT_BIN cmake var
# JAVELIN_DICT_BIN via CMake cache / corne.conf extra args). # 2) pre-compiled dicts/steno_dict.bin
# If no dict found, a null placeholder is embedded and engine # 3) auto-download Plover dict + compile
# logs a warning at boot. # 4) null placeholder (engine won't start)
set(DICT_DIR "${CMAKE_CURRENT_LIST_DIR}/dicts")
set(DICT_SRC_DIR "${CMAKE_CURRENT_LIST_DIR}/dicts_src")
set(COMPILER "${CMAKE_CURRENT_LIST_DIR}/tools/dict_compiler/compile_dict.py")
set(DICT_BIN "${DICT_DIR}/steno_dict.bin")
if(DEFINED JAVELIN_DICT_BIN) if(DEFINED JAVELIN_DICT_BIN)
set(DICT_BIN_PATH "${JAVELIN_DICT_BIN}") set(DICT_BIN_PATH "${JAVELIN_DICT_BIN}")
elseif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/dicts/steno_dict.bin") elseif(EXISTS "${DICT_BIN}")
set(DICT_BIN_PATH "${CMAKE_CURRENT_LIST_DIR}/dicts/steno_dict.bin") set(DICT_BIN_PATH "${DICT_BIN}")
else() else()
set(DICT_BIN_PATH "") # Auto-download + compile if no pre-built binary exists
set(PLOVER_JSON "${DICT_SRC_DIR}/plover-main.json")
set(PLOVER_URL "https://raw.githubusercontent.com/openstenoproject/plover/main/plover/assets/main.json")
if(NOT EXISTS "${PLOVER_JSON}")
message(STATUS "Javelin steno: downloading Plover dictionary...")
file(MAKE_DIRECTORY "${DICT_SRC_DIR}")
file(DOWNLOAD "${PLOVER_URL}" "${PLOVER_JSON}"
STATUS DOWNLOAD_STATUS
TIMEOUT 30
)
list(GET DOWNLOAD_STATUS 0 DOWNLOAD_RC)
if(NOT DOWNLOAD_RC EQUAL 0)
message(WARNING "Javelin steno: dict download failed (rc=${DOWNLOAD_RC})")
file(REMOVE "${PLOVER_JSON}")
else()
message(STATUS "Javelin steno: downloaded Plover dictionary")
endif()
else()
message(STATUS "Javelin steno: using cached Plover dictionary")
endif()
if(EXISTS "${PLOVER_JSON}" AND EXISTS "${COMPILER}")
message(STATUS "Javelin steno: compiling dictionary...")
execute_process(
COMMAND python3 "${COMPILER}" "${PLOVER_JSON}"
-n plover-main -o "${DICT_BIN}"
RESULT_VARIABLE COMPILE_RC
ERROR_VARIABLE COMPILE_ERR
)
if(COMPILE_RC EQUAL 0)
set(DICT_BIN_PATH "${DICT_BIN}")
message(STATUS "Javelin steno: dictionary compiled")
else()
message(WARNING "Javelin steno: dict compile failed: ${COMPILE_ERR}")
set(DICT_BIN_PATH "")
endif()
else()
set(DICT_BIN_PATH "")
endif()
endif() endif()
if(NOT "${DICT_BIN_PATH}" STREQUAL "") if(NOT "${DICT_BIN_PATH}" STREQUAL "")
@ -268,7 +313,7 @@ print(f'Stripped test blocks from {count} files')
) )
message(STATUS "Javelin steno: embedding dictionary from ${DICT_BIN_PATH}") message(STATUS "Javelin steno: embedding dictionary from ${DICT_BIN_PATH}")
else() else()
message(WARNING "Javelin steno: no dictionary binary found — engine will not start") message(WARNING "Javelin steno: no dictionary — engine will not start")
endif() endif()
target_sources(app PRIVATE src/dict_embed.S) target_sources(app PRIVATE src/dict_embed.S)