Skip to content

Commit

Permalink
Give a more helpful warning when test compilation fails
Browse files Browse the repository at this point in the history
Mention CC and CXX in particular for OS X
  • Loading branch information
mstimberg committed Oct 29, 2021
1 parent a7ae761 commit 8dfd80b
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 6 deletions.
8 changes: 6 additions & 2 deletions brian2/codegen/runtime/cython_rt/cython_rt.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,12 @@ def main():
compiled.main()
return True
except Exception as ex:
logger.warn(f'Cannot use Cython, a test compilation failed: {str(ex)} ({ex.__class__.__name__})',
'failed_compile_test')
logger.warn(
f"Cannot use Cython, a test compilation failed: {str(ex)} ({ex.__class__.__name__})\n"
f"Certain compiler configurations (e.g. clang in a conda environment on OS X) are "
f"known to be problematic. Note that you can switch the compiler by setting the "
f"'CC' and 'CXX' environment variables. For example, you may want to try 'CC=gcc' "
f"and 'CXX=g++'.", 'failed_compile_test')
return False

def compile_block(self, block):
Expand Down
13 changes: 9 additions & 4 deletions brian2/codegen/runtime/cython_rt/extension_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,21 @@ def create_extension(self, code, force=False, name=None,
os.makedirs(lib_dir)
except OSError:
if not os.path.exists(lib_dir):
raise IOError("Couldn't create Cython cache directory '%s', try setting the "
"cache directly with prefs.codegen.runtime.cython.cache_dir." % lib_dir)
raise IOError(
f"Couldn't create Cython cache directory '{lib_dir}', try setting the "
f"cache directly with prefs.codegen.runtime.cython.cache_dir.")

numpy_version = '.'.join(numpy.__version__.split('.')[:2]) # Only use major.minor version
key = code, sys.version_info, sys.executable, Cython.__version__, numpy_version
# avoid some issues when manually switching compilers
CC = os.environ.get('CC', None)
CXX = os.environ.get('CXX', None)
key = (code, sys.version_info, sys.executable, Cython.__version__,
numpy_version, CC, CXX)

if force:
# Force a new module name by adding the current time to the
# key which is hashed to determine the module name.
key += time.time(),
key += time.time(), # Note the trailing comma (this is a tuple)

if key in self._code_cache:
return self._code_cache[key]
Expand Down
23 changes: 23 additions & 0 deletions brian2/tests/test_codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from brian2 import prefs, clear_cache, _cache_dirs_and_extensions
from brian2.codegen.cpp_prefs import compiler_supports_c99, get_compiler_and_args
from brian2.codegen.optimisation import optimise_statements
from brian2.codegen.runtime.cython_rt import CythonCodeObject
from brian2.codegen.translation import (analyse_identifiers,
get_identifiers_recursively,
parse_statement,
Expand Down Expand Up @@ -445,6 +446,28 @@ def test_clear_cache():

os.remove(fname)

def test_compiler_error():
# In particular on OSX with clang in a conda environment, compilation might fail.
# Switching to a system gcc might help in such cases. Make sure that the error
# message mentions that.
old_CC = os.environ.get('CC', None)
old_CXX = os.environ.get('CXX', None)
os.environ.update({'CC': 'non-existing-compiler',
'CXX': 'non-existing-compiler++'})
try:
with catch_logs() as l:
assert not CythonCodeObject.is_available()
assert len(l) > 0 # There are additional warnings about compiler flags
last_warning = l[-1]
assert last_warning[1].endswith('.failed_compile_test')
assert 'CC' in last_warning[2] and 'CXX' in last_warning[2]

finally:
if old_CC:
os.environ['CC'] = old_CC
if old_CXX:
os.environ['CXX'] = old_CXX


def test_compiler_c99():
# On a user's computer, we do not know whether the compiler actually
Expand Down

0 comments on commit 8dfd80b

Please sign in to comment.