We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
MATLAB changes `$LD_LIBRARY_PATH`, breaks Qt apps
I've been debugging an issue with an app that depends on the Qt5 module. The app won't start because it can't find Qt's platform plugins:

```
qt.qpa.plugin: Could not find the Qt platform plugin "xcb" in ""
```

I wrote a minimal Qt app to find the cause of this and it turns out to be MATLAB. More specifically, the fact that the MATLAB module prepends `LD_LIBRARY_PATH` with `$EBROOTMATLAB/bin/glnxa64`, a directory that contains tons of bundled MATLAB libraries, including their own versions of essential Qt5 libraries and many other unrelated libs which could potentially interfere with other modules too. 

This change was introduced in #2008, presumably to make it easier for MCR compiled apps to load. For MATLAB itself this does not seem to be necessary because the `matlab` startup script sets `LD_LIBRARY_PATH` and other required environment variables on invocation. 

The MATLAB [docs](https://www.mathworks.com/help/compiler/mcr-path-settings-for-run-time-deployment.html) cautions (bottom of the page) against setting LD_LIBRARY_PATH permanently on Linux due to this interference risk with other software. They suggest to "run MATLAB Compiler applications using the generated shell script" instead.

I would propose to revert #2008 but would obviously like to hear @smoors  and maybe other's opinion on this first.




--- 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/m/matlab.py`
Content:
```
1 ##
2 # Copyright 2009-2023 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 installing MATLAB, 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: Pieter De Baets (Ghent University)
32 @author: Jens Timmerman (Ghent University)
33 @author: Fotis Georgatos (Uni.Lu, NTUA)
34 """
35 import re
36 import os
37 import stat
38 import tempfile
39 
40 from distutils.version import LooseVersion
41 
42 from easybuild.easyblocks.generic.packedbinary import PackedBinary
43 from easybuild.framework.easyconfig import CUSTOM
44 from easybuild.tools.build_log import EasyBuildError
45 from easybuild.tools.filetools import adjust_permissions, change_dir, copy_file, read_file, write_file
46 from easybuild.tools.py2vs3 import string_type
47 from easybuild.tools.run import run_cmd
48 
49 
50 class EB_MATLAB(PackedBinary):
51     """Support for installing MATLAB."""
52 
53     def __init__(self, *args, **kwargs):
54         """Add extra config options specific to MATLAB."""
55         super(EB_MATLAB, self).__init__(*args, **kwargs)
56         self.comp_fam = None
57         self.configfile = os.path.join(self.builddir, 'my_installer_input.txt')
58         self.outputfile = os.path.join(self.builddir, 'my_installer_output.txt')
59 
60     @staticmethod
61     def extra_options():
62         extra_vars = {
63             'java_options': ['-Xmx256m', "$_JAVA_OPTIONS value set for install and in module file.", CUSTOM],
64             'key': [None, "Installation key(s), make one install for each key. Single key or a list of keys", CUSTOM],
65         }
66         return PackedBinary.extra_options(extra_vars)
67 
68     def configure_step(self):
69         """Configure MATLAB installation: create license file."""
70 
71         licfile = self.cfg['license_file']
72         if licfile is None:
73             licserv = self.cfg['license_server']
74             if licserv is None:
75                 licserv = os.getenv('EB_MATLAB_LICENSE_SERVER', 'license.example.com')
76             licport = self.cfg['license_server_port']
77             if licport is None:
78                 licport = os.getenv('EB_MATLAB_LICENSE_SERVER_PORT', '00000')
79             # create license file
80             lictxt = '\n'.join([
81                 "SERVER %s 000000000000 %s" % (licserv, licport),
82                 "USE_SERVER",
83             ])
84 
85             licfile = os.path.join(self.builddir, 'matlab.lic')
86             write_file(licfile, lictxt)
87 
88         try:
89             copy_file(os.path.join(self.cfg['start_dir'], 'installer_input.txt'), self.configfile)
90             adjust_permissions(self.configfile, stat.S_IWUSR)
91 
92             # read file in binary mode to avoid UTF-8 encoding issues when using Python 3,
93             # due to non-UTF-8 characters...
94             config = read_file(self.configfile, mode='rb')
95 
96             # use raw byte strings (must be 'br', not 'rb'),
97             # required when using Python 3 because file was read in binary mode
98             regdest = re.compile(br"^# destinationFolder=.*", re.M)
99             regagree = re.compile(br"^# agreeToLicense=.*", re.M)
100             regmode = re.compile(br"^# mode=.*", re.M)
101             reglicpath = re.compile(br"^# licensePath=.*", re.M)
102             regoutfile = re.compile(br"^# outputFile=.*", re.M)
103 
104             # must use byte-strings here when using Python 3, see above
105             config = regdest.sub(b"destinationFolder=%s" % self.installdir.encode('utf-8'), config)
106             config = regagree.sub(b"agreeToLicense=Yes", config)
107             config = regmode.sub(b"mode=silent", config)
108             config = reglicpath.sub(b"licensePath=%s" % licfile.encode('utf-8'), config)
109             config = regoutfile.sub(b"outputFile=%s" % self.outputfile.encode('utf-8'), config)
110 
111             write_file(self.configfile, config)
112 
113         except IOError as err:
114             raise EasyBuildError("Failed to create installation config file %s: %s", self.configfile, err)
115 
116         self.log.debug('configuration file written to %s:\n %s', self.configfile, config)
117 
118     def install_step(self):
119         """MATLAB install procedure using 'install' command."""
120 
121         src = os.path.join(self.cfg['start_dir'], 'install')
122 
123         # make sure install script is executable
124         adjust_permissions(src, stat.S_IXUSR)
125 
126         if LooseVersion(self.version) >= LooseVersion('2016b'):
127             perm_dirs = [os.path.join(self.cfg['start_dir'], 'bin', 'glnxa64')]
128             if LooseVersion(self.version) < LooseVersion('2021b'):
129                 jdir = os.path.join(self.cfg['start_dir'], 'sys', 'java', 'jre', 'glnxa64', 'jre', 'bin')
130                 perm_dirs.append(jdir)
131             for perm_dir in perm_dirs:
132                 adjust_permissions(perm_dir, stat.S_IXUSR)
133 
134         # make sure $DISPLAY is not defined, which may lead to (hard to trace) problems
135         # this is a workaround for not being able to specify --nodisplay to the install scripts
136         if 'DISPLAY' in os.environ:
137             os.environ.pop('DISPLAY')
138 
139         if '_JAVA_OPTIONS' not in self.cfg['preinstallopts']:
140             java_opts = 'export _JAVA_OPTIONS="%s" && ' % self.cfg['java_options']
141             self.cfg['preinstallopts'] = java_opts + self.cfg['preinstallopts']
142         if LooseVersion(self.version) >= LooseVersion('2016b'):
143             change_dir(self.builddir)
144 
145         # Build the cmd string
146         cmdlist = [
147             self.cfg['preinstallopts'],
148             src,
149             '-inputFile',
150             self.configfile,
151         ]
152         if LooseVersion(self.version) < LooseVersion('2020a'):
153             # MATLAB installers < 2020a ignore $TMPDIR (always use /tmp) and might need a large tmpdir
154             tmpdir = tempfile.mkdtemp()
155             cmdlist.extend([
156                 '-v',
157                 '-tmpdir',
158                 tmpdir,
159             ])
160         cmdlist.append(self.cfg['installopts'])
161         cmd = ' '.join(cmdlist)
162 
163         keys = self.cfg['key']
164         if keys is None:
165             try:
166                 keys = os.environ['EB_MATLAB_KEY']
167             except KeyError:
168                 raise EasyBuildError("The MATLAB install key is not set. This can be set either with the environment "
169                                      "variable EB_MATLAB_KEY or by the easyconfig variable 'key'.")
170         if isinstance(keys, string_type):
171             keys = keys.split(',')
172 
173         # Compile the installation key regex outside of the loop
174         regkey = re.compile(br"^(# )?fileInstallationKey=.*", re.M)
175 
176         # Run an install for each key
177         for i, key in enumerate(keys):
178 
179             self.log.info('Installing MATLAB with key %s of %s', i + 1, len(keys))
180 
181             try:
182                 config = read_file(self.configfile, mode='rb')
183                 config = regkey.sub(b"fileInstallationKey=%s" % key.encode('utf-8'), config)
184                 write_file(self.configfile, config)
185 
186             except IOError as err:
187                 raise EasyBuildError("Failed to update config file %s: %s", self.configfile, err)
188 
189             (out, _) = run_cmd(cmd, log_all=True, simple=False)
190 
191             # check installer output for known signs of trouble
192             patterns = [
193                 "Error: You have entered an invalid File Installation Key",
194                 "Not a valid key",
195                 "All selected products are already installed",
196                 "The application encountered an unexpected error and needs to close",
197                 "Error: Unable to write to",
198                 "Exiting with status -\\d",
199                 "End - Unsuccessful",
200             ]
201 
202             for pattern in patterns:
203                 regex = re.compile(pattern, re.I)
204                 if regex.search(out):
205                     raise EasyBuildError("Found error pattern '%s' in output of installation command '%s': %s",
206                                          regex.pattern, cmd, out)
207                 with open(self.outputfile) as f:
208                     if regex.search(f.read()):
209                         raise EasyBuildError("Found error pattern '%s' in output file of installer",
210                                              regex.pattern)
211 
212     def sanity_check_step(self):
213         """Custom sanity check for MATLAB."""
214         custom_paths = {
215             'files': ["bin/matlab", "bin/glnxa64/MATLAB", "toolbox/local/classpath.txt"],
216             'dirs': ["java/jar"],
217         }
218         super(EB_MATLAB, self).sanity_check_step(custom_paths=custom_paths)
219 
220     def make_module_extra(self):
221         """Extend PATH and set proper _JAVA_OPTIONS (e.g., -Xmx)."""
222         txt = super(EB_MATLAB, self).make_module_extra()
223 
224         # make MATLAB runtime available
225         if LooseVersion(self.version) >= LooseVersion('2017a'):
226             for ldlibdir in ['runtime', 'bin', os.path.join('sys', 'os')]:
227                 libdir = os.path.join(ldlibdir, 'glnxa64')
228                 txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', libdir)
229         if self.cfg['java_options']:
230             txt += self.module_generator.set_environment('_JAVA_OPTIONS', self.cfg['java_options'])
231         return txt
232
```
--- 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/m/matlab.py b/easybuild/easyblocks/m/matlab.py
--- a/easybuild/easyblocks/m/matlab.py
+++ b/easybuild/easyblocks/m/matlab.py
@@ -221,11 +221,6 @@
         """Extend PATH and set proper _JAVA_OPTIONS (e.g., -Xmx)."""
         txt = super(EB_MATLAB, self).make_module_extra()
 
-        # make MATLAB runtime available
-        if LooseVersion(self.version) >= LooseVersion('2017a'):
-            for ldlibdir in ['runtime', 'bin', os.path.join('sys', 'os')]:
-                libdir = os.path.join(ldlibdir, 'glnxa64')
-                txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', libdir)
         if self.cfg['java_options']:
             txt += self.module_generator.set_environment('_JAVA_OPTIONS', self.cfg['java_options'])
         return txt

{"golden_diff": "diff --git a/easybuild/easyblocks/m/matlab.py b/easybuild/easyblocks/m/matlab.py\n--- a/easybuild/easyblocks/m/matlab.py\n+++ b/easybuild/easyblocks/m/matlab.py\n@@ -221,11 +221,6 @@\n         \"\"\"Extend PATH and set proper _JAVA_OPTIONS (e.g., -Xmx).\"\"\"\n         txt = super(EB_MATLAB, self).make_module_extra()\n \n-        # make MATLAB runtime available\n-        if LooseVersion(self.version) >= LooseVersion('2017a'):\n-            for ldlibdir in ['runtime', 'bin', os.path.join('sys', 'os')]:\n-                libdir = os.path.join(ldlibdir, 'glnxa64')\n-                txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', libdir)\n         if self.cfg['java_options']:\n             txt += self.module_generator.set_environment('_JAVA_OPTIONS', self.cfg['java_options'])\n         return txt\n", "issue": "MATLAB changes `$LD_LIBRARY_PATH`, breaks Qt apps\nI've been debugging an issue with an app that depends on the Qt5 module. The app won't start because it can't find Qt's platform plugins:\r\n\r\n```\r\nqt.qpa.plugin: Could not find the Qt platform plugin \"xcb\" in \"\"\r\n```\r\n\r\nI wrote a minimal Qt app to find the cause of this and it turns out to be MATLAB. More specifically, the fact that the MATLAB module prepends `LD_LIBRARY_PATH` with `$EBROOTMATLAB/bin/glnxa64`, a directory that contains tons of bundled MATLAB libraries, including their own versions of essential Qt5 libraries and many other unrelated libs which could potentially interfere with other modules too. \r\n\r\nThis change was introduced in #2008, presumably to make it easier for MCR compiled apps to load. For MATLAB itself this does not seem to be necessary because the `matlab` startup script sets `LD_LIBRARY_PATH` and other required environment variables on invocation. \r\n\r\nThe MATLAB [docs](https://www.mathworks.com/help/compiler/mcr-path-settings-for-run-time-deployment.html) cautions (bottom of the page) against setting LD_LIBRARY_PATH permanently on Linux due to this interference risk with other software. They suggest to \"run MATLAB Compiler applications using the generated shell script\" instead.\r\n\r\nI would propose to revert #2008 but would obviously like to hear @smoors  and maybe other's opinion on this first.\r\n\r\n\r\n\n", "before_files": [{"content": "##\n# Copyright 2009-2023 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 installing MATLAB, 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: Pieter De Baets (Ghent University)\n@author: Jens Timmerman (Ghent University)\n@author: Fotis Georgatos (Uni.Lu, NTUA)\n\"\"\"\nimport re\nimport os\nimport stat\nimport tempfile\n\nfrom distutils.version import LooseVersion\n\nfrom easybuild.easyblocks.generic.packedbinary import PackedBinary\nfrom easybuild.framework.easyconfig import CUSTOM\nfrom easybuild.tools.build_log import EasyBuildError\nfrom easybuild.tools.filetools import adjust_permissions, change_dir, copy_file, read_file, write_file\nfrom easybuild.tools.py2vs3 import string_type\nfrom easybuild.tools.run import run_cmd\n\n\nclass EB_MATLAB(PackedBinary):\n    \"\"\"Support for installing MATLAB.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"Add extra config options specific to MATLAB.\"\"\"\n        super(EB_MATLAB, self).__init__(*args, **kwargs)\n        self.comp_fam = None\n        self.configfile = os.path.join(self.builddir, 'my_installer_input.txt')\n        self.outputfile = os.path.join(self.builddir, 'my_installer_output.txt')\n\n    @staticmethod\n    def extra_options():\n        extra_vars = {\n            'java_options': ['-Xmx256m', \"$_JAVA_OPTIONS value set for install and in module file.\", CUSTOM],\n            'key': [None, \"Installation key(s), make one install for each key. Single key or a list of keys\", CUSTOM],\n        }\n        return PackedBinary.extra_options(extra_vars)\n\n    def configure_step(self):\n        \"\"\"Configure MATLAB installation: create license file.\"\"\"\n\n        licfile = self.cfg['license_file']\n        if licfile is None:\n            licserv = self.cfg['license_server']\n            if licserv is None:\n                licserv = os.getenv('EB_MATLAB_LICENSE_SERVER', 'license.example.com')\n            licport = self.cfg['license_server_port']\n            if licport is None:\n                licport = os.getenv('EB_MATLAB_LICENSE_SERVER_PORT', '00000')\n            # create license file\n            lictxt = '\\n'.join([\n                \"SERVER %s 000000000000 %s\" % (licserv, licport),\n                \"USE_SERVER\",\n            ])\n\n            licfile = os.path.join(self.builddir, 'matlab.lic')\n            write_file(licfile, lictxt)\n\n        try:\n            copy_file(os.path.join(self.cfg['start_dir'], 'installer_input.txt'), self.configfile)\n            adjust_permissions(self.configfile, stat.S_IWUSR)\n\n            # read file in binary mode to avoid UTF-8 encoding issues when using Python 3,\n            # due to non-UTF-8 characters...\n            config = read_file(self.configfile, mode='rb')\n\n            # use raw byte strings (must be 'br', not 'rb'),\n            # required when using Python 3 because file was read in binary mode\n            regdest = re.compile(br\"^# destinationFolder=.*\", re.M)\n            regagree = re.compile(br\"^# agreeToLicense=.*\", re.M)\n            regmode = re.compile(br\"^# mode=.*\", re.M)\n            reglicpath = re.compile(br\"^# licensePath=.*\", re.M)\n            regoutfile = re.compile(br\"^# outputFile=.*\", re.M)\n\n            # must use byte-strings here when using Python 3, see above\n            config = regdest.sub(b\"destinationFolder=%s\" % self.installdir.encode('utf-8'), config)\n            config = regagree.sub(b\"agreeToLicense=Yes\", config)\n            config = regmode.sub(b\"mode=silent\", config)\n            config = reglicpath.sub(b\"licensePath=%s\" % licfile.encode('utf-8'), config)\n            config = regoutfile.sub(b\"outputFile=%s\" % self.outputfile.encode('utf-8'), config)\n\n            write_file(self.configfile, config)\n\n        except IOError as err:\n            raise EasyBuildError(\"Failed to create installation config file %s: %s\", self.configfile, err)\n\n        self.log.debug('configuration file written to %s:\\n %s', self.configfile, config)\n\n    def install_step(self):\n        \"\"\"MATLAB install procedure using 'install' command.\"\"\"\n\n        src = os.path.join(self.cfg['start_dir'], 'install')\n\n        # make sure install script is executable\n        adjust_permissions(src, stat.S_IXUSR)\n\n        if LooseVersion(self.version) >= LooseVersion('2016b'):\n            perm_dirs = [os.path.join(self.cfg['start_dir'], 'bin', 'glnxa64')]\n            if LooseVersion(self.version) < LooseVersion('2021b'):\n                jdir = os.path.join(self.cfg['start_dir'], 'sys', 'java', 'jre', 'glnxa64', 'jre', 'bin')\n                perm_dirs.append(jdir)\n            for perm_dir in perm_dirs:\n                adjust_permissions(perm_dir, stat.S_IXUSR)\n\n        # make sure $DISPLAY is not defined, which may lead to (hard to trace) problems\n        # this is a workaround for not being able to specify --nodisplay to the install scripts\n        if 'DISPLAY' in os.environ:\n            os.environ.pop('DISPLAY')\n\n        if '_JAVA_OPTIONS' not in self.cfg['preinstallopts']:\n            java_opts = 'export _JAVA_OPTIONS=\"%s\" && ' % self.cfg['java_options']\n            self.cfg['preinstallopts'] = java_opts + self.cfg['preinstallopts']\n        if LooseVersion(self.version) >= LooseVersion('2016b'):\n            change_dir(self.builddir)\n\n        # Build the cmd string\n        cmdlist = [\n            self.cfg['preinstallopts'],\n            src,\n            '-inputFile',\n            self.configfile,\n        ]\n        if LooseVersion(self.version) < LooseVersion('2020a'):\n            # MATLAB installers < 2020a ignore $TMPDIR (always use /tmp) and might need a large tmpdir\n            tmpdir = tempfile.mkdtemp()\n            cmdlist.extend([\n                '-v',\n                '-tmpdir',\n                tmpdir,\n            ])\n        cmdlist.append(self.cfg['installopts'])\n        cmd = ' '.join(cmdlist)\n\n        keys = self.cfg['key']\n        if keys is None:\n            try:\n                keys = os.environ['EB_MATLAB_KEY']\n            except KeyError:\n                raise EasyBuildError(\"The MATLAB install key is not set. This can be set either with the environment \"\n                                     \"variable EB_MATLAB_KEY or by the easyconfig variable 'key'.\")\n        if isinstance(keys, string_type):\n            keys = keys.split(',')\n\n        # Compile the installation key regex outside of the loop\n        regkey = re.compile(br\"^(# )?fileInstallationKey=.*\", re.M)\n\n        # Run an install for each key\n        for i, key in enumerate(keys):\n\n            self.log.info('Installing MATLAB with key %s of %s', i + 1, len(keys))\n\n            try:\n                config = read_file(self.configfile, mode='rb')\n                config = regkey.sub(b\"fileInstallationKey=%s\" % key.encode('utf-8'), config)\n                write_file(self.configfile, config)\n\n            except IOError as err:\n                raise EasyBuildError(\"Failed to update config file %s: %s\", self.configfile, err)\n\n            (out, _) = run_cmd(cmd, log_all=True, simple=False)\n\n            # check installer output for known signs of trouble\n            patterns = [\n                \"Error: You have entered an invalid File Installation Key\",\n                \"Not a valid key\",\n                \"All selected products are already installed\",\n                \"The application encountered an unexpected error and needs to close\",\n                \"Error: Unable to write to\",\n                \"Exiting with status -\\\\d\",\n                \"End - Unsuccessful\",\n            ]\n\n            for pattern in patterns:\n                regex = re.compile(pattern, re.I)\n                if regex.search(out):\n                    raise EasyBuildError(\"Found error pattern '%s' in output of installation command '%s': %s\",\n                                         regex.pattern, cmd, out)\n                with open(self.outputfile) as f:\n                    if regex.search(f.read()):\n                        raise EasyBuildError(\"Found error pattern '%s' in output file of installer\",\n                                             regex.pattern)\n\n    def sanity_check_step(self):\n        \"\"\"Custom sanity check for MATLAB.\"\"\"\n        custom_paths = {\n            'files': [\"bin/matlab\", \"bin/glnxa64/MATLAB\", \"toolbox/local/classpath.txt\"],\n            'dirs': [\"java/jar\"],\n        }\n        super(EB_MATLAB, self).sanity_check_step(custom_paths=custom_paths)\n\n    def make_module_extra(self):\n        \"\"\"Extend PATH and set proper _JAVA_OPTIONS (e.g., -Xmx).\"\"\"\n        txt = super(EB_MATLAB, self).make_module_extra()\n\n        # make MATLAB runtime available\n        if LooseVersion(self.version) >= LooseVersion('2017a'):\n            for ldlibdir in ['runtime', 'bin', os.path.join('sys', 'os')]:\n                libdir = os.path.join(ldlibdir, 'glnxa64')\n                txt += self.module_generator.prepend_paths('LD_LIBRARY_PATH', libdir)\n        if self.cfg['java_options']:\n            txt += self.module_generator.set_environment('_JAVA_OPTIONS', self.cfg['java_options'])\n        return txt\n", "path": "easybuild/easyblocks/m/matlab.py"}], "after_files": [{"content": "##\n# Copyright 2009-2023 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 installing MATLAB, 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: Pieter De Baets (Ghent University)\n@author: Jens Timmerman (Ghent University)\n@author: Fotis Georgatos (Uni.Lu, NTUA)\n\"\"\"\nimport re\nimport os\nimport stat\nimport tempfile\n\nfrom distutils.version import LooseVersion\n\nfrom easybuild.easyblocks.generic.packedbinary import PackedBinary\nfrom easybuild.framework.easyconfig import CUSTOM\nfrom easybuild.tools.build_log import EasyBuildError\nfrom easybuild.tools.filetools import adjust_permissions, change_dir, copy_file, read_file, write_file\nfrom easybuild.tools.py2vs3 import string_type\nfrom easybuild.tools.run import run_cmd\n\n\nclass EB_MATLAB(PackedBinary):\n    \"\"\"Support for installing MATLAB.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"Add extra config options specific to MATLAB.\"\"\"\n        super(EB_MATLAB, self).__init__(*args, **kwargs)\n        self.comp_fam = None\n        self.configfile = os.path.join(self.builddir, 'my_installer_input.txt')\n        self.outputfile = os.path.join(self.builddir, 'my_installer_output.txt')\n\n    @staticmethod\n    def extra_options():\n        extra_vars = {\n            'java_options': ['-Xmx256m', \"$_JAVA_OPTIONS value set for install and in module file.\", CUSTOM],\n            'key': [None, \"Installation key(s), make one install for each key. Single key or a list of keys\", CUSTOM],\n        }\n        return PackedBinary.extra_options(extra_vars)\n\n    def configure_step(self):\n        \"\"\"Configure MATLAB installation: create license file.\"\"\"\n\n        licfile = self.cfg['license_file']\n        if licfile is None:\n            licserv = self.cfg['license_server']\n            if licserv is None:\n                licserv = os.getenv('EB_MATLAB_LICENSE_SERVER', 'license.example.com')\n            licport = self.cfg['license_server_port']\n            if licport is None:\n                licport = os.getenv('EB_MATLAB_LICENSE_SERVER_PORT', '00000')\n            # create license file\n            lictxt = '\\n'.join([\n                \"SERVER %s 000000000000 %s\" % (licserv, licport),\n                \"USE_SERVER\",\n            ])\n\n            licfile = os.path.join(self.builddir, 'matlab.lic')\n            write_file(licfile, lictxt)\n\n        try:\n            copy_file(os.path.join(self.cfg['start_dir'], 'installer_input.txt'), self.configfile)\n            adjust_permissions(self.configfile, stat.S_IWUSR)\n\n            # read file in binary mode to avoid UTF-8 encoding issues when using Python 3,\n            # due to non-UTF-8 characters...\n            config = read_file(self.configfile, mode='rb')\n\n            # use raw byte strings (must be 'br', not 'rb'),\n            # required when using Python 3 because file was read in binary mode\n            regdest = re.compile(br\"^# destinationFolder=.*\", re.M)\n            regagree = re.compile(br\"^# agreeToLicense=.*\", re.M)\n            regmode = re.compile(br\"^# mode=.*\", re.M)\n            reglicpath = re.compile(br\"^# licensePath=.*\", re.M)\n            regoutfile = re.compile(br\"^# outputFile=.*\", re.M)\n\n            # must use byte-strings here when using Python 3, see above\n            config = regdest.sub(b\"destinationFolder=%s\" % self.installdir.encode('utf-8'), config)\n            config = regagree.sub(b\"agreeToLicense=Yes\", config)\n            config = regmode.sub(b\"mode=silent\", config)\n            config = reglicpath.sub(b\"licensePath=%s\" % licfile.encode('utf-8'), config)\n            config = regoutfile.sub(b\"outputFile=%s\" % self.outputfile.encode('utf-8'), config)\n\n            write_file(self.configfile, config)\n\n        except IOError as err:\n            raise EasyBuildError(\"Failed to create installation config file %s: %s\", self.configfile, err)\n\n        self.log.debug('configuration file written to %s:\\n %s', self.configfile, config)\n\n    def install_step(self):\n        \"\"\"MATLAB install procedure using 'install' command.\"\"\"\n\n        src = os.path.join(self.cfg['start_dir'], 'install')\n\n        # make sure install script is executable\n        adjust_permissions(src, stat.S_IXUSR)\n\n        if LooseVersion(self.version) >= LooseVersion('2016b'):\n            perm_dirs = [os.path.join(self.cfg['start_dir'], 'bin', 'glnxa64')]\n            if LooseVersion(self.version) < LooseVersion('2021b'):\n                jdir = os.path.join(self.cfg['start_dir'], 'sys', 'java', 'jre', 'glnxa64', 'jre', 'bin')\n                perm_dirs.append(jdir)\n            for perm_dir in perm_dirs:\n                adjust_permissions(perm_dir, stat.S_IXUSR)\n\n        # make sure $DISPLAY is not defined, which may lead to (hard to trace) problems\n        # this is a workaround for not being able to specify --nodisplay to the install scripts\n        if 'DISPLAY' in os.environ:\n            os.environ.pop('DISPLAY')\n\n        if '_JAVA_OPTIONS' not in self.cfg['preinstallopts']:\n            java_opts = 'export _JAVA_OPTIONS=\"%s\" && ' % self.cfg['java_options']\n            self.cfg['preinstallopts'] = java_opts + self.cfg['preinstallopts']\n        if LooseVersion(self.version) >= LooseVersion('2016b'):\n            change_dir(self.builddir)\n\n        # Build the cmd string\n        cmdlist = [\n            self.cfg['preinstallopts'],\n            src,\n            '-inputFile',\n            self.configfile,\n        ]\n        if LooseVersion(self.version) < LooseVersion('2020a'):\n            # MATLAB installers < 2020a ignore $TMPDIR (always use /tmp) and might need a large tmpdir\n            tmpdir = tempfile.mkdtemp()\n            cmdlist.extend([\n                '-v',\n                '-tmpdir',\n                tmpdir,\n            ])\n        cmdlist.append(self.cfg['installopts'])\n        cmd = ' '.join(cmdlist)\n\n        keys = self.cfg['key']\n        if keys is None:\n            try:\n                keys = os.environ['EB_MATLAB_KEY']\n            except KeyError:\n                raise EasyBuildError(\"The MATLAB install key is not set. This can be set either with the environment \"\n                                     \"variable EB_MATLAB_KEY or by the easyconfig variable 'key'.\")\n        if isinstance(keys, string_type):\n            keys = keys.split(',')\n\n        # Compile the installation key regex outside of the loop\n        regkey = re.compile(br\"^(# )?fileInstallationKey=.*\", re.M)\n\n        # Run an install for each key\n        for i, key in enumerate(keys):\n\n            self.log.info('Installing MATLAB with key %s of %s', i + 1, len(keys))\n\n            try:\n                config = read_file(self.configfile, mode='rb')\n                config = regkey.sub(b\"fileInstallationKey=%s\" % key.encode('utf-8'), config)\n                write_file(self.configfile, config)\n\n            except IOError as err:\n                raise EasyBuildError(\"Failed to update config file %s: %s\", self.configfile, err)\n\n            (out, _) = run_cmd(cmd, log_all=True, simple=False)\n\n            # check installer output for known signs of trouble\n            patterns = [\n                \"Error: You have entered an invalid File Installation Key\",\n                \"Not a valid key\",\n                \"All selected products are already installed\",\n                \"The application encountered an unexpected error and needs to close\",\n                \"Error: Unable to write to\",\n                \"Exiting with status -\\\\d\",\n                \"End - Unsuccessful\",\n            ]\n\n            for pattern in patterns:\n                regex = re.compile(pattern, re.I)\n                if regex.search(out):\n                    raise EasyBuildError(\"Found error pattern '%s' in output of installation command '%s': %s\",\n                                         regex.pattern, cmd, out)\n                with open(self.outputfile) as f:\n                    if regex.search(f.read()):\n                        raise EasyBuildError(\"Found error pattern '%s' in output file of installer\",\n                                             regex.pattern)\n\n    def sanity_check_step(self):\n        \"\"\"Custom sanity check for MATLAB.\"\"\"\n        custom_paths = {\n            'files': [\"bin/matlab\", \"bin/glnxa64/MATLAB\", \"toolbox/local/classpath.txt\"],\n            'dirs': [\"java/jar\"],\n        }\n        super(EB_MATLAB, self).sanity_check_step(custom_paths=custom_paths)\n\n    def make_module_extra(self):\n        \"\"\"Extend PATH and set proper _JAVA_OPTIONS (e.g., -Xmx).\"\"\"\n        txt = super(EB_MATLAB, self).make_module_extra()\n\n        if self.cfg['java_options']:\n            txt += self.module_generator.set_environment('_JAVA_OPTIONS', self.cfg['java_options'])\n        return txt\n", "path": "easybuild/easyblocks/m/matlab.py"}]}