# Using ggmlR as a Backend in Your Package

ggmlR exports a static library (`libggml.a`) and C headers so downstream packages can link against ggml directly — the same pattern used by `llamaR` (LLM inference) and `sd2R` (Stable Diffusion).

## 1. What ggmlR exports

After installing ggmlR you will find:

    $(R_HOME_DIR)/library/ggmlR/lib/libggml.a
    $(R_HOME_DIR)/library/ggmlR/include/ggml.h
    $(R_HOME_DIR)/library/ggmlR/include/ggml-backend.h
    $(R_HOME_DIR)/library/ggmlR/include/ggml-alloc.h
    $(R_HOME_DIR)/library/ggmlR/include/ggml-opt.h
    $(R_HOME_DIR)/library/ggmlR/include/ggml-quants.h
    $(R_HOME_DIR)/library/ggmlR/include/ggml-vulkan.h
    $(R_HOME_DIR)/library/ggmlR/include/r_ggml_compat.h
    ... (full list in inst/include/)

`r_ggml_compat.h` redirects `printf`/`fprintf`/`abort` to R-safe equivalents (`Rprintf`, `Rf_error`). Always include it (or use `-include r_ggml_compat.h`) in your C/C++ sources.

## 2. DESCRIPTION

Add ggmlR to `LinkingTo` and `Imports`:

    Package: myPackage
    ...
    Imports:   ggmlR
    LinkingTo: ggmlR

`LinkingTo` makes R add `ggmlR/include` to the compiler include path automatically.

## 3. `src/Makevars`

Link against the static library:

    GGMLR_LIB = $(shell Rscript -e "cat(system.file('lib', package='ggmlR'))")
    GGMLR_INC = $(shell Rscript -e "cat(system.file('include', package='ggmlR'))")

    PKG_CPPFLAGS = -I$(GGMLR_INC) -include r_ggml_compat.h
    PKG_LIBS     = $(GGMLR_LIB)/libggml.a

If ggmlR was built with Vulkan you also need to link Vulkan:

    # detect Vulkan (same logic as ggmlR's own configure)
    VULKAN_LIBS = $(shell pkg-config --libs vulkan 2>/dev/null)
    PKG_LIBS    = $(GGMLR_LIB)/libggml.a $(VULKAN_LIBS)

## 4. `configure` — detect ggmlR at build time

    #!/bin/sh
    # configure

    GGMLR_INC=$(Rscript -e "cat(system.file('include', package='ggmlR'))" 2>/dev/null)
    GGMLR_LIB=$(Rscript -e "cat(system.file('lib',     package='ggmlR'))" 2>/dev/null)

    if [ -z "$GGMLR_INC" ] || [ ! -f "$GGMLR_LIB/libggml.a" ]; then
      echo "ERROR: ggmlR not found. Install it first: install.packages('ggmlR')" >&2
      exit 1
    fi

    sed -e "s|@GGMLR_INC@|$GGMLR_INC|g" \
        -e "s|@GGMLR_LIB@|$GGMLR_LIB|g" \
        src/Makevars.in > src/Makevars

`src/Makevars.in`:

    PKG_CPPFLAGS = -I@GGMLR_INC@ -include r_ggml_compat.h
    PKG_LIBS     = @GGMLR_LIB@/libggml.a

## 5. C code — minimal example

    /* src/my_model.c */
    #include "ggml.h"
    #include "ggml-backend.h"
    #include <R.h>
    #include <Rinternals.h>

    SEXP R_my_inference(SEXP r_input) {
        struct ggml_init_params params = {
            .mem_size   = 256 * 1024 * 1024,  /* 256 MB */
            .mem_buffer = NULL,
            .no_alloc   = false,
        };
        struct ggml_context *ctx = ggml_init(params);

        int n = length(r_input);
        struct ggml_tensor *x = ggml_new_tensor_1d(ctx, GGML_TYPE_F32, n);
        memcpy(x->data, REAL(r_input), n * sizeof(float));

        /* ... build graph, compute ... */

        ggml_free(ctx);
        return R_NilValue;
    }

Register in the `.Call` table (R’s standard routine registration):

    /* src/init.c */
    #include <R.h>
    #include <Rinternals.h>
    #include <R_ext/Rdynload.h>

    extern SEXP R_my_inference(SEXP);

    static const R_CallMethodDef CallEntries[] = {
        {"R_my_inference", (DL_FUNC) &R_my_inference, 1},
        {NULL, NULL, 0}
    };

    void R_init_myPackage(DllInfo *dll) {
        R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
        R_useDynamicSymbols(dll, FALSE);
    }

## 6. R wrapper

    my_inference <- function(input) {
      .Call("R_my_inference", as.numeric(input))
    }

## 7. Thread count

ggmlR manages the CPU thread count via `ggmlR_get_n_threads()` (exported from `r_interface.c`). If your package calls `ggml_backend_cpu_init()` directly, set the thread count to match:

    #include "ggml-backend.h"
    /* ggmlR_get_n_threads() is exported by ggmlR — link against libggml.a */
    extern int ggmlR_get_n_threads(void);

    ggml_backend_t cpu = ggml_backend_cpu_init();
    ggml_backend_cpu_set_n_threads(cpu, ggmlR_get_n_threads());

This ensures your package respects the same thread limit as ggmlR (important for CRAN compliance — tests must not exceed 2 threads).

## 8. Vulkan in downstream packages

If your package needs Vulkan, the Vulkan backend is already compiled into `libggml.a` when ggmlR was built with Vulkan support. You only need to link `-lvulkan`:

    VULKAN_LIBS = $(shell pkg-config --libs vulkan 2>/dev/null)
    PKG_LIBS    = @GGMLR_LIB@/libggml.a $(VULKAN_LIBS)

Do not vendor ggml source again — link the pre-built `libggml.a` from ggmlR to avoid symbol collisions.

## 9. Real-world references

- `llamaR` — LLM inference (LLaMA, Mistral, …) using ggmlR as backend
- `sd2R` — Stable Diffusion image generation using ggmlR as backend

Both follow the pattern above: `LinkingTo: ggmlR`, `configure` script to locate headers and `libggml.a`, thin C wrappers, R `.Call` interface.