Repository: numba/numba

Issue:
NUMBAPRO_NVVM behavior changed to look for directory.
<!--

Thanks for opening an issue! To help the Numba team handle your information
efficiently, please first ensure that there is no other issue present that
already describes the issue you have
(search at https://github.com/numba/numba/issues?&q=is%3Aissue).

For more general "how do I do X?" type questions, please speak to us in real
time on https://gitter.im/numba/numba or post to the Numba mailing list
https://groups.google.com/a/continuum.io/forum/#!forum/numba-users.

-->

## Reporting a bug

<!--

Before submitting a bug report please ensure that you can check off these boxes:

-->

- [x] I am using the latest released version of Numba (most recent is visible in
 the change log (https://github.com/numba/numba/blob/master/CHANGE_LOG).
- [x] I have included below a minimal working reproducer (if you are unsure how
 to write one see http://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports).

Fix https://github.com/numba/numba/pull/4096#issuecomment-499661626

Reproducer:

```bash
NUMBAPRO_NVVM=/path/to/libnvvm.so python -c "from numba.cuda.cudadrv import libs; libs.test()"
```

^ would fail on master and 0.44.0


Discussion:

Resolving patch:
diff --git a/numba/cuda/cuda_paths.py b/numba/cuda/cuda_paths.py
--- a/numba/cuda/cuda_paths.py
+++ b/numba/cuda/cuda_paths.py
@@ -52,8 +52,8 @@ def _get_nvvm_path_decision():
         ('CUDA_HOME', get_cuda_home(*_nvvm_lib_dir())),
         ('System', get_system_ctk(*_nvvm_lib_dir())),
     ]
-    by, libdir = _find_valid_path(options)
-    return by, libdir
+    by, path = _find_valid_path(options)
+    return by, path
 
 
 def _get_libdevice_paths():
@@ -134,9 +134,10 @@ def get_cuda_home(*subdirs):
 
 
 def _get_nvvm_path():
-    by, libdir = _get_nvvm_path_decision()
-    candidates = find_lib('nvvm', libdir)
-    path = max(candidates) if candidates else None
+    by, path = _get_nvvm_path_decision()
+    if by != 'NUMBAPRO_NVVM':
+        candidates = find_lib('nvvm', path)
+        path = max(candidates) if candidates else None
     return _env_path_tuple(by, path)
 
 


Test patch:
diff --git a/numba/cuda/tests/nocuda/test_library_lookup.py b/numba/cuda/tests/nocuda/test_library_lookup.py
--- a/numba/cuda/tests/nocuda/test_library_lookup.py
+++ b/numba/cuda/tests/nocuda/test_library_lookup.py
@@ -3,6 +3,7 @@
 import sys
 import os
 import multiprocessing as mp
+from functools import partial
 
 from numba.config import IS_WIN32, IS_OSX
 from numba.cuda.cudadrv import nvvm
@@ -17,6 +18,7 @@
     _get_nvvm_path_decision,
     _get_cudalib_dir_path_decision,
     get_system_ctk,
+    _get_nvvm_path,
 )
 
 
@@ -193,6 +195,21 @@ def do_set_nvvm():
         os.environ['NUMBAPRO_NVVM'] = 'nbp_nvvm'
         return True, _get_nvvm_path_decision()
 
+    def test_nvvm_issue4164(self):
+        # Make sure NUMBAPRO_NVVM can be a file.
+        nvvm_path = _get_nvvm_path().info
+        self.assertTrue(os.path.isfile(nvvm_path))
+        got = self.remote_do(
+            partial(self.do_get_nvvm_path, nvvm_path=nvvm_path),
+        )
+        self.assertEqual(got.by, 'NUMBAPRO_NVVM')
+        self.assertEqual(got.info, nvvm_path)
+
+    @staticmethod
+    def do_get_nvvm_path(nvvm_path):
+        os.environ['NUMBAPRO_NVVM'] = nvvm_path
+        return True, _get_nvvm_path()
+
 
 @skip_on_cudasim('Library detection unsupported in the simulator')
 @unittest.skipUnless(has_mp_get_context, 'mp.get_context not available')