We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
CUDA_{ROOT,HOME,PATH} are PATH-like?
See: https://github.com/easybuilders/easybuild-easyblocks/blob/e3a4cd70357103e1fa463751df13378f217c7ad1/easybuild/easyblocks/c/cuda.py#L191-L193

This creates `prepend_path` module commands, instead of `setenv`! Is there a particular reason to do so?

--- 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/c/cuda.py`
Content:
```
1 ##
2 # This file is an EasyBuild reciPY as per https://github.com/easybuilders/easybuild
3 #
4 # Copyright:: Copyright 2012-2019 Cyprus Institute / CaSToRC, Uni.Lu, NTUA, Ghent University, Forschungszentrum Juelich GmbH
5 # Authors::   George Tsouloupas <g.tsouloupas@cyi.ac.cy>, Fotis Georgatos <fotis@cern.ch>, Kenneth Hoste, Damian Alvarez
6 # License::   MIT/GPL
7 # $Id$
8 #
9 # This work implements a part of the HPCBIOS project and is a component of the policy:
10 # http://hpcbios.readthedocs.org/en/latest/HPCBIOS_2012-99.html
11 ##
12 """
13 EasyBuild support for CUDA, implemented as an easyblock
14 
15 Ref: https://speakerdeck.com/ajdecon/introduction-to-the-cuda-toolkit-for-building-applications
16 
17 @author: George Tsouloupas (Cyprus Institute)
18 @author: Fotis Georgatos (Uni.lu)
19 @author: Kenneth Hoste (Ghent University)
20 @author: Damian Alvarez (Forschungszentrum Juelich)
21 @author: Ward Poelmans (Free University of Brussels)
22 """
23 import os
24 import re
25 import stat
26 
27 from distutils.version import LooseVersion
28 
29 from easybuild.easyblocks.generic.binary import Binary
30 from easybuild.framework.easyconfig import CUSTOM
31 from easybuild.tools.build_log import EasyBuildError
32 from easybuild.tools.filetools import adjust_permissions, patch_perl_script_autoflush, read_file, write_file
33 from easybuild.tools.run import run_cmd, run_cmd_qa
34 from easybuild.tools.systemtools import get_shared_lib_ext
35 
36 # Wrapper script definition
37 WRAPPER_TEMPLATE = """#!/bin/sh
38 echo "$@" | grep -e '-ccbin' -e '--compiler-bindir' > /dev/null
39 if [ $? -eq 0 ];
40 then
41         echo "ERROR: do not set -ccbin or --compiler-bindir when using the `basename $0` wrapper"
42 else
43         nvcc -ccbin=%s "$@"
44         exit $?
45 fi """
46 
47 class EB_CUDA(Binary):
48     """
49     Support for installing CUDA.
50     """
51 
52     @staticmethod
53     def extra_options():
54         """Create a set of wrappers based on a list determined by the easyconfig file"""
55         extra_vars = {
56             'host_compilers': [None, "Host compilers for which a wrapper will be generated", CUSTOM]
57         }
58         return Binary.extra_options(extra_vars)
59 
60     def extract_step(self):
61         """Extract installer to have more control, e.g. options, patching Perl scripts, etc."""
62         execpath = self.src[0]['path']
63         run_cmd("/bin/sh " + execpath + " --noexec --nox11 --target " + self.builddir)
64         self.src[0]['finalpath'] = self.builddir
65 
66     def install_step(self):
67         """Install CUDA using Perl install script."""
68 
69         # define how to run the installer
70         # script has /usr/bin/perl hardcoded, but we want to have control over which perl is being used
71         if LooseVersion(self.version) <= LooseVersion("5"):
72             install_interpreter = "perl"
73             install_script = "install-linux.pl"
74             self.cfg.update('installopts', '--prefix=%s' % self.installdir)
75         elif LooseVersion(self.version) > LooseVersion("5") and LooseVersion(self.version) < LooseVersion("10.1"):
76             install_interpreter = "perl"
77             install_script = "cuda-installer.pl"
78             # note: also including samples (via "-samplespath=%(installdir)s -samples") would require libglut
79             self.cfg.update('installopts', "-verbose -silent -toolkitpath=%s -toolkit" % self.installdir)
80         else:
81             install_interpreter = ""
82             install_script = "./cuda-installer"
83             # note: also including samples (via "-samplespath=%(installdir)s -samples") would require libglut
84             self.cfg.update('installopts', "--silent --toolkit --toolkitpath=%s --defaultroot=%s" % (
85                             self.installdir, self.installdir))
86 
87         cmd = "%(preinstallopts)s %(interpreter)s %(script)s %(installopts)s" % {
88             'preinstallopts': self.cfg['preinstallopts'],
89             'interpreter': install_interpreter,
90             'script': install_script,
91             'installopts': self.cfg['installopts']
92         }
93 
94         # prepare for running install script autonomously
95         qanda = {}
96         stdqa = {
97             # this question is only asked if CUDA tools are already available system-wide
98             r"Would you like to remove all CUDA files under .*? (yes/no/abort): ": "no",
99         }
100         noqanda = [
101             r"^Configuring",
102             r"Installation Complete",
103             r"Verifying archive integrity.*",
104             r"^Uncompressing NVIDIA CUDA",
105             r".* -> .*",
106         ]
107 
108         # patch install script to handle Q&A autonomously
109         if install_interpreter == "perl":
110             patch_perl_script_autoflush(os.path.join(self.builddir, install_script))
111 
112         # make sure $DISPLAY is not defined, which may lead to (weird) problems
113         # this is workaround for not being able to specify --nox11 to the Perl install scripts
114         if 'DISPLAY' in os.environ:
115             os.environ.pop('DISPLAY')
116 
117         # overriding maxhits default value to 300 (300s wait for nothing to change in the output without seeing a known
118         # question)
119         run_cmd_qa(cmd, qanda, std_qa=stdqa, no_qa=noqanda, log_all=True, simple=True, maxhits=300)
120 
121         # check if there are patches to apply
122         if len(self.src) > 1:
123             for patch in self.src[1:]:
124                 self.log.debug("Running patch %s", patch['name'])
125                 run_cmd("/bin/sh " + patch['path'] + " --accept-eula --silent --installdir=" + self.installdir)
126 
127     def post_install_step(self):
128         """Create wrappers for the specified host compilers and generate the appropriate stub symlinks"""
129         def create_wrapper(wrapper_name, wrapper_comp):
130             """Create for a particular compiler, with a particular name"""
131             wrapper_f = os.path.join(self.installdir, 'bin', wrapper_name)
132             write_file(wrapper_f, WRAPPER_TEMPLATE % wrapper_comp)
133             adjust_permissions(wrapper_f, stat.S_IXUSR|stat.S_IRUSR|stat.S_IXGRP|stat.S_IRGRP|stat.S_IXOTH|stat.S_IROTH)
134 
135         # Prepare wrappers to handle a default host compiler other than g++
136         for comp in (self.cfg['host_compilers'] or []):
137             create_wrapper('nvcc_%s' % comp, comp)
138 
139         # Run ldconfig to create missing symlinks in the stubs directory (libcuda.so.1, etc)
140         run_cmd("ldconfig -N " + os.path.join(self.installdir, 'lib64', 'stubs'))
141 
142         super(EB_CUDA, self).post_install_step()
143 
144     def sanity_check_step(self):
145         """Custom sanity check for CUDA."""
146 
147         if LooseVersion(self.version) > LooseVersion("9"):
148             versionfile = read_file(os.path.join(self.installdir, "version.txt"))
149             if not re.search("Version %s$" % self.version, versionfile):
150                 raise EasyBuildError("Unable to find the correct version (%s) in the version.txt file", self.version)
151 
152         shlib_ext = get_shared_lib_ext()
153 
154         chk_libdir = ["lib64"]
155 
156         # Versions higher than 6 do not provide 32 bit libraries
157         if LooseVersion(self.version) < LooseVersion("6"):
158             chk_libdir += ["lib"]
159 
160         culibs = ["cublas", "cudart", "cufft", "curand", "cusparse"]
161         custom_paths = {
162             'files': [os.path.join("bin", x) for x in ["fatbinary", "nvcc", "nvlink", "ptxas"]] +
163             [os.path.join("%s", "lib%s.%s") % (x, y, shlib_ext) for x in chk_libdir for y in culibs],
164             'dirs': ["include"],
165         }
166 
167         if LooseVersion(self.version) < LooseVersion('7'):
168             custom_paths['files'].append(os.path.join('open64', 'bin', 'nvopencc'))
169         if LooseVersion(self.version) >= LooseVersion('7'):
170             custom_paths['files'].append(os.path.join("extras", "CUPTI", "lib64", "libcupti.%s") % shlib_ext)
171             custom_paths['dirs'].append(os.path.join("extras", "CUPTI", "include"))
172 
173 
174         super(EB_CUDA, self).sanity_check_step(custom_paths=custom_paths)
175 
176     def make_module_req_guess(self):
177         """Specify CUDA custom values for PATH etc."""
178 
179         guesses = super(EB_CUDA, self).make_module_req_guess()
180 
181         # The dirs should be in the order ['open64/bin', 'bin']
182         bin_path = []
183         if LooseVersion(self.version) < LooseVersion('7'):
184             bin_path.append(os.path.join('open64', 'bin'))
185         bin_path.append('bin')
186 
187         lib_path = ['lib64']
188         inc_path = ['include']
189         if LooseVersion(self.version) >= LooseVersion('7'):
190             lib_path.append(os.path.join('extras', 'CUPTI', 'lib64'))
191             inc_path.append(os.path.join('extras', 'CUPTI', 'include'))
192             bin_path.append(os.path.join('nvvm', 'bin'))
193             lib_path.append(os.path.join('nvvm', 'lib64'))
194             inc_path.append(os.path.join('nvvm', 'include'))
195 
196         guesses.update({
197             'PATH': bin_path,
198             'LD_LIBRARY_PATH': lib_path,
199             'LIBRARY_PATH': ['lib64', os.path.join('lib64', 'stubs')],
200             'CPATH': inc_path,
201             'CUDA_HOME': [''],
202             'CUDA_ROOT': [''],
203             'CUDA_PATH': [''],
204         })
205 
206         return guesses
207
```
--- 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/c/cuda.py b/easybuild/easyblocks/c/cuda.py
--- a/easybuild/easyblocks/c/cuda.py
+++ b/easybuild/easyblocks/c/cuda.py
@@ -173,6 +173,15 @@
 
         super(EB_CUDA, self).sanity_check_step(custom_paths=custom_paths)
 
+    def make_module_extra(self):
+        """Set the install directory as CUDA_HOME, CUDA_ROOT, CUDA_PATH."""
+        txt = super(EB_CUDA, self).make_module_extra()
+        txt += self.module_generator.set_environment('CUDA_HOME', self.installdir)
+        txt += self.module_generator.set_environment('CUDA_ROOT', self.installdir)
+        txt += self.module_generator.set_environment('CUDA_PATH', self.installdir)
+        self.log.debug("make_module_extra added this: %s", txt)
+        return txt
+
     def make_module_req_guess(self):
         """Specify CUDA custom values for PATH etc."""
 
@@ -198,9 +207,6 @@
             'LD_LIBRARY_PATH': lib_path,
             'LIBRARY_PATH': ['lib64', os.path.join('lib64', 'stubs')],
             'CPATH': inc_path,
-            'CUDA_HOME': [''],
-            'CUDA_ROOT': [''],
-            'CUDA_PATH': [''],
         })
 
         return guesses

{"golden_diff": "diff --git a/easybuild/easyblocks/c/cuda.py b/easybuild/easyblocks/c/cuda.py\n--- a/easybuild/easyblocks/c/cuda.py\n+++ b/easybuild/easyblocks/c/cuda.py\n@@ -173,6 +173,15 @@\n \n         super(EB_CUDA, self).sanity_check_step(custom_paths=custom_paths)\n \n+    def make_module_extra(self):\n+        \"\"\"Set the install directory as CUDA_HOME, CUDA_ROOT, CUDA_PATH.\"\"\"\n+        txt = super(EB_CUDA, self).make_module_extra()\n+        txt += self.module_generator.set_environment('CUDA_HOME', self.installdir)\n+        txt += self.module_generator.set_environment('CUDA_ROOT', self.installdir)\n+        txt += self.module_generator.set_environment('CUDA_PATH', self.installdir)\n+        self.log.debug(\"make_module_extra added this: %s\", txt)\n+        return txt\n+\n     def make_module_req_guess(self):\n         \"\"\"Specify CUDA custom values for PATH etc.\"\"\"\n \n@@ -198,9 +207,6 @@\n             'LD_LIBRARY_PATH': lib_path,\n             'LIBRARY_PATH': ['lib64', os.path.join('lib64', 'stubs')],\n             'CPATH': inc_path,\n-            'CUDA_HOME': [''],\n-            'CUDA_ROOT': [''],\n-            'CUDA_PATH': [''],\n         })\n \n         return guesses\n", "issue": "CUDA_{ROOT,HOME,PATH} are PATH-like?\nSee: https://github.com/easybuilders/easybuild-easyblocks/blob/e3a4cd70357103e1fa463751df13378f217c7ad1/easybuild/easyblocks/c/cuda.py#L191-L193\r\n\r\nThis creates `prepend_path` module commands, instead of `setenv`! Is there a particular reason to do so?\n", "before_files": [{"content": "##\n# This file is an EasyBuild reciPY as per https://github.com/easybuilders/easybuild\n#\n# Copyright:: Copyright 2012-2019 Cyprus Institute / CaSToRC, Uni.Lu, NTUA, Ghent University, Forschungszentrum Juelich GmbH\n# Authors::   George Tsouloupas <g.tsouloupas@cyi.ac.cy>, Fotis Georgatos <fotis@cern.ch>, Kenneth Hoste, Damian Alvarez\n# License::   MIT/GPL\n# $Id$\n#\n# This work implements a part of the HPCBIOS project and is a component of the policy:\n# http://hpcbios.readthedocs.org/en/latest/HPCBIOS_2012-99.html\n##\n\"\"\"\nEasyBuild support for CUDA, implemented as an easyblock\n\nRef: https://speakerdeck.com/ajdecon/introduction-to-the-cuda-toolkit-for-building-applications\n\n@author: George Tsouloupas (Cyprus Institute)\n@author: Fotis Georgatos (Uni.lu)\n@author: Kenneth Hoste (Ghent University)\n@author: Damian Alvarez (Forschungszentrum Juelich)\n@author: Ward Poelmans (Free University of Brussels)\n\"\"\"\nimport os\nimport re\nimport stat\n\nfrom distutils.version import LooseVersion\n\nfrom easybuild.easyblocks.generic.binary import Binary\nfrom easybuild.framework.easyconfig import CUSTOM\nfrom easybuild.tools.build_log import EasyBuildError\nfrom easybuild.tools.filetools import adjust_permissions, patch_perl_script_autoflush, read_file, write_file\nfrom easybuild.tools.run import run_cmd, run_cmd_qa\nfrom easybuild.tools.systemtools import get_shared_lib_ext\n\n# Wrapper script definition\nWRAPPER_TEMPLATE = \"\"\"#!/bin/sh\necho \"$@\" | grep -e '-ccbin' -e '--compiler-bindir' > /dev/null\nif [ $? -eq 0 ];\nthen\n        echo \"ERROR: do not set -ccbin or --compiler-bindir when using the `basename $0` wrapper\"\nelse\n        nvcc -ccbin=%s \"$@\"\n        exit $?\nfi \"\"\"\n\nclass EB_CUDA(Binary):\n    \"\"\"\n    Support for installing CUDA.\n    \"\"\"\n\n    @staticmethod\n    def extra_options():\n        \"\"\"Create a set of wrappers based on a list determined by the easyconfig file\"\"\"\n        extra_vars = {\n            'host_compilers': [None, \"Host compilers for which a wrapper will be generated\", CUSTOM]\n        }\n        return Binary.extra_options(extra_vars)\n\n    def extract_step(self):\n        \"\"\"Extract installer to have more control, e.g. options, patching Perl scripts, etc.\"\"\"\n        execpath = self.src[0]['path']\n        run_cmd(\"/bin/sh \" + execpath + \" --noexec --nox11 --target \" + self.builddir)\n        self.src[0]['finalpath'] = self.builddir\n\n    def install_step(self):\n        \"\"\"Install CUDA using Perl install script.\"\"\"\n\n        # define how to run the installer\n        # script has /usr/bin/perl hardcoded, but we want to have control over which perl is being used\n        if LooseVersion(self.version) <= LooseVersion(\"5\"):\n            install_interpreter = \"perl\"\n            install_script = \"install-linux.pl\"\n            self.cfg.update('installopts', '--prefix=%s' % self.installdir)\n        elif LooseVersion(self.version) > LooseVersion(\"5\") and LooseVersion(self.version) < LooseVersion(\"10.1\"):\n            install_interpreter = \"perl\"\n            install_script = \"cuda-installer.pl\"\n            # note: also including samples (via \"-samplespath=%(installdir)s -samples\") would require libglut\n            self.cfg.update('installopts', \"-verbose -silent -toolkitpath=%s -toolkit\" % self.installdir)\n        else:\n            install_interpreter = \"\"\n            install_script = \"./cuda-installer\"\n            # note: also including samples (via \"-samplespath=%(installdir)s -samples\") would require libglut\n            self.cfg.update('installopts', \"--silent --toolkit --toolkitpath=%s --defaultroot=%s\" % (\n                            self.installdir, self.installdir))\n\n        cmd = \"%(preinstallopts)s %(interpreter)s %(script)s %(installopts)s\" % {\n            'preinstallopts': self.cfg['preinstallopts'],\n            'interpreter': install_interpreter,\n            'script': install_script,\n            'installopts': self.cfg['installopts']\n        }\n\n        # prepare for running install script autonomously\n        qanda = {}\n        stdqa = {\n            # this question is only asked if CUDA tools are already available system-wide\n            r\"Would you like to remove all CUDA files under .*? (yes/no/abort): \": \"no\",\n        }\n        noqanda = [\n            r\"^Configuring\",\n            r\"Installation Complete\",\n            r\"Verifying archive integrity.*\",\n            r\"^Uncompressing NVIDIA CUDA\",\n            r\".* -> .*\",\n        ]\n\n        # patch install script to handle Q&A autonomously\n        if install_interpreter == \"perl\":\n            patch_perl_script_autoflush(os.path.join(self.builddir, install_script))\n\n        # make sure $DISPLAY is not defined, which may lead to (weird) problems\n        # this is workaround for not being able to specify --nox11 to the Perl install scripts\n        if 'DISPLAY' in os.environ:\n            os.environ.pop('DISPLAY')\n\n        # overriding maxhits default value to 300 (300s wait for nothing to change in the output without seeing a known\n        # question)\n        run_cmd_qa(cmd, qanda, std_qa=stdqa, no_qa=noqanda, log_all=True, simple=True, maxhits=300)\n\n        # check if there are patches to apply\n        if len(self.src) > 1:\n            for patch in self.src[1:]:\n                self.log.debug(\"Running patch %s\", patch['name'])\n                run_cmd(\"/bin/sh \" + patch['path'] + \" --accept-eula --silent --installdir=\" + self.installdir)\n\n    def post_install_step(self):\n        \"\"\"Create wrappers for the specified host compilers and generate the appropriate stub symlinks\"\"\"\n        def create_wrapper(wrapper_name, wrapper_comp):\n            \"\"\"Create for a particular compiler, with a particular name\"\"\"\n            wrapper_f = os.path.join(self.installdir, 'bin', wrapper_name)\n            write_file(wrapper_f, WRAPPER_TEMPLATE % wrapper_comp)\n            adjust_permissions(wrapper_f, stat.S_IXUSR|stat.S_IRUSR|stat.S_IXGRP|stat.S_IRGRP|stat.S_IXOTH|stat.S_IROTH)\n\n        # Prepare wrappers to handle a default host compiler other than g++\n        for comp in (self.cfg['host_compilers'] or []):\n            create_wrapper('nvcc_%s' % comp, comp)\n\n        # Run ldconfig to create missing symlinks in the stubs directory (libcuda.so.1, etc)\n        run_cmd(\"ldconfig -N \" + os.path.join(self.installdir, 'lib64', 'stubs'))\n\n        super(EB_CUDA, self).post_install_step()\n\n    def sanity_check_step(self):\n        \"\"\"Custom sanity check for CUDA.\"\"\"\n\n        if LooseVersion(self.version) > LooseVersion(\"9\"):\n            versionfile = read_file(os.path.join(self.installdir, \"version.txt\"))\n            if not re.search(\"Version %s$\" % self.version, versionfile):\n                raise EasyBuildError(\"Unable to find the correct version (%s) in the version.txt file\", self.version)\n\n        shlib_ext = get_shared_lib_ext()\n\n        chk_libdir = [\"lib64\"]\n\n        # Versions higher than 6 do not provide 32 bit libraries\n        if LooseVersion(self.version) < LooseVersion(\"6\"):\n            chk_libdir += [\"lib\"]\n\n        culibs = [\"cublas\", \"cudart\", \"cufft\", \"curand\", \"cusparse\"]\n        custom_paths = {\n            'files': [os.path.join(\"bin\", x) for x in [\"fatbinary\", \"nvcc\", \"nvlink\", \"ptxas\"]] +\n            [os.path.join(\"%s\", \"lib%s.%s\") % (x, y, shlib_ext) for x in chk_libdir for y in culibs],\n            'dirs': [\"include\"],\n        }\n\n        if LooseVersion(self.version) < LooseVersion('7'):\n            custom_paths['files'].append(os.path.join('open64', 'bin', 'nvopencc'))\n        if LooseVersion(self.version) >= LooseVersion('7'):\n            custom_paths['files'].append(os.path.join(\"extras\", \"CUPTI\", \"lib64\", \"libcupti.%s\") % shlib_ext)\n            custom_paths['dirs'].append(os.path.join(\"extras\", \"CUPTI\", \"include\"))\n\n\n        super(EB_CUDA, self).sanity_check_step(custom_paths=custom_paths)\n\n    def make_module_req_guess(self):\n        \"\"\"Specify CUDA custom values for PATH etc.\"\"\"\n\n        guesses = super(EB_CUDA, self).make_module_req_guess()\n\n        # The dirs should be in the order ['open64/bin', 'bin']\n        bin_path = []\n        if LooseVersion(self.version) < LooseVersion('7'):\n            bin_path.append(os.path.join('open64', 'bin'))\n        bin_path.append('bin')\n\n        lib_path = ['lib64']\n        inc_path = ['include']\n        if LooseVersion(self.version) >= LooseVersion('7'):\n            lib_path.append(os.path.join('extras', 'CUPTI', 'lib64'))\n            inc_path.append(os.path.join('extras', 'CUPTI', 'include'))\n            bin_path.append(os.path.join('nvvm', 'bin'))\n            lib_path.append(os.path.join('nvvm', 'lib64'))\n            inc_path.append(os.path.join('nvvm', 'include'))\n\n        guesses.update({\n            'PATH': bin_path,\n            'LD_LIBRARY_PATH': lib_path,\n            'LIBRARY_PATH': ['lib64', os.path.join('lib64', 'stubs')],\n            'CPATH': inc_path,\n            'CUDA_HOME': [''],\n            'CUDA_ROOT': [''],\n            'CUDA_PATH': [''],\n        })\n\n        return guesses\n", "path": "easybuild/easyblocks/c/cuda.py"}], "after_files": [{"content": "##\n# This file is an EasyBuild reciPY as per https://github.com/easybuilders/easybuild\n#\n# Copyright:: Copyright 2012-2019 Cyprus Institute / CaSToRC, Uni.Lu, NTUA, Ghent University, Forschungszentrum Juelich GmbH\n# Authors::   George Tsouloupas <g.tsouloupas@cyi.ac.cy>, Fotis Georgatos <fotis@cern.ch>, Kenneth Hoste, Damian Alvarez\n# License::   MIT/GPL\n# $Id$\n#\n# This work implements a part of the HPCBIOS project and is a component of the policy:\n# http://hpcbios.readthedocs.org/en/latest/HPCBIOS_2012-99.html\n##\n\"\"\"\nEasyBuild support for CUDA, implemented as an easyblock\n\nRef: https://speakerdeck.com/ajdecon/introduction-to-the-cuda-toolkit-for-building-applications\n\n@author: George Tsouloupas (Cyprus Institute)\n@author: Fotis Georgatos (Uni.lu)\n@author: Kenneth Hoste (Ghent University)\n@author: Damian Alvarez (Forschungszentrum Juelich)\n@author: Ward Poelmans (Free University of Brussels)\n\"\"\"\nimport os\nimport re\nimport stat\n\nfrom distutils.version import LooseVersion\n\nfrom easybuild.easyblocks.generic.binary import Binary\nfrom easybuild.framework.easyconfig import CUSTOM\nfrom easybuild.tools.build_log import EasyBuildError\nfrom easybuild.tools.filetools import adjust_permissions, patch_perl_script_autoflush, read_file, write_file\nfrom easybuild.tools.run import run_cmd, run_cmd_qa\nfrom easybuild.tools.systemtools import get_shared_lib_ext\n\n# Wrapper script definition\nWRAPPER_TEMPLATE = \"\"\"#!/bin/sh\necho \"$@\" | grep -e '-ccbin' -e '--compiler-bindir' > /dev/null\nif [ $? -eq 0 ];\nthen\n        echo \"ERROR: do not set -ccbin or --compiler-bindir when using the `basename $0` wrapper\"\nelse\n        nvcc -ccbin=%s \"$@\"\n        exit $?\nfi \"\"\"\n\nclass EB_CUDA(Binary):\n    \"\"\"\n    Support for installing CUDA.\n    \"\"\"\n\n    @staticmethod\n    def extra_options():\n        \"\"\"Create a set of wrappers based on a list determined by the easyconfig file\"\"\"\n        extra_vars = {\n            'host_compilers': [None, \"Host compilers for which a wrapper will be generated\", CUSTOM]\n        }\n        return Binary.extra_options(extra_vars)\n\n    def extract_step(self):\n        \"\"\"Extract installer to have more control, e.g. options, patching Perl scripts, etc.\"\"\"\n        execpath = self.src[0]['path']\n        run_cmd(\"/bin/sh \" + execpath + \" --noexec --nox11 --target \" + self.builddir)\n        self.src[0]['finalpath'] = self.builddir\n\n    def install_step(self):\n        \"\"\"Install CUDA using Perl install script.\"\"\"\n\n        # define how to run the installer\n        # script has /usr/bin/perl hardcoded, but we want to have control over which perl is being used\n        if LooseVersion(self.version) <= LooseVersion(\"5\"):\n            install_interpreter = \"perl\"\n            install_script = \"install-linux.pl\"\n            self.cfg.update('installopts', '--prefix=%s' % self.installdir)\n        elif LooseVersion(self.version) > LooseVersion(\"5\") and LooseVersion(self.version) < LooseVersion(\"10.1\"):\n            install_interpreter = \"perl\"\n            install_script = \"cuda-installer.pl\"\n            # note: also including samples (via \"-samplespath=%(installdir)s -samples\") would require libglut\n            self.cfg.update('installopts', \"-verbose -silent -toolkitpath=%s -toolkit\" % self.installdir)\n        else:\n            install_interpreter = \"\"\n            install_script = \"./cuda-installer\"\n            # note: also including samples (via \"-samplespath=%(installdir)s -samples\") would require libglut\n            self.cfg.update('installopts', \"--silent --toolkit --toolkitpath=%s --defaultroot=%s\" % (\n                            self.installdir, self.installdir))\n\n        cmd = \"%(preinstallopts)s %(interpreter)s %(script)s %(installopts)s\" % {\n            'preinstallopts': self.cfg['preinstallopts'],\n            'interpreter': install_interpreter,\n            'script': install_script,\n            'installopts': self.cfg['installopts']\n        }\n\n        # prepare for running install script autonomously\n        qanda = {}\n        stdqa = {\n            # this question is only asked if CUDA tools are already available system-wide\n            r\"Would you like to remove all CUDA files under .*? (yes/no/abort): \": \"no\",\n        }\n        noqanda = [\n            r\"^Configuring\",\n            r\"Installation Complete\",\n            r\"Verifying archive integrity.*\",\n            r\"^Uncompressing NVIDIA CUDA\",\n            r\".* -> .*\",\n        ]\n\n        # patch install script to handle Q&A autonomously\n        if install_interpreter == \"perl\":\n            patch_perl_script_autoflush(os.path.join(self.builddir, install_script))\n\n        # make sure $DISPLAY is not defined, which may lead to (weird) problems\n        # this is workaround for not being able to specify --nox11 to the Perl install scripts\n        if 'DISPLAY' in os.environ:\n            os.environ.pop('DISPLAY')\n\n        # overriding maxhits default value to 300 (300s wait for nothing to change in the output without seeing a known\n        # question)\n        run_cmd_qa(cmd, qanda, std_qa=stdqa, no_qa=noqanda, log_all=True, simple=True, maxhits=300)\n\n        # check if there are patches to apply\n        if len(self.src) > 1:\n            for patch in self.src[1:]:\n                self.log.debug(\"Running patch %s\", patch['name'])\n                run_cmd(\"/bin/sh \" + patch['path'] + \" --accept-eula --silent --installdir=\" + self.installdir)\n\n    def post_install_step(self):\n        \"\"\"Create wrappers for the specified host compilers and generate the appropriate stub symlinks\"\"\"\n        def create_wrapper(wrapper_name, wrapper_comp):\n            \"\"\"Create for a particular compiler, with a particular name\"\"\"\n            wrapper_f = os.path.join(self.installdir, 'bin', wrapper_name)\n            write_file(wrapper_f, WRAPPER_TEMPLATE % wrapper_comp)\n            adjust_permissions(wrapper_f, stat.S_IXUSR|stat.S_IRUSR|stat.S_IXGRP|stat.S_IRGRP|stat.S_IXOTH|stat.S_IROTH)\n\n        # Prepare wrappers to handle a default host compiler other than g++\n        for comp in (self.cfg['host_compilers'] or []):\n            create_wrapper('nvcc_%s' % comp, comp)\n\n        # Run ldconfig to create missing symlinks in the stubs directory (libcuda.so.1, etc)\n        run_cmd(\"ldconfig -N \" + os.path.join(self.installdir, 'lib64', 'stubs'))\n\n        super(EB_CUDA, self).post_install_step()\n\n    def sanity_check_step(self):\n        \"\"\"Custom sanity check for CUDA.\"\"\"\n\n        if LooseVersion(self.version) > LooseVersion(\"9\"):\n            versionfile = read_file(os.path.join(self.installdir, \"version.txt\"))\n            if not re.search(\"Version %s$\" % self.version, versionfile):\n                raise EasyBuildError(\"Unable to find the correct version (%s) in the version.txt file\", self.version)\n\n        shlib_ext = get_shared_lib_ext()\n\n        chk_libdir = [\"lib64\"]\n\n        # Versions higher than 6 do not provide 32 bit libraries\n        if LooseVersion(self.version) < LooseVersion(\"6\"):\n            chk_libdir += [\"lib\"]\n\n        culibs = [\"cublas\", \"cudart\", \"cufft\", \"curand\", \"cusparse\"]\n        custom_paths = {\n            'files': [os.path.join(\"bin\", x) for x in [\"fatbinary\", \"nvcc\", \"nvlink\", \"ptxas\"]] +\n            [os.path.join(\"%s\", \"lib%s.%s\") % (x, y, shlib_ext) for x in chk_libdir for y in culibs],\n            'dirs': [\"include\"],\n        }\n\n        if LooseVersion(self.version) < LooseVersion('7'):\n            custom_paths['files'].append(os.path.join('open64', 'bin', 'nvopencc'))\n        if LooseVersion(self.version) >= LooseVersion('7'):\n            custom_paths['files'].append(os.path.join(\"extras\", \"CUPTI\", \"lib64\", \"libcupti.%s\") % shlib_ext)\n            custom_paths['dirs'].append(os.path.join(\"extras\", \"CUPTI\", \"include\"))\n\n\n        super(EB_CUDA, self).sanity_check_step(custom_paths=custom_paths)\n\n    def make_module_extra(self):\n        \"\"\"Set the install directory as CUDA_HOME, CUDA_ROOT, CUDA_PATH.\"\"\"\n        txt = super(EB_CUDA, self).make_module_extra()\n        txt += self.module_generator.set_environment('CUDA_HOME', self.installdir)\n        txt += self.module_generator.set_environment('CUDA_ROOT', self.installdir)\n        txt += self.module_generator.set_environment('CUDA_PATH', self.installdir)\n        self.log.debug(\"make_module_extra added this: %s\", txt)\n        return txt\n\n    def make_module_req_guess(self):\n        \"\"\"Specify CUDA custom values for PATH etc.\"\"\"\n\n        guesses = super(EB_CUDA, self).make_module_req_guess()\n\n        # The dirs should be in the order ['open64/bin', 'bin']\n        bin_path = []\n        if LooseVersion(self.version) < LooseVersion('7'):\n            bin_path.append(os.path.join('open64', 'bin'))\n        bin_path.append('bin')\n\n        lib_path = ['lib64']\n        inc_path = ['include']\n        if LooseVersion(self.version) >= LooseVersion('7'):\n            lib_path.append(os.path.join('extras', 'CUPTI', 'lib64'))\n            inc_path.append(os.path.join('extras', 'CUPTI', 'include'))\n            bin_path.append(os.path.join('nvvm', 'bin'))\n            lib_path.append(os.path.join('nvvm', 'lib64'))\n            inc_path.append(os.path.join('nvvm', 'include'))\n\n        guesses.update({\n            'PATH': bin_path,\n            'LD_LIBRARY_PATH': lib_path,\n            'LIBRARY_PATH': ['lib64', os.path.join('lib64', 'stubs')],\n            'CPATH': inc_path,\n        })\n\n        return guesses\n", "path": "easybuild/easyblocks/c/cuda.py"}]}