|
| 1 | +cmake_minimum_required(VERSION 3.20) |
| 2 | +project(llamadart_webgpu_bridge C CXX) |
| 3 | + |
| 4 | +if (NOT EMSCRIPTEN) |
| 5 | + message(FATAL_ERROR "This project must be configured with emcmake/emcc") |
| 6 | +endif() |
| 7 | + |
| 8 | +if (NOT DEFINED LLAMA_CPP_DIR) |
| 9 | + set(LLAMA_CPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/llama_cpp") |
| 10 | +endif() |
| 11 | + |
| 12 | +if (NOT EXISTS "${LLAMA_CPP_DIR}/CMakeLists.txt") |
| 13 | + message(FATAL_ERROR "LLAMA_CPP_DIR is invalid: ${LLAMA_CPP_DIR}") |
| 14 | +endif() |
| 15 | + |
| 16 | +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/artifacts") |
| 17 | + |
| 18 | +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) |
| 19 | + |
| 20 | +set(LLAMA_BUILD_COMMON OFF CACHE BOOL "" FORCE) |
| 21 | +set(LLAMA_BUILD_TESTS OFF CACHE BOOL "" FORCE) |
| 22 | +set(LLAMA_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) |
| 23 | +set(LLAMA_BUILD_SERVER OFF CACHE BOOL "" FORCE) |
| 24 | +set(LLAMA_BUILD_TOOLS OFF CACHE BOOL "" FORCE) |
| 25 | +set(LLAMA_HTTPLIB OFF CACHE BOOL "" FORCE) |
| 26 | +set(LLAMA_OPENSSL OFF CACHE BOOL "" FORCE) |
| 27 | +set(LLAMA_BUILD_HTML OFF CACHE BOOL "" FORCE) |
| 28 | +set(LLAMA_WASM_SINGLE_FILE OFF CACHE BOOL "" FORCE) |
| 29 | + |
| 30 | +set(GGML_NATIVE OFF CACHE BOOL "" FORCE) |
| 31 | +set(GGML_OPENMP OFF CACHE BOOL "" FORCE) |
| 32 | +set(GGML_WEBGPU ON CACHE BOOL "" FORCE) |
| 33 | +set(GGML_VULKAN OFF CACHE BOOL "" FORCE) |
| 34 | +set(GGML_METAL OFF CACHE BOOL "" FORCE) |
| 35 | +set(GGML_BLAS OFF CACHE BOOL "" FORCE) |
| 36 | + |
| 37 | +add_subdirectory("${LLAMA_CPP_DIR}" "${CMAKE_BINARY_DIR}/llama_cpp") |
| 38 | + |
| 39 | +find_package(Threads REQUIRED) |
| 40 | + |
| 41 | +set(MTMD_AUDIO_SRC "${LLAMA_CPP_DIR}/tools/mtmd/mtmd-audio.cpp") |
| 42 | +set(MTMD_AUDIO_PATCHED "${CMAKE_BINARY_DIR}/generated/mtmd-audio-single-thread.cpp") |
| 43 | + |
| 44 | +file(READ "${MTMD_AUDIO_SRC}" MTMD_AUDIO_CONTENT) |
| 45 | +string(FIND "${MTMD_AUDIO_CONTENT}" "4, // n_threads" MTMD_AUDIO_THREAD_MARKER_INDEX) |
| 46 | +if (MTMD_AUDIO_THREAD_MARKER_INDEX EQUAL -1) |
| 47 | + message(FATAL_ERROR "mtmd-audio.cpp thread marker not found; update single-thread wasm patch") |
| 48 | +endif() |
| 49 | +string(REPLACE |
| 50 | + "4, // n_threads" |
| 51 | + "1, // n_threads (patched for single-threaded wasm)" |
| 52 | + MTMD_AUDIO_CONTENT |
| 53 | + "${MTMD_AUDIO_CONTENT}") |
| 54 | +file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/generated") |
| 55 | +file(WRITE "${MTMD_AUDIO_PATCHED}" "${MTMD_AUDIO_CONTENT}") |
| 56 | + |
| 57 | +add_library(llamadart_mtmd STATIC |
| 58 | + "${LLAMA_CPP_DIR}/tools/mtmd/mtmd.cpp" |
| 59 | + "${MTMD_AUDIO_PATCHED}" |
| 60 | + "${LLAMA_CPP_DIR}/tools/mtmd/mtmd-helper.cpp" |
| 61 | + "${LLAMA_CPP_DIR}/tools/mtmd/clip.cpp" |
| 62 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/cogvlm.cpp" |
| 63 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/conformer.cpp" |
| 64 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/glm4v.cpp" |
| 65 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/internvl.cpp" |
| 66 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/kimivl.cpp" |
| 67 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/kimik25.cpp" |
| 68 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/llama4.cpp" |
| 69 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/llava.cpp" |
| 70 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/minicpmv.cpp" |
| 71 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/pixtral.cpp" |
| 72 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/qwen2vl.cpp" |
| 73 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/qwen3vl.cpp" |
| 74 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/siglip.cpp" |
| 75 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/whisper-enc.cpp" |
| 76 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/mobilenetv5.cpp" |
| 77 | + "${LLAMA_CPP_DIR}/tools/mtmd/models/youtuvl.cpp" |
| 78 | +) |
| 79 | + |
| 80 | +target_compile_features(llamadart_mtmd PRIVATE cxx_std_17) |
| 81 | +target_compile_options(llamadart_mtmd PRIVATE |
| 82 | + "-sMEMORY64=1" |
| 83 | +) |
| 84 | +target_include_directories(llamadart_mtmd PRIVATE |
| 85 | + "${LLAMA_CPP_DIR}/tools/mtmd" |
| 86 | + "${LLAMA_CPP_DIR}" |
| 87 | + "${LLAMA_CPP_DIR}/vendor" |
| 88 | +) |
| 89 | +target_link_libraries(llamadart_mtmd PRIVATE ggml llama Threads::Threads) |
| 90 | + |
| 91 | +if (NOT MSVC) |
| 92 | + target_compile_options(llamadart_mtmd PRIVATE -Wno-cast-qual) |
| 93 | +endif() |
| 94 | + |
| 95 | +add_executable(llama_webgpu_core src/llama_webgpu_core.cpp) |
| 96 | + |
| 97 | +target_compile_features(llama_webgpu_core PRIVATE cxx_std_17) |
| 98 | + |
| 99 | +target_compile_options(llama_webgpu_core PRIVATE |
| 100 | + "-sMEMORY64=1" |
| 101 | +) |
| 102 | + |
| 103 | +target_include_directories(llama_webgpu_core PRIVATE |
| 104 | + "${LLAMA_CPP_DIR}/include" |
| 105 | + "${LLAMA_CPP_DIR}/ggml/include" |
| 106 | + "${LLAMA_CPP_DIR}/tools/mtmd" |
| 107 | +) |
| 108 | + |
| 109 | +target_link_libraries(llama_webgpu_core PRIVATE llama llamadart_mtmd) |
| 110 | + |
| 111 | +target_link_options(llama_webgpu_core PRIVATE |
| 112 | + "-sMEMORY64=1" |
| 113 | + "-sALLOW_MEMORY_GROWTH=1" |
| 114 | + "-sASSERTIONS=1" |
| 115 | + "-sJSPI=1" |
| 116 | + "-sJSPI_EXPORTS=['llamadart_webgpu_probe','llamadart_webgpu_load_model','llamadart_webgpu_mmproj_load','llamadart_webgpu_tokenize_to_json','llamadart_webgpu_detokenize_from_json','llamadart_webgpu_generate','llamadart_webgpu_begin_generation','llamadart_webgpu_next_token','llamadart_webgpu_shutdown']" |
| 117 | + "-sMODULARIZE=1" |
| 118 | + "-sEXPORT_ES6=1" |
| 119 | + "-sEXPORT_NAME=createLlamaWebGpuCoreModule" |
| 120 | + "-sENVIRONMENT=web,worker" |
| 121 | + "-sEXPORTED_RUNTIME_METHODS=['FS','ccall','UTF8ToString']" |
| 122 | + "-sEXPORTED_FUNCTIONS=['_main','_llamadart_webgpu_probe','_llamadart_webgpu_backends_json','_llamadart_webgpu_last_error','_llamadart_webgpu_load_model','_llamadart_webgpu_mmproj_load','_llamadart_webgpu_mmproj_free','_llamadart_webgpu_mmproj_supports_vision','_llamadart_webgpu_mmproj_supports_audio','_llamadart_webgpu_media_clear_pending','_llamadart_webgpu_media_add_file','_llamadart_webgpu_media_add_encoded','_llamadart_webgpu_media_add_rgb','_llamadart_webgpu_media_add_audio_f32','_llamadart_webgpu_tokenize_to_json','_llamadart_webgpu_last_tokens_json','_llamadart_webgpu_detokenize_from_json','_llamadart_webgpu_last_detokenized','_llamadart_webgpu_generate','_llamadart_webgpu_begin_generation','_llamadart_webgpu_next_token','_llamadart_webgpu_last_piece','_llamadart_webgpu_end_generation','_llamadart_webgpu_request_cancel','_llamadart_webgpu_last_output','_llamadart_webgpu_get_context_size','_llamadart_webgpu_model_meta_json','_llamadart_webgpu_shutdown']" |
| 123 | +) |
| 124 | + |
| 125 | +set_target_properties(llama_webgpu_core PROPERTIES |
| 126 | + OUTPUT_NAME "llama_webgpu_core" |
| 127 | + SUFFIX ".js" |
| 128 | +) |
0 commit comments