CXX_STD = CXX17

# Get ggmlR paths
GGMLR_INCLUDE = $(shell "$(R_HOME)/bin/Rscript" -e "cat(system.file('include', package='ggmlR'))")
GGMLR_LIB = $(shell "$(R_HOME)/bin/Rscript" -e "cat(system.file('lib', package='ggmlR'))")

# Include paths. All vendored headers are included with directory prefixes
# ("jinja/...", "nlohmann/...") so a single -I. resolves them; we deliberately
# avoid -Ijinja, which would shadow libc's <string.h> with jinja/string.h.
PKG_CPPFLAGS = -I. -I$(GGMLR_INCLUDE) -DGGML_USE_CPU

# Compiler flags
PKG_CXXFLAGS = @OPENMP_CXXFLAGS@

# Link with ggmlR static library
PKG_LIBS = -L$(GGMLR_LIB) -lggml @OPENMP_CXXFLAGS@ @VULKAN_LIBS@ -lpthread -lm

# llama.cpp sources
SOURCES_CPP = \
  llama.cpp \
  llama-adapter.cpp \
  llama-arch.cpp \
  llama-batch.cpp \
  llama-chat.cpp \
  llama-context.cpp \
  llama-cparams.cpp \
  llama-grammar.cpp \
  llama-graph.cpp \
  llama-hparams.cpp \
  llama-impl.cpp \
  llama-io.cpp \
  llama-kv-cache.cpp \
  llama-kv-cache-iswa.cpp \
  llama-memory.cpp \
  llama-memory-hybrid.cpp \
  llama-memory-hybrid-iswa.cpp \
  llama-memory-recurrent.cpp \
  llama-mmap.cpp \
  llama-model.cpp \
  llama-model-loader.cpp \
  llama-model-saver.cpp \
  llama-quant.cpp \
  llama-sampling.cpp \
  llama-vocab.cpp \
  unicode.cpp \
  unicode-data.cpp \
  r_llama_interface.cpp \
  r_chat_interface.cpp \
  r_mtmd_interface.cpp

# Vendored common/ chat + template layer (tool-aware chat templates and
# tool-call parsing — the common_chat_templates_apply / common_chat_parse
# closure from llama.cpp's common/). common_chat_support.cpp is a trimmed
# slice of common.cpp (string helpers + common_token_to_piece only).
CHAT_CPP = \
  chat.cpp \
  chat-parser.cpp \
  chat-parser-xml-toolcall.cpp \
  chat-peg-parser.cpp \
  peg-parser.cpp \
  common-unicode.cpp \
  json-partial.cpp \
  json-schema-to-grammar.cpp \
  regex-partial.cpp \
  log.cpp \
  build-info.cpp \
  common_chat_support.cpp

# Jinja template engine (vendored from common/jinja/)
JINJA_CPP = $(wildcard jinja/*.cpp)

# Model implementations
MODELS_CPP = $(wildcard models/*.cpp)

# Multimodal (vision) subsystem — vendored from llama.cpp master tools/mtmd/.
# clip ViT/projector engine + mtmd dispatcher + per-encoder graphs (mtmd/models/).
# Mirrors the upstream layout so include paths inside these files need no edits;
# GCC resolves "..." includes relative to each file's own directory. The header-
# only image decoder lives in vendor/stb/. Audio (miniaudio) is compiled out by
# default (see mtmd-helper.cpp / LLAMAR_ENABLE_AUDIO). mtmd-debug.cpp (a CLI
# utility pulling common/arg/log) is intentionally NOT compiled — the
# mtmd_debug_* symbols it declares are defined inside mtmd.cpp.
MTMD_CPP = $(wildcard mtmd/*.cpp mtmd/models/*.cpp)

OBJECTS = $(SOURCES_CPP:.cpp=.o) $(CHAT_CPP:.cpp=.o) $(JINJA_CPP:.cpp=.o) $(MODELS_CPP:.cpp=.o) $(MTMD_CPP:.cpp=.o)

# Force include R compatibility header for files using stderr/stdout
# This redirects fprintf(stderr,...) to REprintf(...) for CRAN compliance
llama-grammar.o: PKG_CPPFLAGS += -include r_llama_compat.h
llama-impl.o: PKG_CPPFLAGS += -include r_llama_compat.h
llama-quant.o: PKG_CPPFLAGS += -include r_llama_compat.h
unicode.o: PKG_CPPFLAGS += -include r_llama_compat.h
json-partial.o: PKG_CPPFLAGS += -include r_llama_compat.h
json-schema-to-grammar.o: PKG_CPPFLAGS += -include r_llama_compat.h
log.o: PKG_CPPFLAGS += -include r_llama_compat.h

# jinja + mtmd objects leak stderr/stdout/__printf_chk symbols (R CMD check
# flags these as non-portable); force-include the redirect header so they go
# through REprintf. Comes after the -Imtmd rule below via append.
$(JINJA_CPP:.cpp=.o): PKG_CPPFLAGS += -include r_llama_compat.h

# mtmd objects need -Imtmd so cross-includes like debug/mtmd-debug.h -> "mtmd.h"
# resolve (upstream builds tools/mtmd with -Itools/mtmd). -Ivendor mirrors how
# upstream resolves the vendored single-header "stb/stb_image.h" from src/vendor/
# (= upstream's vendor/). Scoped to mtmd objects only; the core engine does not
# include any mtmd/clip headers, so this cannot shadow core headers. NB: we
# deliberately do NOT add -Imtmd/models globally — that would let our
# src/models/*.cpp pick up mtmd/models/models.h.
$(MTMD_CPP:.cpp=.o): PKG_CPPFLAGS += -Imtmd -Ivendor

# Force the stderr/stdout redirect on the mtmd C++ objects (clip/mtmd leak those
# symbols). mtmd-helper.o is deliberately excluded: it compiles miniaudio inline
# via MINIAUDIO_IMPLEMENTATION, and overriding exit/fprintf/stderr there could
# break that vendored C code — it calls REprintf explicitly instead.
MTMD_COMPAT_OBJ = $(filter-out mtmd/mtmd-helper.o, $(MTMD_CPP:.cpp=.o))
$(MTMD_COMPAT_OBJ): PKG_CPPFLAGS += -include r_llama_compat.h

# The R<->mtmd bridge includes mtmd.h / mtmd-helper.h from src/mtmd/.
r_mtmd_interface.o: PKG_CPPFLAGS += -Imtmd
