# Linking to beachmat from another package

Aaron Lun

#### 30 October 2018

#### Package

beachmat 1.4.0

# 1 Introduction

The beachmat package provides a C++ API for handling a variety of R matrix types. The aim is to abstract away the specific type of matrix object when writing C++ extensions, thus simplifying the processing of data stored in those objects. Currently, the API supports double-precision, integer, logical and character matrices. Supported classes include base `matrix` objects, a number of classes from the Matrix package, and disk-backed matrices from the HDF5Array package. This document describes how to link to beachmat from the C++ code of another R package.

# 2 Prerequisites for linking

The beachmat package currently has several dependencies:

- The compiler should support the C++11 standard. This usually requires GCC version 4.8.1 or higher. You need to tell the build system to use C++11, by modifying the `SystemRequirements` field of the `DESCRIPTION` file:

        SystemRequirements: C++11

- Rcpp should be installed. You also need to ensure that Rcpp is initialized when your package is loaded. This requires addition of `Rcpp` to the `Imports` field of the `DESCRIPTION` file:

       Imports: Rcpp

  … and a corresponding `importFrom` specification in the `NAMESPACE` file:

       importFrom(Rcpp, sourceCpp)

  (The exact function to be imported doesn’t matter, as long as the namespace is loaded. Check out the Rcpp documentation for more details.)

- HDF5Array, DelayedArray and beachmat itself should be added to the `Suggests` field, as the API will perform some calls to R functions in those packages to query certain parameters. If you intend to accept instances of Matrix classes, the package should also be listed in the `Suggests` field, if not already in `Imports` or `Depends`:

        Suggests: beachmat, HDF5Array, DelayedArray, Matrix

- Rhdf5lib should be installed.

# 3 Linking to the library

To link successfully to the beachmat library, a package must include both a `src/Makevars.win` and `src/Makevars` file.

Note: the contents of `src/Makevars.win` and `src/Makevars` are almost identical, but not quite. Be careful of the differences.

Create a `src/Makevars.win` file with the following lines:

    BEACHMAT_LIBS=$(shell echo 'beachmat::pkgconfig("PKG_LIBS")'|\
        "${R_HOME}/bin/R" --vanilla --slave)
    PKG_LIBS=$(BEACHMAT_LIBS)

… and a `src/Makevars` file with the following lines:

    BEACHMAT_LIBS=`echo 'beachmat::pkgconfig("PKG_LIBS")'|\
        "${R_HOME}/bin/R" --vanilla --slave`
    PKG_LIBS=$(BEACHMAT_LIBS)

The statement for each platfrom modifies the `$PKG_LIBS` variable. If your package needs to add to the `$PKG_LIBS` variable, do so by adding to the `PKG_LIBS=$(BEACHMAT_LIBS)` line. For example:

    PKG_LIBS=$(BEACHMAT_LIBS) -L/path/to/foolib -lfoo

The Linux implementation embeds the location of the beachmat library in the package-specific shared object via the compiler flag `-Wl,rpath,path`, where `path` is determined by `system.file("lib", package="beachmat")`. The path determined by `system.file()` is from `.libPaths()` and will resolve all symbolic links. This can cause problems, e.g., when the “head” node of a cluster mimicks the cluster node via a symbolic link to the directory in which beachmat is installed. Use the environment variable `BEACHMAT_RPATH` to resolve this by setting it to the cluster-node accessible path. Similar arguments apply to Rhdf5lib with the environment variable `RHDF5LIB_RPATH`.

# 4 Including the headers

In order for the C/C++ compiler to find the beachmat package headers during installation, add the following to the `LinkingTo` field of the `DESCRIPTION` file:

    LinkingTo: Rcpp, Rhdf5lib, beachmat

In C or C++ code files, use standard techniques to include header definitions, e.g., `#include "beachmat/numeric_matrix.h"` (see here for more details). Header files are available for perusal at the following location (enter in an R session):

    system.file(package="beachmat", "include")

    ## [1] "/tmp/RtmpS3CKSB/Rinst3ae91d9a18df/beachmat/include"

# 5 Common problems

- An `undefined symbol` error starting with `_ZN2H56H5FileC1ERKNSt7_...` usually indicates that Rhdf5lib was compiled with a different GCC version than beachmat, leading to incompatibilities in the binaries. This can usually be fixed by re-installing Rhdf5lib prior to installing beachmat.

- An `expected unqualified-id before 'using'` error. This means that the version of GCC used to compile beachmat is out of date and does not fully support C++11.

Users can ask for help by making a post on the Bioconductor support site, labelled with the beachmat tag. This is the preferred avenue for questions. New users are advised to read the posting guide before creating a post.