--- title: "Building the rSPDE package from source on Mac and Linux" author: "David Bolin and Alexandre B. Simas" date: "Created: 2023-01-17. Last modified: `r Sys.Date()`." output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Building the rSPDE package from source on Mac and Linux} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ## Overview Starting with this release of `rSPDE`, the C/C++ `cgeneric` sources used by `INLA` live on a single branch (`devel`) together with the R code, and compilation is **opt-in**. The default install — including the CRAN release and the regular GitHub install — is pure R and requires no compiler. When you opt in, the `configure` script copies the sources from `inst/src-optional/` into `src/` and then `R CMD INSTALL` builds `inst/shared/rspde_cgeneric_models.so` (or `.dll` on Windows). At runtime `rSPDE` detects this shared object and uses it directly; otherwise it falls back to the shared object that ships with `INLA`. The legacy `devel-src` and `stable-src` branches are deprecated. ## Asking for the compiled build Pick one of the following — both have the same effect: ```{r, eval=FALSE} # Via configure args remotes::install_github( "davidbolin/rSPDE", ref = "devel", configure.args = "--enable-compiled" ) ``` ```{r, eval=FALSE} # Via an environment variable withr::with_envvar( c(RSPDE_COMPILE = "1"), remotes::install_github("davidbolin/rSPDE", ref = "devel") ) ``` Without the flag (or `RSPDE_COMPILE=1`), `configure` writes a no-op `Makevars` and the install stays pure R. If you have already cloned the repository and want to build locally: ```{bash, eval=FALSE} git clone https://github.com/davidbolin/rSPDE.git cd rSPDE RSPDE_COMPILE=1 R CMD INSTALL . ``` You can verify the compiled path is active from R with: ```{r, eval=FALSE} getOption("rspde.compiled") # TRUE when the local shared object is loaded ``` ## Toolchain prerequisites The `Makefile` shipped in `inst/src-optional/` is the same one that used to live on `devel-src`. It expects: - **Eigen** headers (the `cgeneric` C++ helpers `#include `), - **`gcc-14` / `g++-14`** (Homebrew on macOS, distro packages on Linux), - **BLAS / LAPACK** (linked via `-lblas -llapack`), - on macOS, the Homebrew prefix exposed at the symlinked locations `/usr/local/brewlib` and `/usr/local/brewinclude`. ### Linux Install Eigen: ```{bash, eval=FALSE} sudo apt install libeigen3-dev # Debian / Ubuntu sudo pacman -S eigen # Arch / Manjaro sudo yum install eigen3-devel # RHEL / Fedora / CentOS sudo zypper install eigen3-devel # openSUSE ``` Install `gcc-14` / `g++-14` (or the most recent `gcc` available; the Makefile defaults to `gcc-14`): ```{bash, eval=FALSE} sudo apt install gcc-14 g++-14 # Debian / Ubuntu sudo pacman -S gcc # Arch / Manjaro sudo dnf install gcc gcc-c++ # Fedora sudo zypper install gcc gcc-c++ # openSUSE ``` If your `gcc` is not at `/opt/homebrew/bin/gcc-14`, edit the `CC` / `CXX` lines in `inst/src-optional/Makefile` (or in `src/Makefile` after running `configure --enable-compiled`) before running `R CMD INSTALL`. The Makefile auto-detects Linux and emits the correct architecture flags. ### macOS Install [Homebrew](https://brew.sh/): ```{bash, eval=FALSE} /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" ``` Install Eigen, `gcc@14`, and the Homebrew copies of BLAS/LAPACK that the package links against: ```{bash, eval=FALSE} brew install eigen brew install gcc@14 ``` If `eigen` is not picked up automatically, create the symlinks the Makefile looks for: ```{bash, eval=FALSE} sudo ln -s $(brew --prefix eigen)/include/eigen3 /usr/local/include/eigen3 sudo ln -s $(brew --prefix)/lib /usr/local/brewlib sudo ln -s $(brew --prefix)/include /usr/local/brewinclude ``` The Makefile sets `CC = /opt/homebrew/bin/gcc-14` and `CXX = /opt/homebrew/bin/g++-14`. On Apple Silicon (Homebrew under `/opt/homebrew`) the path is correct out of the box. On Intel Macs (Homebrew under `/usr/local`) either edit those two lines to point at your `gcc-14` binary, or expose a symlink: ```{bash, eval=FALSE} sudo ln -s $(brew --prefix gcc@14)/bin/gcc-14 /opt/homebrew/bin/gcc-14 sudo ln -s $(brew --prefix gcc@14)/bin/g++-14 /opt/homebrew/bin/g++-14 ``` The Makefile also `codesign`s the produced `.so` ad-hoc, which is required by the macOS dynamic linker on macOS 26+. ## Inspecting and adjusting the Makefile The Makefile shipped in `inst/src-optional/` is reproduced (truncated) below. After running `./configure --enable-compiled` you will find the same file in `src/`, where any tweaks for an unusual environment should be made before running `R CMD INSTALL .`: ```{bash, eval=FALSE} toInclude = $(R_LIBRARY_DIR)/INLA/include/ PKG_CFLAGS = -I$(R_HOME)/include CC = /opt/homebrew/bin/gcc-14 CXX = /opt/homebrew/bin/g++-14 EIGEN_MAC = /opt/homebrew/ EIGEN_MAC_VAR = /usr/local EIGEN_LINUX = /usr MAC_LIB = /usr/local/brewlib MAC_INCLUDE = /usr/local/brewinclude # --- platform-specific flags follow; see the file for the full content --- ``` Most users only need to update `CC` / `CXX` (if `gcc-14` lives elsewhere) and the Eigen / Homebrew paths. The first time you build, the Makefile will fetch `cgeneric.h` from the upstream `r-inla` repository if it is not already present in `${R_LIBRARY_DIR}/INLA/include/`. ## Windows The Makefile is not maintained for Windows. Windows users should stick with the default pure-R install (`remotes::install_github("davidbolin/rSPDE", ref = "devel")`), which delegates the cgeneric implementation to the shared object that ships with `INLA`.