|
| 1 | +# SPDX-License-Identifier: MIT |
| 2 | +# |
| 3 | +# apply-llama-patches.cmake — applies every patch in the repo-root `patches/` directory to the |
| 4 | +# llama.cpp source tree fetched by FetchContent. Wired as the llama.cpp `PATCH_COMMAND` in the |
| 5 | +# top-level CMakeLists.txt, so it runs for EVERY C++ build (all CI jobs + local) from one place, |
| 6 | +# rather than per-build-step. |
| 7 | +# |
| 8 | +# Design: |
| 9 | +# * Cross-platform: invoked via `cmake -P`, so it behaves identically on Linux, macOS and |
| 10 | +# Windows (the dockcross/native/MSVC jobs all call the same code path). |
| 11 | +# * Every `patches/*.patch` and `patches/*.diff` is applied, sorted by filename (so a numeric |
| 12 | +# prefix like 0001-, 0002- defines a deterministic order). |
| 13 | +# * Idempotent: `git apply --reverse --check` detects an already-applied patch and skips it, so |
| 14 | +# a CMake reconfigure over an already-patched source tree does not fail. |
| 15 | +# * Fail-loud: a patch that no longer applies (e.g. after a llama.cpp version bump shifts the |
| 16 | +# context) aborts the configure with a clear message, so a stale patch can never be silently |
| 17 | +# dropped from a release build. |
| 18 | +# |
| 19 | +# Invoked as: |
| 20 | +# cmake -DPATCH_DIR=<repo>/patches -DLLAMA_SRC=<fetched-src> -P cmake/apply-llama-patches.cmake |
| 21 | + |
| 22 | +if(NOT DEFINED PATCH_DIR OR NOT DEFINED LLAMA_SRC) |
| 23 | + message(FATAL_ERROR "apply-llama-patches: both PATCH_DIR and LLAMA_SRC must be defined") |
| 24 | +endif() |
| 25 | + |
| 26 | +find_program(GIT_EXECUTABLE NAMES git) |
| 27 | +if(NOT GIT_EXECUTABLE) |
| 28 | + message(FATAL_ERROR "apply-llama-patches: 'git' not found on PATH (required to apply patches)") |
| 29 | +endif() |
| 30 | + |
| 31 | +file(GLOB patch_files "${PATCH_DIR}/*.patch" "${PATCH_DIR}/*.diff") |
| 32 | +list(SORT patch_files) |
| 33 | + |
| 34 | +if(NOT patch_files) |
| 35 | + message(STATUS "apply-llama-patches: no patches in ${PATCH_DIR} (nothing to apply)") |
| 36 | + return() |
| 37 | +endif() |
| 38 | + |
| 39 | +foreach(patch IN LISTS patch_files) |
| 40 | + get_filename_component(patch_name "${patch}" NAME) |
| 41 | + |
| 42 | + # Already applied? A successful reverse-apply check means the change is present already. |
| 43 | + execute_process( |
| 44 | + COMMAND "${GIT_EXECUTABLE}" -C "${LLAMA_SRC}" apply --reverse --check "${patch}" |
| 45 | + RESULT_VARIABLE reverse_rc |
| 46 | + OUTPUT_QUIET ERROR_QUIET) |
| 47 | + if(reverse_rc EQUAL 0) |
| 48 | + message(STATUS "apply-llama-patches: ${patch_name} already applied — skipping") |
| 49 | + continue() |
| 50 | + endif() |
| 51 | + |
| 52 | + # Not applied yet — confirm it applies cleanly before touching the tree. |
| 53 | + execute_process( |
| 54 | + COMMAND "${GIT_EXECUTABLE}" -C "${LLAMA_SRC}" apply --check "${patch}" |
| 55 | + RESULT_VARIABLE check_rc |
| 56 | + OUTPUT_QUIET ERROR_QUIET) |
| 57 | + if(NOT check_rc EQUAL 0) |
| 58 | + message(FATAL_ERROR |
| 59 | + "apply-llama-patches: ${patch_name} does not apply cleanly to ${LLAMA_SRC}.\n" |
| 60 | + " A llama.cpp version bump probably shifted the patched code — refresh the patch " |
| 61 | + "against the new source and recommit it.") |
| 62 | + endif() |
| 63 | + |
| 64 | + execute_process( |
| 65 | + COMMAND "${GIT_EXECUTABLE}" -C "${LLAMA_SRC}" apply "${patch}" |
| 66 | + RESULT_VARIABLE apply_rc) |
| 67 | + if(NOT apply_rc EQUAL 0) |
| 68 | + message(FATAL_ERROR "apply-llama-patches: failed to apply ${patch_name}") |
| 69 | + endif() |
| 70 | + message(STATUS "apply-llama-patches: applied ${patch_name}") |
| 71 | +endforeach() |
0 commit comments