Repository: mesonbuild/meson

Issue:
dependencies/cuda.py requires python 3.6 and does not support ARM linux
**Describe the bug**
Invalid use of regex match indexing results in an unhandled exception or a failure to find the CUDA library that is actually there.

- Root cause: lines 162 and 175
    - Indexing regex matches is only supported from python 3.6 (use `.group()` instead)
- Root cause: line 162
    - Missing exception handling for 
- Root cause: line 195
    - No check for aarm64 in linux architectures, should be matched to lib64 folder name

**To Reproduce**
Using Python 3.5:
meson.build:
    `dependency('cuda')`

Unhandled exception observed:
 ```
 File "/home/nvidia/.local/lib/python3.5/site-packages/mesonbuild/dependencies/cuda.py", line 162, in _cuda_toolkit_version
    return m[1]
TypeError: '_sre.SRE_Match' object is not subscriptable
```
If you fix that it will fail silently but the log shows the same error for line 175

For the ARM issue, run the same from an ARM machine.

**Expected behavior**
Find the CUDA version with no exceptions and no need to install Python 3.6

**system parameters**
* native - NVIDIA Jetson TX2
* Ubuntu 16.04
* 3.5.2
* 0.54.1
* N/A

**Notes**
I have not submitted a pull request because I don't time at the minute to figure out how to add a CI test to ensure the use of python 3.5, I would have thought was standard for all tests as it is the minimum required by meson? Probably this code never gets executed in the current test suite (need a test with no CUDA installed).

All tests should fail at the moment on an ARM platform, that would be easy to test if you have access to one but I imagine they are hard to come by in the cloud.

I can submit a request without test changes, but a meson build log showing success, if that's ok?



Discussion:
We are currently only testing python 3.5 in one CI and CUDA in another CI (with the latest python). I am also reluctant to add CUDA to all / most CI images since it is huge...

We are also planning on bumping the minimum python version to 3.6 (see #6297), so I would say that adding a test here won't be necessary.

As for ARM, I think we already have some cross tests on Travis, but I am not sure (also no CUDA there). So a PR without a test is OK in this case (since it is very platform-specific) and we trust you when you say that it works on your system, no need for a meson log as proof :)

Resolving patch:
diff --git a/mesonbuild/dependencies/cuda.py b/mesonbuild/dependencies/cuda.py
--- a/mesonbuild/dependencies/cuda.py
+++ b/mesonbuild/dependencies/cuda.py
@@ -157,11 +157,15 @@ def _cuda_toolkit_version(self, path):
 
         mlog.debug('Falling back to extracting version from path')
         path_version_regex = self.path_version_win_regex if self._is_windows() else self.path_version_nix_regex
-        m = path_version_regex.match(os.path.basename(path))
-        if m:
-            return m[1]
+        try:
+            m = path_version_regex.match(os.path.basename(path))
+            if m:
+                return m.group(1)
+            else:
+                mlog.warning('Could not detect CUDA Toolkit version for {}'.format(path))
+        except Exception as e:
+            mlog.warning('Could not detect CUDA Toolkit version for {}: {}'.format(path, str(e)))
 
-        mlog.warning('Could not detect CUDA Toolkit version for {}'.format(path))
         return '0.0'
 
     def _read_toolkit_version_txt(self, path):
@@ -172,7 +176,7 @@ def _read_toolkit_version_txt(self, path):
                 version_str = version_file.readline() # e.g. 'CUDA Version 10.1.168'
                 m = self.toolkit_version_regex.match(version_str)
                 if m:
-                    return self._strip_patch_version(m[1])
+                    return self._strip_patch_version(m.group(1))
         except Exception as e:
             mlog.debug('Could not read CUDA Toolkit\'s version file {}: {}'.format(version_file_path, str(e)))
 
@@ -192,7 +196,7 @@ def _detect_arch_libdir(self):
                 raise DependencyException(msg.format(arch, 'Windows'))
             return os.path.join('lib', libdirs[arch])
         elif machine.is_linux():
-            libdirs = {'x86_64': 'lib64', 'ppc64': 'lib'}
+            libdirs = {'x86_64': 'lib64', 'ppc64': 'lib', 'aarch64': 'lib64'}
             if arch not in libdirs:
                 raise DependencyException(msg.format(arch, 'Linux'))
             return libdirs[arch]


Test patch: