Reference page
How R's Build System Invokes Rtools (and How to Replicate It)
Open the MSYS2 UCRT64 shell that ships with Rtools45. On a default install this is:
πQuick Start: Mimicking the R Build Terminal
πFor x86_64 (Intel/AMD) builds
Open the MSYS2 UCRT64 shell that ships with Rtools45. On a default install this is:
c:\rtools45\ucrt64.exe
Or from cmd.exe:
c:\rtools45\usr\bin\bash.exe --login -i
Once inside, verify the environment:
which gcc # should resolve to /ucrt64/bin/gcc or similar
which make # should resolve to the MSYS2 make
echo $MSYSTEM # should say UCRT64πFor aarch64 (ARM) builds
Open the MSYS2 CLANG64 shell from Rtools45-aarch64:
c:\rtools45-aarch64\clangarm64.exe
Or:
c:\rtools45-aarch64\usr\bin\bash.exe --login -i
Verify:
which clang # should resolve inside the toolchain
echo $MSYSTEM # should say CLANGARM64
πWhat the Build System Actually Does
πShell: sh (MSYS2), not cmd.exe
The R build Makefiles set:
SHELL = sh
(in src/gnuwin32/fixed/Makeconf, line 9)
This sh is the MSYS2 Bourne shell (/usr/bin/sh) shipped inside
Rtools. All Make recipe lines execute through it. This gives you POSIX
shell semantics (pipes, redirects, sed, which, etc.) even on
Windows.
Important distinction: when R is running (not building) and a user
calls system(), R uses COMSPEC (typically cmd.exe /c ...) instead.
See src/gnuwin32/run.c.
πToolchain discovery: everything must be on PATH
Since Rtools42, R assumes the compiler toolchain is on PATH. There is no
hardcoded path to gcc or any tool. From MkRules.rules:
βSince Rtools42, Rtools assumes that the compiler toolchain (e.g. gcc, as, β¦ for Intel targets) is on PATHβ
The key PATH entries for Rtools45 x86_64 are:
c:/rtools45/x86_64-w64-mingw32.static.posix/bin # gcc, g++, gfortran, ar, etc.
c:/rtools45/usr/bin # sh, make, sed, tar, etc.
For aarch64:
c:/rtools45-aarch64/aarch64-w64-mingw32.static.posix/bin # clang, flang, lld, etc.
c:/rtools45-aarch64/usr/bin # sh, make, sed, tar, etc.
These paths come from Rcmd_environ (lines 39-42) and are what the
Rtools MSYS2 shell launchers set up for you automatically.
πLOCAL_SOFT: auto-detected from compiler location
LOCAL_SOFT points to the root of the Rtools software collection
(headers and static libraries). It is computed dynamically from wherever
gcc/clang lives:
LOCAL_SOFT ?= $(shell which `echo $(CC) | sed -e 's/ .*//g'` | sed -e 's!/bin/[^/]\+!!g')
In practice:
- x86_64:
LOCAL_SOFT=/ucrt64(i.e.c:/rtools45/x86_64-w64-mingw32.static.posix) - aarch64:
LOCAL_SOFT=/clangarm64(i.e.c:/rtools45-aarch64/aarch64-w64-mingw32.static.posix)
You can override it with R_CUSTOM_TOOLS_SOFT.
πKey Environment Variables
| Variable | Purpose | Default |
|---|---|---|
MSYSTEM | Set by MSYS2 shell launcher; controls which toolchain prefix is active | UCRT64 or CLANGARM64 |
RTOOLS45_HOME | Override Rtools install location | c:/rtools45 |
RTOOLS45_AARCH64_HOME | Override aarch64 Rtools location | c:/rtools45-aarch64 |
R_CUSTOM_TOOLS_SOFT | Override LOCAL_SOFT for packages | (unset) |
R_CUSTOM_TOOLS_PATH | Override the Rtools PATH entries | (unset) |
USE_LLVM | Set to 1 to use clang/flang instead of gcc/gfortran | (unset) |
WIN | 64 for x86_64 subarch layout; empty for aarch64 (no subarch) | 64 |
BINPREF / BINPREF64 | Prefix for tool names (for cross-compilation) | (empty) |
MSYS2_ENV_CONV_EXCL | R sets this to R_ARCH to prevent MSYS2 path mangling | set in C code |
πConfiguration File Chain
When you run make in src/gnuwin32/, here is what happens:
MkRules.dist # shipped defaults (template, not read directly)
|
v
MkRules.local # your overrides (copy from .dist, uncomment what you need)
+
MkRules.rules # runtime logic: compiler detection, LOCAL_SOFT, tool paths
=
MkRules # generated by concatenating .local + .rules
|
v
fixed/etc/Makeconf # template for installed R's Makeconf (@ tokens substituted)
|
v (via fixed/Makefile sed substitutions)
$R_HOME/etc/Makeconf # final Makeconf shipped with RπWhat MkRules.rules computes automatically
CC = $(BINPREF)$(CCBASE) $(M_ARCH)β compiler commandCCBASE=gccorclang(ifUSE_LLVMis set)FC=gfortranorflangAR,NM,RANLIB,DLLTOOL,RESCOMPβ all prefixed withBINPREFand optionallyLLVMPREF(llvm-) for LLVM buildsTEXI2DVI = env COMSPEC= texi2dviβ clears COMSPEC to work around an MSYS2 bugPKG_CONFIG = $(BINPREF)pkg-configβ for library detection
πStep-by-Step: Set Up a Terminal That Matches the Build Environment
πOption A: Use the Rtools MSYS2 launcher (recommended)
Just launch the appropriate .exe:
- x86_64:
c:\rtools45\ucrt64.exe - aarch64:
c:\rtools45-aarch64\clangarm64.exe
This sets MSYSTEM, PATH, and everything else correctly.
πOption B: Manual setup from cmd.exe or PowerShell
@echo off
set RTOOLS45_HOME=c:\rtools45
set PATH=%RTOOLS45_HOME%\x86_64-w64-mingw32.static.posix\bin;%RTOOLS45_HOME%\usr\bin;%PATH%
set MSYSTEM=UCRT64
rem Launch the MSYS2 sh (what make uses as SHELL)
%RTOOLS45_HOME%\usr\bin\bash.exe --login
For aarch64, replace paths and set MSYSTEM=CLANGARM64.
πOption C: From an existing MSYS2 bash, set up for R building
export PATH="/c/rtools45/x86_64-w64-mingw32.static.posix/bin:/c/rtools45/usr/bin:$PATH"
# Navigate to the R source
cd /c/path/to/r-source/src/gnuwin32
# Create MkRules.local if you haven't (copy from dist, edit as needed)
cp MkRules.dist MkRules.local
# Build
make all recommended
πHow R Invokes make for Package Installation
When you run R CMD INSTALL on a package with compiled code, R:
- Reads
$R_HOME/etc/Makeconf(which has all the tool paths baked in) - Reads the packageβs
Makevars.win(if present) - Invokes
makewithSHELL = sh - The compiler (
gcc/clang) and all tools are found on PATH
The Rcmd_environ file sets up the PATH for this (lines 39-42 are
uncommented during installer builds):
R_RTOOLS45_PATH="${RTOOLS45_HOME:-c:/rtools45}/x86_64-w64-mingw32.static.posix/bin;${RTOOLS45_HOME:-c:/rtools45}/usr/bin"
PATH="${R_CUSTOM_TOOLS_PATH:-${R_RTOOLS45_PATH}};${PATH}/"
πCommon Gotchas
-
SHELL = sh, not bash. Make recipes use
shsemantics. Bashisms (arrays,[[ ]], etc.) will fail in Makefile recipes. -
COMSPEC is cleared for texi2dvi.
TEXI2DVI = env COMSPEC= texi2dviworks around an MSYS2 bug where texi2dvi gets confused by Windows COMSPEC. -
MSYS2 path conversion. MSYS2 auto-converts
/c/footoC:\fooin some contexts. R setsMSYS2_ENV_CONV_EXCL=R_ARCHin C code (src/gnuwin32/system.c) to prevent mangling ofR_ARCH. -
No hardcoded Rtools path. If
gccisnβt on PATH, the build will fail β there is no fallback path detection. -
pkg-config is used by default (
USE_PKG_CONFIG = 1) to find library flags. Falls back to hardcoded library lists if pkg-config is unavailable. -
Static linking. Rtools uses static libraries (the
.static.posixin the toolchain name).DLLFLAGSincludes-static-libgccand libraries are linked statically fromLOCAL_SOFT/lib.