We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
R package modules have priority over user-installed packages
R has multiple variables that control the library path, `R_LIBS`, `R_LIBS_USER` and `R_LIBS_SITE`.

The path can be inspected with `.libPaths()` and is made up of in order of the entries in `R_LIBS`, `R_LIBS_USER` and `R_LIBS_SITE` and last the R installation itself.

Our R package modules currently prepend their path to `R_LIBS` similar to how `PYTHONPATH` is handled, but this means that the user's directory (typically specified in `~/.Renviron` or the default) is not at the front of the library path.

This means that users cannot override system-installed packages and more importantly, `install.packages` only ever considers the first entry in the library path unless you explicitly specify a `lib=` to install to. Some installation functions like `install_github` doesn't even have that customization point.

I suggest that we alter our R packages to prepend to `R_LIBS_SITE` instead, it seems to yield the preferred order for an end-user.

Our R installations do not have a bundled `site-library` directory so the environment variable is currently unused.

Upstream documentation on how the paths are constructed: https://stat.ethz.ch/R-manual/R-devel/library/base/html/libPaths.html

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `easybuild/easyblocks/generic/rpackage.py`
Content:
```
1 ##
2 # Copyright 2009-2021 Ghent University
3 #
4 # This file is part of EasyBuild,
5 # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
6 # with support of Ghent University (http://ugent.be/hpc),
7 # the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
8 # Flemish Research Foundation (FWO) (http://www.fwo.be/en)
9 # and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
10 #
11 # https://github.com/easybuilders/easybuild
12 #
13 # EasyBuild is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation v2.
16 #
17 # EasyBuild is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with EasyBuild.  If not, see <http://www.gnu.org/licenses/>.
24 ##
25 """
26 EasyBuild support for building and installing R packages, implemented as an easyblock
27 
28 @author: Stijn De Weirdt (Ghent University)
29 @author: Dries Verdegem (Ghent University)
30 @author: Kenneth Hoste (Ghent University)
31 @author: Jens Timmerman (Ghent University)
32 @author: Toon Willems (Ghent University)
33 @author: Balazs Hajgato (Vrije Universiteit Brussel)
34 """
35 import os
36 
37 from easybuild.easyblocks.r import EXTS_FILTER_R_PACKAGES, EB_R
38 from easybuild.easyblocks.generic.configuremake import check_config_guess, obtain_config_guess
39 from easybuild.framework.easyconfig import CUSTOM
40 from easybuild.framework.extensioneasyblock import ExtensionEasyBlock
41 from easybuild.tools.build_log import EasyBuildError
42 from easybuild.tools.filetools import mkdir, copy_file
43 from easybuild.tools.run import run_cmd, parse_log_for_error
44 
45 
46 def make_R_install_option(opt, values, cmdline=False):
47     """
48     Make option list for install.packages, to specify in R environment.
49     """
50     txt = ""
51     if values:
52         if cmdline:
53             txt = " --%s=\"%s" % (opt, values[0])
54         else:
55             txt = "%s=c(\"%s" % (opt, values[0])
56         for i in values[1:]:
57             txt += " %s" % i
58         if cmdline:
59             txt += "\""
60         else:
61             txt += "\")"
62     return txt
63 
64 
65 class RPackage(ExtensionEasyBlock):
66     """
67     Install an R package as a separate module, or as an extension.
68     """
69 
70     @staticmethod
71     def extra_options(extra_vars=None):
72         """Extra easyconfig parameters specific to RPackage."""
73         extra_vars = ExtensionEasyBlock.extra_options(extra_vars=extra_vars)
74         extra_vars.update({
75             'exts_subdir': ['', "Subdirectory where R extensions should be installed info", CUSTOM],
76             'unpack_sources': [False, "Unpack sources before installation", CUSTOM],
77         })
78         return extra_vars
79 
80     def __init__(self, *args, **kwargs):
81         """Initliaze RPackage-specific class variables."""
82 
83         super(RPackage, self).__init__(*args, **kwargs)
84 
85         self.configurevars = []
86         self.configureargs = []
87         self.ext_src = None
88 
89     def make_r_cmd(self, prefix=None):
90         """Create a command to run in R to install an R package."""
91         confvars = "confvars"
92         confargs = "confargs"
93         confvarslist = make_R_install_option(confvars, self.configurevars)
94         confargslist = make_R_install_option(confargs, self.configureargs)
95         confvarsstr = ""
96         if confvarslist:
97             confvarslist = confvarslist + "; names(%s)=\"%s\"" % (confvars, self.name)
98             confvarsstr = ", configure.vars=%s" % confvars
99         confargsstr = ""
100         if confargslist:
101             confargslist = confargslist + "; names(%s)=\"%s\"" % (confargs, self.name)
102             confargsstr = ", configure.args=%s" % confargs
103 
104         if prefix:
105             prefix = '"%s", ' % prefix
106         else:
107             prefix = ''
108 
109         r_cmd = """
110         options(repos=c(CRAN="http://www.freestatistics.org/cran"))
111         %s
112         %s
113         install.packages("%s", %s dependencies = FALSE %s%s)
114         """ % (confvarslist, confargslist, self.name, prefix, confvarsstr, confargsstr)
115         cmd = "%s R -q --no-save %s" % (self.cfg['preinstallopts'], self.cfg['installopts'])
116 
117         self.log.debug("make_r_cmd returns %s with input %s" % (cmd, r_cmd))
118 
119         return (cmd, r_cmd)
120 
121     def make_cmdline_cmd(self, prefix=None):
122         """Create a command line to install an R package."""
123         confvars = ""
124         if self.configurevars:
125             confvars = make_R_install_option("configure-vars", self.configurevars, cmdline=True)
126         confargs = ""
127         if self.configureargs:
128             confargs = make_R_install_option("configure-args", self.configureargs, cmdline=True)
129 
130         if prefix:
131             prefix = '--library=%s' % prefix
132         else:
133             prefix = ''
134 
135         if self.start_dir:
136             loc = os.path.join(self.ext_dir or os.path.sep, self.start_dir)
137         else:
138             loc = self.ext_dir or self.ext_src
139 
140         cmd = ' '.join([
141             self.cfg['preinstallopts'],
142             "R CMD INSTALL",
143             loc,
144             confargs,
145             confvars,
146             prefix,
147             '--no-clean-on-error',
148             self.cfg['installopts'],
149         ])
150 
151         self.log.debug("make_cmdline_cmd returns %s" % cmd)
152         return cmd, None
153 
154     def configure_step(self):
155         """No configuration for installing R packages."""
156         pass
157 
158     def build_step(self):
159         """No separate build step for R packages."""
160         pass
161 
162     def install_R_package(self, cmd, inp=None):
163         """Install R package as specified, and check for errors."""
164 
165         cmdttdouterr, _ = run_cmd(cmd, log_all=True, simple=False, inp=inp, regexp=False)
166 
167         cmderrors = parse_log_for_error(cmdttdouterr, regExp="^ERROR:")
168         if cmderrors:
169             cmd = "R -q --no-save"
170             stdin = """
171             remove.library(%s)
172             """ % self.name
173             # remove package if errors were detected
174             # it's possible that some of the dependencies failed, but the package itself was installed
175             run_cmd(cmd, log_all=False, log_ok=False, simple=False, inp=stdin, regexp=False)
176             raise EasyBuildError("Errors detected during installation of R package %s!", self.name)
177         else:
178             self.log.debug("R package %s installed succesfully" % self.name)
179 
180     def update_config_guess(self, path):
181         """Update any config.guess found in specified directory"""
182         for config_guess_dir in (root for root, _, files in os.walk(path) if 'config.guess' in files):
183             config_guess = os.path.join(config_guess_dir, 'config.guess')
184             if not check_config_guess(config_guess):
185                 updated_config_guess = obtain_config_guess()
186                 if updated_config_guess:
187                     self.log.debug("Replacing outdated %s with more recent %s", config_guess, updated_config_guess)
188                     copy_file(updated_config_guess, config_guess)
189                 else:
190                     raise EasyBuildError("Failed to obtain updated config.guess")
191 
192     def install_step(self):
193         """Install procedure for R packages."""
194         # Update config.guess if the package was extracted
195         if self.start_dir:
196             self.update_config_guess(self.start_dir)
197         cmd, stdin = self.make_cmdline_cmd(prefix=os.path.join(self.installdir, self.cfg['exts_subdir']))
198         self.install_R_package(cmd, inp=stdin)
199 
200     def run(self):
201         """Install R package as an extension."""
202 
203         # determine location
204         if isinstance(self.master, EB_R):
205             # extension is being installed as part of an R installation/module
206             (out, _) = run_cmd("R RHOME", log_all=True, simple=False)
207             rhome = out.strip()
208             lib_install_prefix = os.path.join(rhome, 'library')
209         else:
210             # extension is being installed in a separate installation prefix
211             lib_install_prefix = os.path.join(self.installdir, self.cfg['exts_subdir'])
212             mkdir(lib_install_prefix, parents=True)
213 
214         if self.src:
215             super(RPackage, self).run(unpack_src=True)
216             self.ext_src = self.src
217             self.update_config_guess(self.ext_dir)
218             self.log.debug("Installing R package %s version %s." % (self.name, self.version))
219             cmd, stdin = self.make_cmdline_cmd(prefix=lib_install_prefix)
220         else:
221             if self.patches:
222                 raise EasyBuildError("Cannot patch R package %s as no explicit source is given!", self.name)
223             self.log.debug("Installing most recent version of R package %s (source not found)." % self.name)
224             cmd, stdin = self.make_r_cmd(prefix=lib_install_prefix)
225 
226         self.install_R_package(cmd, inp=stdin)
227 
228     def sanity_check_step(self, *args, **kwargs):
229         """
230         Custom sanity check for R packages
231         """
232         return super(RPackage, self).sanity_check_step(EXTS_FILTER_R_PACKAGES, *args, **kwargs)
233 
234     def make_module_extra(self):
235         """Add install path to R_LIBS"""
236         # prepend R_LIBS with install path
237         extra = self.module_generator.prepend_paths("R_LIBS", [self.cfg['exts_subdir']])
238         return super(RPackage, self).make_module_extra(extra)
239
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/easybuild/easyblocks/generic/rpackage.py b/easybuild/easyblocks/generic/rpackage.py
--- a/easybuild/easyblocks/generic/rpackage.py
+++ b/easybuild/easyblocks/generic/rpackage.py
@@ -232,7 +232,7 @@
         return super(RPackage, self).sanity_check_step(EXTS_FILTER_R_PACKAGES, *args, **kwargs)
 
     def make_module_extra(self):
-        """Add install path to R_LIBS"""
-        # prepend R_LIBS with install path
-        extra = self.module_generator.prepend_paths("R_LIBS", [self.cfg['exts_subdir']])
+        """Add install path to R_LIBS_SITE"""
+        # prepend R_LIBS_SITE with install path
+        extra = self.module_generator.prepend_paths("R_LIBS_SITE", [self.cfg['exts_subdir']])
         return super(RPackage, self).make_module_extra(extra)

{"golden_diff": "diff --git a/easybuild/easyblocks/generic/rpackage.py b/easybuild/easyblocks/generic/rpackage.py\n--- a/easybuild/easyblocks/generic/rpackage.py\n+++ b/easybuild/easyblocks/generic/rpackage.py\n@@ -232,7 +232,7 @@\n         return super(RPackage, self).sanity_check_step(EXTS_FILTER_R_PACKAGES, *args, **kwargs)\n \n     def make_module_extra(self):\n-        \"\"\"Add install path to R_LIBS\"\"\"\n-        # prepend R_LIBS with install path\n-        extra = self.module_generator.prepend_paths(\"R_LIBS\", [self.cfg['exts_subdir']])\n+        \"\"\"Add install path to R_LIBS_SITE\"\"\"\n+        # prepend R_LIBS_SITE with install path\n+        extra = self.module_generator.prepend_paths(\"R_LIBS_SITE\", [self.cfg['exts_subdir']])\n         return super(RPackage, self).make_module_extra(extra)\n", "issue": "R package modules have priority over user-installed packages\nR has multiple variables that control the library path, `R_LIBS`, `R_LIBS_USER` and `R_LIBS_SITE`.\r\n\r\nThe path can be inspected with `.libPaths()` and is made up of in order of the entries in `R_LIBS`, `R_LIBS_USER` and `R_LIBS_SITE` and last the R installation itself.\r\n\r\nOur R package modules currently prepend their path to `R_LIBS` similar to how `PYTHONPATH` is handled, but this means that the user's directory (typically specified in `~/.Renviron` or the default) is not at the front of the library path.\r\n\r\nThis means that users cannot override system-installed packages and more importantly, `install.packages` only ever considers the first entry in the library path unless you explicitly specify a `lib=` to install to. Some installation functions like `install_github` doesn't even have that customization point.\r\n\r\nI suggest that we alter our R packages to prepend to `R_LIBS_SITE` instead, it seems to yield the preferred order for an end-user.\r\n\r\nOur R installations do not have a bundled `site-library` directory so the environment variable is currently unused.\r\n\r\nUpstream documentation on how the paths are constructed: https://stat.ethz.ch/R-manual/R-devel/library/base/html/libPaths.html\n", "before_files": [{"content": "##\n# Copyright 2009-2021 Ghent University\n#\n# This file is part of EasyBuild,\n# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),\n# with support of Ghent University (http://ugent.be/hpc),\n# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),\n# Flemish Research Foundation (FWO) (http://www.fwo.be/en)\n# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).\n#\n# https://github.com/easybuilders/easybuild\n#\n# EasyBuild is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation v2.\n#\n# EasyBuild is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with EasyBuild.  If not, see <http://www.gnu.org/licenses/>.\n##\n\"\"\"\nEasyBuild support for building and installing R packages, implemented as an easyblock\n\n@author: Stijn De Weirdt (Ghent University)\n@author: Dries Verdegem (Ghent University)\n@author: Kenneth Hoste (Ghent University)\n@author: Jens Timmerman (Ghent University)\n@author: Toon Willems (Ghent University)\n@author: Balazs Hajgato (Vrije Universiteit Brussel)\n\"\"\"\nimport os\n\nfrom easybuild.easyblocks.r import EXTS_FILTER_R_PACKAGES, EB_R\nfrom easybuild.easyblocks.generic.configuremake import check_config_guess, obtain_config_guess\nfrom easybuild.framework.easyconfig import CUSTOM\nfrom easybuild.framework.extensioneasyblock import ExtensionEasyBlock\nfrom easybuild.tools.build_log import EasyBuildError\nfrom easybuild.tools.filetools import mkdir, copy_file\nfrom easybuild.tools.run import run_cmd, parse_log_for_error\n\n\ndef make_R_install_option(opt, values, cmdline=False):\n    \"\"\"\n    Make option list for install.packages, to specify in R environment.\n    \"\"\"\n    txt = \"\"\n    if values:\n        if cmdline:\n            txt = \" --%s=\\\"%s\" % (opt, values[0])\n        else:\n            txt = \"%s=c(\\\"%s\" % (opt, values[0])\n        for i in values[1:]:\n            txt += \" %s\" % i\n        if cmdline:\n            txt += \"\\\"\"\n        else:\n            txt += \"\\\")\"\n    return txt\n\n\nclass RPackage(ExtensionEasyBlock):\n    \"\"\"\n    Install an R package as a separate module, or as an extension.\n    \"\"\"\n\n    @staticmethod\n    def extra_options(extra_vars=None):\n        \"\"\"Extra easyconfig parameters specific to RPackage.\"\"\"\n        extra_vars = ExtensionEasyBlock.extra_options(extra_vars=extra_vars)\n        extra_vars.update({\n            'exts_subdir': ['', \"Subdirectory where R extensions should be installed info\", CUSTOM],\n            'unpack_sources': [False, \"Unpack sources before installation\", CUSTOM],\n        })\n        return extra_vars\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"Initliaze RPackage-specific class variables.\"\"\"\n\n        super(RPackage, self).__init__(*args, **kwargs)\n\n        self.configurevars = []\n        self.configureargs = []\n        self.ext_src = None\n\n    def make_r_cmd(self, prefix=None):\n        \"\"\"Create a command to run in R to install an R package.\"\"\"\n        confvars = \"confvars\"\n        confargs = \"confargs\"\n        confvarslist = make_R_install_option(confvars, self.configurevars)\n        confargslist = make_R_install_option(confargs, self.configureargs)\n        confvarsstr = \"\"\n        if confvarslist:\n            confvarslist = confvarslist + \"; names(%s)=\\\"%s\\\"\" % (confvars, self.name)\n            confvarsstr = \", configure.vars=%s\" % confvars\n        confargsstr = \"\"\n        if confargslist:\n            confargslist = confargslist + \"; names(%s)=\\\"%s\\\"\" % (confargs, self.name)\n            confargsstr = \", configure.args=%s\" % confargs\n\n        if prefix:\n            prefix = '\"%s\", ' % prefix\n        else:\n            prefix = ''\n\n        r_cmd = \"\"\"\n        options(repos=c(CRAN=\"http://www.freestatistics.org/cran\"))\n        %s\n        %s\n        install.packages(\"%s\", %s dependencies = FALSE %s%s)\n        \"\"\" % (confvarslist, confargslist, self.name, prefix, confvarsstr, confargsstr)\n        cmd = \"%s R -q --no-save %s\" % (self.cfg['preinstallopts'], self.cfg['installopts'])\n\n        self.log.debug(\"make_r_cmd returns %s with input %s\" % (cmd, r_cmd))\n\n        return (cmd, r_cmd)\n\n    def make_cmdline_cmd(self, prefix=None):\n        \"\"\"Create a command line to install an R package.\"\"\"\n        confvars = \"\"\n        if self.configurevars:\n            confvars = make_R_install_option(\"configure-vars\", self.configurevars, cmdline=True)\n        confargs = \"\"\n        if self.configureargs:\n            confargs = make_R_install_option(\"configure-args\", self.configureargs, cmdline=True)\n\n        if prefix:\n            prefix = '--library=%s' % prefix\n        else:\n            prefix = ''\n\n        if self.start_dir:\n            loc = os.path.join(self.ext_dir or os.path.sep, self.start_dir)\n        else:\n            loc = self.ext_dir or self.ext_src\n\n        cmd = ' '.join([\n            self.cfg['preinstallopts'],\n            \"R CMD INSTALL\",\n            loc,\n            confargs,\n            confvars,\n            prefix,\n            '--no-clean-on-error',\n            self.cfg['installopts'],\n        ])\n\n        self.log.debug(\"make_cmdline_cmd returns %s\" % cmd)\n        return cmd, None\n\n    def configure_step(self):\n        \"\"\"No configuration for installing R packages.\"\"\"\n        pass\n\n    def build_step(self):\n        \"\"\"No separate build step for R packages.\"\"\"\n        pass\n\n    def install_R_package(self, cmd, inp=None):\n        \"\"\"Install R package as specified, and check for errors.\"\"\"\n\n        cmdttdouterr, _ = run_cmd(cmd, log_all=True, simple=False, inp=inp, regexp=False)\n\n        cmderrors = parse_log_for_error(cmdttdouterr, regExp=\"^ERROR:\")\n        if cmderrors:\n            cmd = \"R -q --no-save\"\n            stdin = \"\"\"\n            remove.library(%s)\n            \"\"\" % self.name\n            # remove package if errors were detected\n            # it's possible that some of the dependencies failed, but the package itself was installed\n            run_cmd(cmd, log_all=False, log_ok=False, simple=False, inp=stdin, regexp=False)\n            raise EasyBuildError(\"Errors detected during installation of R package %s!\", self.name)\n        else:\n            self.log.debug(\"R package %s installed succesfully\" % self.name)\n\n    def update_config_guess(self, path):\n        \"\"\"Update any config.guess found in specified directory\"\"\"\n        for config_guess_dir in (root for root, _, files in os.walk(path) if 'config.guess' in files):\n            config_guess = os.path.join(config_guess_dir, 'config.guess')\n            if not check_config_guess(config_guess):\n                updated_config_guess = obtain_config_guess()\n                if updated_config_guess:\n                    self.log.debug(\"Replacing outdated %s with more recent %s\", config_guess, updated_config_guess)\n                    copy_file(updated_config_guess, config_guess)\n                else:\n                    raise EasyBuildError(\"Failed to obtain updated config.guess\")\n\n    def install_step(self):\n        \"\"\"Install procedure for R packages.\"\"\"\n        # Update config.guess if the package was extracted\n        if self.start_dir:\n            self.update_config_guess(self.start_dir)\n        cmd, stdin = self.make_cmdline_cmd(prefix=os.path.join(self.installdir, self.cfg['exts_subdir']))\n        self.install_R_package(cmd, inp=stdin)\n\n    def run(self):\n        \"\"\"Install R package as an extension.\"\"\"\n\n        # determine location\n        if isinstance(self.master, EB_R):\n            # extension is being installed as part of an R installation/module\n            (out, _) = run_cmd(\"R RHOME\", log_all=True, simple=False)\n            rhome = out.strip()\n            lib_install_prefix = os.path.join(rhome, 'library')\n        else:\n            # extension is being installed in a separate installation prefix\n            lib_install_prefix = os.path.join(self.installdir, self.cfg['exts_subdir'])\n            mkdir(lib_install_prefix, parents=True)\n\n        if self.src:\n            super(RPackage, self).run(unpack_src=True)\n            self.ext_src = self.src\n            self.update_config_guess(self.ext_dir)\n            self.log.debug(\"Installing R package %s version %s.\" % (self.name, self.version))\n            cmd, stdin = self.make_cmdline_cmd(prefix=lib_install_prefix)\n        else:\n            if self.patches:\n                raise EasyBuildError(\"Cannot patch R package %s as no explicit source is given!\", self.name)\n            self.log.debug(\"Installing most recent version of R package %s (source not found).\" % self.name)\n            cmd, stdin = self.make_r_cmd(prefix=lib_install_prefix)\n\n        self.install_R_package(cmd, inp=stdin)\n\n    def sanity_check_step(self, *args, **kwargs):\n        \"\"\"\n        Custom sanity check for R packages\n        \"\"\"\n        return super(RPackage, self).sanity_check_step(EXTS_FILTER_R_PACKAGES, *args, **kwargs)\n\n    def make_module_extra(self):\n        \"\"\"Add install path to R_LIBS\"\"\"\n        # prepend R_LIBS with install path\n        extra = self.module_generator.prepend_paths(\"R_LIBS\", [self.cfg['exts_subdir']])\n        return super(RPackage, self).make_module_extra(extra)\n", "path": "easybuild/easyblocks/generic/rpackage.py"}], "after_files": [{"content": "##\n# Copyright 2009-2021 Ghent University\n#\n# This file is part of EasyBuild,\n# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),\n# with support of Ghent University (http://ugent.be/hpc),\n# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),\n# Flemish Research Foundation (FWO) (http://www.fwo.be/en)\n# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).\n#\n# https://github.com/easybuilders/easybuild\n#\n# EasyBuild is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation v2.\n#\n# EasyBuild is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with EasyBuild.  If not, see <http://www.gnu.org/licenses/>.\n##\n\"\"\"\nEasyBuild support for building and installing R packages, implemented as an easyblock\n\n@author: Stijn De Weirdt (Ghent University)\n@author: Dries Verdegem (Ghent University)\n@author: Kenneth Hoste (Ghent University)\n@author: Jens Timmerman (Ghent University)\n@author: Toon Willems (Ghent University)\n@author: Balazs Hajgato (Vrije Universiteit Brussel)\n\"\"\"\nimport os\n\nfrom easybuild.easyblocks.r import EXTS_FILTER_R_PACKAGES, EB_R\nfrom easybuild.easyblocks.generic.configuremake import check_config_guess, obtain_config_guess\nfrom easybuild.framework.easyconfig import CUSTOM\nfrom easybuild.framework.extensioneasyblock import ExtensionEasyBlock\nfrom easybuild.tools.build_log import EasyBuildError\nfrom easybuild.tools.filetools import mkdir, copy_file\nfrom easybuild.tools.run import run_cmd, parse_log_for_error\n\n\ndef make_R_install_option(opt, values, cmdline=False):\n    \"\"\"\n    Make option list for install.packages, to specify in R environment.\n    \"\"\"\n    txt = \"\"\n    if values:\n        if cmdline:\n            txt = \" --%s=\\\"%s\" % (opt, values[0])\n        else:\n            txt = \"%s=c(\\\"%s\" % (opt, values[0])\n        for i in values[1:]:\n            txt += \" %s\" % i\n        if cmdline:\n            txt += \"\\\"\"\n        else:\n            txt += \"\\\")\"\n    return txt\n\n\nclass RPackage(ExtensionEasyBlock):\n    \"\"\"\n    Install an R package as a separate module, or as an extension.\n    \"\"\"\n\n    @staticmethod\n    def extra_options(extra_vars=None):\n        \"\"\"Extra easyconfig parameters specific to RPackage.\"\"\"\n        extra_vars = ExtensionEasyBlock.extra_options(extra_vars=extra_vars)\n        extra_vars.update({\n            'exts_subdir': ['', \"Subdirectory where R extensions should be installed info\", CUSTOM],\n            'unpack_sources': [False, \"Unpack sources before installation\", CUSTOM],\n        })\n        return extra_vars\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"Initliaze RPackage-specific class variables.\"\"\"\n\n        super(RPackage, self).__init__(*args, **kwargs)\n\n        self.configurevars = []\n        self.configureargs = []\n        self.ext_src = None\n\n    def make_r_cmd(self, prefix=None):\n        \"\"\"Create a command to run in R to install an R package.\"\"\"\n        confvars = \"confvars\"\n        confargs = \"confargs\"\n        confvarslist = make_R_install_option(confvars, self.configurevars)\n        confargslist = make_R_install_option(confargs, self.configureargs)\n        confvarsstr = \"\"\n        if confvarslist:\n            confvarslist = confvarslist + \"; names(%s)=\\\"%s\\\"\" % (confvars, self.name)\n            confvarsstr = \", configure.vars=%s\" % confvars\n        confargsstr = \"\"\n        if confargslist:\n            confargslist = confargslist + \"; names(%s)=\\\"%s\\\"\" % (confargs, self.name)\n            confargsstr = \", configure.args=%s\" % confargs\n\n        if prefix:\n            prefix = '\"%s\", ' % prefix\n        else:\n            prefix = ''\n\n        r_cmd = \"\"\"\n        options(repos=c(CRAN=\"http://www.freestatistics.org/cran\"))\n        %s\n        %s\n        install.packages(\"%s\", %s dependencies = FALSE %s%s)\n        \"\"\" % (confvarslist, confargslist, self.name, prefix, confvarsstr, confargsstr)\n        cmd = \"%s R -q --no-save %s\" % (self.cfg['preinstallopts'], self.cfg['installopts'])\n\n        self.log.debug(\"make_r_cmd returns %s with input %s\" % (cmd, r_cmd))\n\n        return (cmd, r_cmd)\n\n    def make_cmdline_cmd(self, prefix=None):\n        \"\"\"Create a command line to install an R package.\"\"\"\n        confvars = \"\"\n        if self.configurevars:\n            confvars = make_R_install_option(\"configure-vars\", self.configurevars, cmdline=True)\n        confargs = \"\"\n        if self.configureargs:\n            confargs = make_R_install_option(\"configure-args\", self.configureargs, cmdline=True)\n\n        if prefix:\n            prefix = '--library=%s' % prefix\n        else:\n            prefix = ''\n\n        if self.start_dir:\n            loc = os.path.join(self.ext_dir or os.path.sep, self.start_dir)\n        else:\n            loc = self.ext_dir or self.ext_src\n\n        cmd = ' '.join([\n            self.cfg['preinstallopts'],\n            \"R CMD INSTALL\",\n            loc,\n            confargs,\n            confvars,\n            prefix,\n            '--no-clean-on-error',\n            self.cfg['installopts'],\n        ])\n\n        self.log.debug(\"make_cmdline_cmd returns %s\" % cmd)\n        return cmd, None\n\n    def configure_step(self):\n        \"\"\"No configuration for installing R packages.\"\"\"\n        pass\n\n    def build_step(self):\n        \"\"\"No separate build step for R packages.\"\"\"\n        pass\n\n    def install_R_package(self, cmd, inp=None):\n        \"\"\"Install R package as specified, and check for errors.\"\"\"\n\n        cmdttdouterr, _ = run_cmd(cmd, log_all=True, simple=False, inp=inp, regexp=False)\n\n        cmderrors = parse_log_for_error(cmdttdouterr, regExp=\"^ERROR:\")\n        if cmderrors:\n            cmd = \"R -q --no-save\"\n            stdin = \"\"\"\n            remove.library(%s)\n            \"\"\" % self.name\n            # remove package if errors were detected\n            # it's possible that some of the dependencies failed, but the package itself was installed\n            run_cmd(cmd, log_all=False, log_ok=False, simple=False, inp=stdin, regexp=False)\n            raise EasyBuildError(\"Errors detected during installation of R package %s!\", self.name)\n        else:\n            self.log.debug(\"R package %s installed succesfully\" % self.name)\n\n    def update_config_guess(self, path):\n        \"\"\"Update any config.guess found in specified directory\"\"\"\n        for config_guess_dir in (root for root, _, files in os.walk(path) if 'config.guess' in files):\n            config_guess = os.path.join(config_guess_dir, 'config.guess')\n            if not check_config_guess(config_guess):\n                updated_config_guess = obtain_config_guess()\n                if updated_config_guess:\n                    self.log.debug(\"Replacing outdated %s with more recent %s\", config_guess, updated_config_guess)\n                    copy_file(updated_config_guess, config_guess)\n                else:\n                    raise EasyBuildError(\"Failed to obtain updated config.guess\")\n\n    def install_step(self):\n        \"\"\"Install procedure for R packages.\"\"\"\n        # Update config.guess if the package was extracted\n        if self.start_dir:\n            self.update_config_guess(self.start_dir)\n        cmd, stdin = self.make_cmdline_cmd(prefix=os.path.join(self.installdir, self.cfg['exts_subdir']))\n        self.install_R_package(cmd, inp=stdin)\n\n    def run(self):\n        \"\"\"Install R package as an extension.\"\"\"\n\n        # determine location\n        if isinstance(self.master, EB_R):\n            # extension is being installed as part of an R installation/module\n            (out, _) = run_cmd(\"R RHOME\", log_all=True, simple=False)\n            rhome = out.strip()\n            lib_install_prefix = os.path.join(rhome, 'library')\n        else:\n            # extension is being installed in a separate installation prefix\n            lib_install_prefix = os.path.join(self.installdir, self.cfg['exts_subdir'])\n            mkdir(lib_install_prefix, parents=True)\n\n        if self.src:\n            super(RPackage, self).run(unpack_src=True)\n            self.ext_src = self.src\n            self.update_config_guess(self.ext_dir)\n            self.log.debug(\"Installing R package %s version %s.\" % (self.name, self.version))\n            cmd, stdin = self.make_cmdline_cmd(prefix=lib_install_prefix)\n        else:\n            if self.patches:\n                raise EasyBuildError(\"Cannot patch R package %s as no explicit source is given!\", self.name)\n            self.log.debug(\"Installing most recent version of R package %s (source not found).\" % self.name)\n            cmd, stdin = self.make_r_cmd(prefix=lib_install_prefix)\n\n        self.install_R_package(cmd, inp=stdin)\n\n    def sanity_check_step(self, *args, **kwargs):\n        \"\"\"\n        Custom sanity check for R packages\n        \"\"\"\n        return super(RPackage, self).sanity_check_step(EXTS_FILTER_R_PACKAGES, *args, **kwargs)\n\n    def make_module_extra(self):\n        \"\"\"Add install path to R_LIBS_SITE\"\"\"\n        # prepend R_LIBS_SITE with install path\n        extra = self.module_generator.prepend_paths(\"R_LIBS_SITE\", [self.cfg['exts_subdir']])\n        return super(RPackage, self).make_module_extra(extra)\n", "path": "easybuild/easyblocks/generic/rpackage.py"}]}