Repository: spack/spack

Issue:
spack unable to find an lmod loaded compiler
### Steps to reproduce the issue

I noticed a change of behavior of the following scenario between spack@v0.12.1 and spack@develop :
 
```console
$ module load gcc/8.1.0
$ spack compiler find
```

### The problem

On "release" tag v0.12.1, the compiler is found, on the develop branch, it isn’t.

### System information 

The issue occurs on a supercomputer using lmod mechanism for modules.




Discussion:
@alalazo FYI (although I can look into this if you prefer)

Bisect is implicating https://github.com/spack/spack/pull/10190 (https://github.com/spack/spack/commit/6d56d4545472ddff1cdc0e8fd49d8260428a141e)

I'm not sure why that would cause an error yet.
@adrienbernede @scheibelp I'll have a look at this today, thanks for the report

Resolving patch:
diff --git a/lib/spack/spack/cmd/compiler.py b/lib/spack/spack/cmd/compiler.py
--- a/lib/spack/spack/cmd/compiler.py
+++ b/lib/spack/spack/cmd/compiler.py
@@ -73,7 +73,8 @@ def compiler_find(args):
        add them to Spack's configuration.
 
     """
-    paths = args.add_paths
+    # None signals spack.compiler.find_compilers to use its default logic
+    paths = args.add_paths or None
 
     # Don't initialize compilers config via compilers.get_compiler_config.
     # Just let compiler_find do the
diff --git a/lib/spack/spack/compilers/__init__.py b/lib/spack/spack/compilers/__init__.py
--- a/lib/spack/spack/compilers/__init__.py
+++ b/lib/spack/spack/compilers/__init__.py
@@ -34,6 +34,8 @@
                         'extra_rpaths']
 _cache_config_file = []
 
+# TODO: Caches at module level make it difficult to mock configurations in
+# TODO: unit tests. It might be worth reworking their implementation.
 #: cache of compilers constructed from config data, keyed by config entry id.
 _compiler_cache = {}
 


Test patch:
diff --git a/lib/spack/spack/test/cmd/compiler_command.py b/lib/spack/spack/test/cmd/compiler_command.py
new file mode 100644
--- /dev/null
+++ b/lib/spack/spack/test/cmd/compiler_command.py
@@ -0,0 +1,33 @@
+# Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+import pytest
+
+import os
+import os.path
+
+import spack.main
+
+compiler = spack.main.SpackCommand('compiler')
+
+
+@pytest.fixture
+def no_compilers_yaml(mutable_config, monkeypatch):
+    """Creates a temporary configuration without compilers.yaml"""
+
+    for scope, local_config in mutable_config.scopes.items():
+        compilers_yaml = os.path.join(
+            local_config.path, scope, 'compilers.yaml'
+        )
+        if os.path.exists(compilers_yaml):
+            os.remove(compilers_yaml)
+
+
+@pytest.mark.regression('11678')
+@pytest.mark.requires_executables('/usr/bin/gcc')
+def test_compiler_find_without_paths(no_compilers_yaml):
+    output = compiler('find', '--scope=site')
+
+    assert 'gcc' in output
diff --git a/lib/spack/spack/test/conftest.py b/lib/spack/spack/test/conftest.py
--- a/lib/spack/spack/test/conftest.py
+++ b/lib/spack/spack/test/conftest.py
@@ -19,6 +19,7 @@
 from llnl.util.filesystem import remove_linked_tree
 
 import spack.architecture
+import spack.compilers
 import spack.config
 import spack.caches
 import spack.database
@@ -202,6 +203,21 @@ def __str__(self):
     monkeypatch.setattr(spack.caches, 'fetch_cache', MockCache())
 
 
+@pytest.fixture(autouse=True)
+def _skip_if_missing_executables(request):
+    """Permits to mark tests with 'require_executables' and skip the
+    tests if the executables passed as arguments are not found.
+    """
+    if request.node.get_marker('requires_executables'):
+        required_execs = request.node.get_marker('requires_executables').args
+        missing_execs = [
+            x for x in required_execs if spack.util.executable.which(x) is None
+        ]
+        if missing_execs:
+            msg = 'could not find executables: {0}'
+            pytest.skip(msg.format(', '.join(missing_execs)))
+
+
 # FIXME: The lines below should better be added to a fixture with
 # FIXME: session-scope. Anyhow doing it is not easy, as it seems
 # FIXME: there's some weird interaction with compilers during concretization.
@@ -306,22 +322,24 @@ def config(configuration_dir):
 
 
 @pytest.fixture(scope='function')
-def mutable_config(tmpdir_factory, configuration_dir, config):
+def mutable_config(tmpdir_factory, configuration_dir, monkeypatch):
     """Like config, but tests can modify the configuration."""
     spack.package_prefs.PackagePrefs.clear_caches()
 
     mutable_dir = tmpdir_factory.mktemp('mutable_config').join('tmp')
     configuration_dir.copy(mutable_dir)
 
-    real_configuration = spack.config.config
-
-    spack.config.config = spack.config.Configuration(
+    cfg = spack.config.Configuration(
         *[spack.config.ConfigScope(name, str(mutable_dir))
           for name in ['site', 'system', 'user']])
+    monkeypatch.setattr(spack.config, 'config', cfg)
+
+    # This is essential, otherwise the cache will create weird side effects
+    # that will compromise subsequent tests if compilers.yaml is modified
+    monkeypatch.setattr(spack.compilers, '_cache_config_file', [])
 
     yield spack.config.config
 
-    spack.config.config = real_configuration
     spack.package_prefs.PackagePrefs.clear_caches()
 
 
diff --git a/lib/spack/spack/test/relocate.py b/lib/spack/spack/test/relocate.py
--- a/lib/spack/spack/test/relocate.py
+++ b/lib/spack/spack/test/relocate.py
@@ -17,21 +17,6 @@
 import spack.util.executable
 
 
-@pytest.fixture(autouse=True)
-def _skip_if_missing_executables(request):
-    """Permits to mark tests with 'require_executables' and skip the
-    tests if the executables passed as arguments are not found.
-    """
-    if request.node.get_marker('requires_executables'):
-        required_execs = request.node.get_marker('requires_executables').args
-        missings_execs = [
-            x for x in required_execs if spack.util.executable.which(x) is None
-        ]
-        if missings_execs:
-            msg = 'could not find executables: {0}'
-            pytest.skip(msg.format(', '.join(missings_execs)))
-
-
 @pytest.fixture(params=[True, False])
 def is_relocatable(request):
     return request.param