R Packaging Guidelines

R is a language and environment for statistical computing and graphics. R is similar to the award-winning S system, which was developed at Bell Laboratories by John Chambers et al. It provides a wide variety of statistical and graphical techniques (linear and nonlinear modelling, statistical tests, time series analysis, classification, clustering, …​).

R is designed as a true computer language with control-flow constructions for iteration and alternation, and it allows users to add additional functionality by defining new functions. For computationally intensive tasks, C, C++ and Fortran code can be linked and called at run time. For more info, see An introduction to R.

This document covers how to handle R "add-on packages" for inclusion in Fedora’s repositories. For a complete example, see the Example spec file below.

Naming

The canonical source of R packages is CRAN, the "Comprehensive R Archive Network". The are additional CRAN-like repositories for specific fields, such as Bioconductor (Bioc for short) for bioinformatics. But since they are designed to be complementary, package names do not conflict with each other.

R add-ons MUST be packaged with R-$pkg as the name of the source package, where $pkg is the name of the project on the upstream CRAN-like repository, i.e. the package DESCRIPTION's Package field. This $pkg name MUST be exactly as written upstream, including case distinctions and dots. Also:

  • The spec’s Summary field SHOULD match the package DESCRIPTION’s Title field.

  • The spec’s Description field SHOULD match the package DESCRIPTION’s Description field.

Versioning

Since upstream versions may contain characters that are invalid in RPM version strings, they MUST be translated to be RPM-compatible. Particularly, it is common for R packages to specify patch versions using the hyphen as the separator, e.g. 1.2-3. Such hyphens MUST be converted to a dot. This translation SHOULD be done via the %R_rpm_version macro as follows:

Version: %R_rpm_version 1.2-3

Apart from defining %{version} as 1.2.3 in this case, this macro sets %__R_upstream_version to keep track of the upstream version for URL generation.

License

Typically, R packages do not contain license files per CRAN policy. R allows and ships a set of open source licenses, and R packages just declare which one they adhere to in the DESCRIPTION file. Following this policy, and as an exception to the general Licensing Guidelines, we do not require upstream R packages to add additional license files.

Full text licenses can be found under /usr/share/R/licenses. These texts can also be displayed in the R console using the RShowDoc() function.

Sources

Projects from standard CRAN-like repositories MUST be packaged from the sources that are published there. Packages from the following repositories MUST use the set macros provided for automatic generation of the project’s URL and package’s source URL:

  • CRAN: %{cran_url} and %{cran_source}

  • Bioc: %{bioc_url} and %{bioc_source}

Architectures

Packages that do not contain architecture-specific code (i.e. no compiled parts), MUST set BuildArch: noarch.

This affects the installation path:

  • %{_datadir}/R/library/$pkg for noarch packages;

  • %{_libdir}/R/library/$pkg otherwise;

but this is automatically handled by RPM macros as described below.

Dependencies

Automatic standardized names

All R packages will automatically produce standardized Requires and Provides via a generator in R-rpm-macros:

  • Provides are in the form R($pkg) = $version;

  • Requires are in the form R($pkg), with optional >= $version as specified in the package’s metadata if supplied;

where $pkg is the upstream package name, and $version is the RPM-compatible version as described in Versioning.

The packager MUST inspect the generated Requires for correctness. All hard dependencies (R’s LinkingTo, Depends, Imports) MUST be resolvable within the targeted Fedora version.

BuildRequires

Packages MUST declare BuildRequires: R-devel, which in turn pulls the necessary R-rpm-macros and sets the development environment (compilers, libraries, etc.).

Note that R packages inherit their compilation flags from the main R package, which stores them in %{_libdir}/R/etc/Makeconf. The design of R is such that all R add-on packages use the same optimization flags that the main R package was built with. Accordingly, this is why R addon packages do not pass %{optflags}.

If other libraries and utilities (e.g. cmake) are required for building, they MUST be declared explicitly as BuildRequires.

Build-time dependencies on other R packages are automatically handled by the %R_buildrequires macro, which MUST be called in the %generate_buildrequires scriptlet.

  • All hard dependencies (R’s LinkingTo, Depends, Imports) are declared as BuildRequires using standardized names (see Automatic standardized names).

  • Soft dependencies (R’s Suggests, Enhances) are skipped, except for packages used to develop the test suite (currently, testthat, tinytest or RUnit).

Bundled dependencies

Following the general guidelines, packages SHOULD unbundle other dependencies found in R package sources whenever possible. Whenever bundled dependencies are used, they MUST be declared with virtual Provides.

Sub-packages

Some R packages expose header files under the standard path R/library/$pkg/include (defined by CRAN and expected by R), so that other packages can link to them via LinkingTo. The Rcpp package is a notable example. Sometimes, these headers are required at build-time, sometimes at build- as well as run-time and therefore they are essential for proper functioning…​ For these and a variety of other reasons, these headers MUST NOT be split off into a -devel sub-package.

If a particular package contains a large number of examples or documentation that do not impact the package’s functionality, these parts MAY be split off into a sub-package, but sub-packages in general are highly discouraged.

Walkthrough

Preparing the sources

The rest of the scriptlets expect package sources to be extracted in a subdirectory named after the package. Therefore, in %prep, the call to %setup or %autosetup MUST set the -c option.

%prep
%autosetup -c

Other code for unbundling, fixes and workarounds MAY be placed here.

Dynamic BuildRequires

The %R_buildrequires macro MUST be called in the %generate_buildrequires scriptlet to generate the dynamic BuildRequires.

%generate_buildrequires
%R_buildrequires

Testing packages such as testthat, which are declared in Suggests are whitelisted in %{__R_whitelist}, and added as BuildRequires by %R_buildrequires.

Building and Installing

R packages are built and installed in a single stage via R CMD INSTALL. Therefore, the %build section MUST be empty.

Two macros are provided and MUST be called in the %install section. First, %R_install builds and installs the package, then %R_save_files generates a list of files corresponding to the given importable module, and saves it as %{R_files}.

%build

%install
%R_install
%R_save_files

The %R_install macro ensures reprodubility by setting the package’s build timestamp as $SOURCE_DATE_EPOCH.

R package installation generates a new R.css file that conflicts with the master R.css file included in the main R package. The %R_install macro deletes this file.

The %R_install macro calls %_R_libdir_check to ensure that a noarch package did not produce a shared library, or an archful package actually contains a shared library; otherwise, it fails with an informative error message. If the packager does not want this check, %_R_libdir_check can be set e.g. to an empty string.

Testing

The %R_check macro MUST be called in the %check section to run R package checks.

%check
%R_check

According to CRAN’s guidelines, R packages MUST work without soft dependencies. If package checks fail because soft dependencies are used unconditionally (e.g. in examples or tests), this is considered a bug and SHOULD be reported upstream. Meanwhile, a workaround MUST be put in place:

  • If the failure happens in an example, the --no-examples flag MAY be appended to %R_check.

  • If the failure happens in a test, a skip() call MAY be added in the proper place to skip a test, or a test file MAY be removed, or even the --no-tests flag MAY be appended to %R_check for more complicated situations.

Listing files

Module files MUST be added via the -f option as follows:

%files -f %{R_files}

If necessary, any additional files outside the package’s path SHOULD be added explicitly afterwards.

Example spec file

This is an example spec file for a hypothetical R package called "foo", with upstream version 1.2-3:

Name:           R-foo
Version:        %R_rpm_version 1.2-3
Release:        %autorelease
Summary:        Adds foo functionality for R

License:        GPL-2.0-or-later
URL:            %{cran_url}
Source:         %{cran_source}

# BuildArch:      noarch
BuildRequires:  R-devel
# BuildRequires:  somelib-devel

%description
R Interface to foo, enables bar!

%prep
%autosetup -c

%generate_buildrequires
%R_buildrequires

%build

%install
%R_install
%R_save_files

%check
%R_check

%files -f %{R_files}

%changelog
%autochangelog