Note
Self-contained GDAL runtime tooling for Windows.
gdalraster.windows is an R package with companion CI scripts that build and
publish a Windows GDAL runtime bundle.
The package helps you:
- install that runtime locally
- build
gdalrasterfrom source against it - load and verify
gdalrasterin a Windows session
By default, installs are isolated under package-managed user directories.
Full documentation is available at docs.jimbrig.com/gdalraster.windows.
Latest GDAL runtime release: gdal-v3.13.1
- Windows with R installed
- Rtools matching your R version —
install_gdalraster()compiles gdalraster from source against the bundled GDAL, which is the one step the prebuilt runtime cannot eliminate (the function checks for a toolchain up front and tells you if one is missing)
pak::pak("jimbrig/gdalraster.windows")# 1) install runtime bundle (defaults to latest release asset)
gdalraster.windows::install_gdal_runtime()
# 2) build gdalraster from source against that runtime
gdalraster.windows::install_gdalraster()
# 3) load and verify
library(gdalraster.windows)
gdalraster::gdal_global_reg_names()install_gdal_runtime() downloads the runtime bundle from GitHub Releases by
default. On machines without network access (or to pin an exact asset), pass a
local zip directly:
# 1) download the release asset on a connected machine:
# https://github.com/jimbrig/gdalraster.windows/releases
# 2) transfer to the target machine
# 3) install from the local zip
gdalraster.windows::install_gdal_runtime(
local_zip = "C:/Downloads/gdal-ucrt64-v3.13.1-windows-x64.zip"
)A fallback_zip argument is also supported: when a release download fails and
a fallback zip exists, it is installed instead.
If runtime and custom gdalraster install are already present:
library(gdalraster.windows)
library(gdalraster)
gdalraster::gdal_global_reg_names()Explicit load flow is also supported:
gdalraster.windows::load_gdal_dll()
gdalraster.windows::load_gdalraster()
gdalraster::gdal_global_reg_names()Runtime verification helper:
gdalraster.windows::verify_gdalraster_runtime()- An R helper package (
gdalraster.windows) - A Windows CI build pipeline for GDAL
(
.github/workflows/build.yml) - Build and bundle scripts:
The package and build scripts are designed to work together.
The runtime bundle is reproducible entirely from this repository. To build
and publish a new GDAL release, push a tag (or dispatch the workflow with a
gdal_version input):
git tag gdal-v3.14.0 && git push origin gdal-v3.14.0The tag drives the GDAL source checkout, cache key, asset name, and release tag. See the Architecture article for the full procedure, including local (non-CI) reproduction.
# writes a managed hook block that loads the GDAL DLL and prepends
# the custom gdalraster library path at session startup
gdalraster.windows::add_gdal_rprofile_hook()This repository started from practical Windows failures where
gdalraster::gdal_global_reg_names() could be empty under some toolchain
states. It now provides a maintained runtime path that is isolated by default.
This section is the technical rationale for the current design.
GDAL's Algorithm API uses static C++ registration. Under some Windows build
states (notably specific Rtools/MXE combinations), the top-level algorithm
registry has been observed to load but return no names. In practice this means
gdalraster::gdal_global_reg_names() can return character(0) even when GDAL
is present.
This project solves that by controlling both the GDAL build profile and runtime
loading path, then rebuilding gdalraster against that known runtime.
- MinGW-w64: GCC-based Windows compiler
toolchain for native
.exe/.dll. - MSYS2: package manager + shell environment
used to assemble toolchains and dependencies (
pacman). - UCRT64: MSYS2 toolchain target using Microsoft's Universal CRT.
- Rtools45: Windows R package build toolchain, also UCRT-based.
The practical requirement is to keep compile/runtime toolchains compatible (MinGW/UCRT alignment) to avoid C/C++ runtime and ABI mismatch problems.
- Some runtime pieces are linked statically (for portability of GCC runtime bits).
- GDAL itself is delivered as a shared runtime DLL (
libgdal-*.dll) with transitive dependencies bundled alongside it.
In other words: this project is not "single-file static GDAL", it is a self-contained runtime bundle with controlled dependency closure.
gdalraster binds to GDAL C++ APIs via compiled code. Even when headers match,
ABI mismatches can break at runtime if binaries are built with incompatible
compiler/runtime combinations.
That is why this package installs gdalraster from source against the bundled
GDAL headers/import libs rather than assuming an arbitrary prebuilt binary is
compatible.
Current build uses flags in
tools/build_gdal.sh,
including:
-DGDAL_USE_MUPARSER=ONfor muparser-enabled algorithm functionality-DGDAL_HIDE_INTERNAL_SYMBOLS=ONto reduce export-surface pressure on Windows-Wl,--kill-atfor Windows/MinGW export naming behavior-static-libgcc -static-libstdc++and staticwinpthreadhandling to reduce external runtime fragility
These flags are practical stability choices from observed Windows build/runtime behavior, not arbitrary tuning.
Building libgdal-*.dll is not sufficient by itself. Runtime success depends on
all non-Windows transitive DLL dependencies being present.
tools/collect_dlls.sh
performs recursive dependency inspection with
ntldd (ntldd -R), copies required UCRT64
DLLs into the bundle, and fails when unresolved external non-Windows
dependencies remain.
Compile-time link success does not guarantee runtime load success. Windows still
needs to resolve libgdal-*.dll and its dependency tree in the active process.
activate_gdal_runtime() addresses this by:
- prepending bundle
bin/toPATH - setting GDAL/PROJ data env vars
- prepending bundle
python/toPYTHONPATH(see section 9) - optionally preloading
libgdal-*.dllwithdyn.load(..., local = FALSE, now = TRUE)
This is why explicit runtime activation exists in addition to source builds.
GDAL and PROJ require runtime data files (share/gdal, share/proj).
Without these, CRS and related functionality can fail even when DLL loading
succeeds.
activate_gdal_runtime() sets:
GDAL_DATAPROJ_LIBPROJ_DATA
from the installed bundle when available.
Some GDAL CLI algorithms are implemented in Python rather than C++. For
example, gdal driver gpkg validate is a thin C++ entry point in libgdal
that embeds a CPython interpreter at runtime: GDAL locates a python.exe on
PATH, dynamically loads the matching libpython DLL, calls
Py_Initialize(), and imports osgeo_utils.samples.validate_gpkg.
osgeo_utils is the pure-Python package shipped by GDAL's
gdal-utils
distribution (swig/python/gdal-utils/ in the GDAL source tree). Because it
contains no compiled extension modules, it has no CPython ABI coupling — any
embedded interpreter version can import it.
The runtime bundle ships this package under python/osgeo_utils,
version-locked to the built GDAL tag. activate_gdal_runtime() prepends
<gdal_home>/python to PYTHONPATH (session-scoped; never persisted to user
or machine environment) so the embedded interpreter can resolve it.
PYTHONPATH is read at Py_Initialize(), which libgdal triggers lazily on
first use of an embedded-python algorithm, so activation-time configuration is
early enough.
Without this, such algorithms fail with:
GDAL FAILURE 1: ... ModuleNotFoundError: No module named 'osgeo_utils'
Note: the compiled osgeo SWIG bindings (from osgeo import gdal) are
intentionally not built or bundled (BUILD_PYTHON_BINDINGS stays off —
no Python/SWIG in the build environment). They would pin the bundle to a
single CPython version/ABI. The Python-implemented validators degrade
gracefully without them (e.g. validate_gpkg skips only tiled gridded
coverage checks).
These are separate concerns:
- Compile-time: headers/libs via Makevars (
PKG_CPPFLAGS,PKG_LIBS) - Runtime: DLL resolution via process environment and loader state
This package scopes compile-time settings to install calls (withr), then
manages runtime activation separately for session reliability.
For users who want persistence, add_gdal_rprofile_hook() writes a managed
startup block that can load runtime context early in each session.
This is optional by design; default behavior stays non-destructive and local.
- firelab/gdalraster#826 — algorithm-registry failure mode on Windows
- firelab/gdalraster#858 — enabling muparser in the Rtools GDAL build
- firelab/gdalraster#982 — working Windows workflow this package productized
- OSGeo/gdal#13592 — upstream registration fix (GDAL 3.12.2)
- Rtools45 news — muparser added to the Rtools GDAL build in release 6768
- Getting Started — install, load, and verify the full workflow
- Runtime Guide — session activation, configuration, source builds, and startup hooks
- Architecture — why the package exists and how the runtime bundle is built
- Troubleshooting — common failure modes and fixes
- Function reference
Run fast tests:
testthat::test_dir("tests/testthat")Run clean-room isolation checks:
testthat::test_file("tests/testthat/test-e2e-clean-room.R")Run full end-to-end clean-room flow (opt-in):
$env:GDALRASTER_WINDOWS_RUN_E2E="true"
Rscript -e "testthat::test_file('tests/testthat/test-e2e-clean-room.R')"