diff --git a/devito/arch/compiler.py b/devito/arch/compiler.py index 1faf77cc90..ef248cbdf0 100644 --- a/devito/arch/compiler.py +++ b/devito/arch/compiler.py @@ -22,7 +22,7 @@ from devito.logger import debug, warning from devito.parameters import configuration from devito.tools import ( - as_list, change_directory, filter_ordered, make_tempdir, memoized_func + Signer, as_list, change_directory, filter_ordered, make_tempdir, memoized_func ) __all__ = ['compiler_registry', 'sniff_mpi_distro'] @@ -148,7 +148,7 @@ def call_capture_output(cmd): return _call_capture_output(cmd) -class Compiler(GCCToolchain): +class Compiler(GCCToolchain, Signer): """ Base class for all compiler classes. @@ -457,6 +457,9 @@ def __getstate__(self): # The superclass would otherwise only return a subset of attributes return self.__dict__ + def _signature_items(self): + return (str(self._cmdline([])), self.src_ext, self.so_ext) + def add_include_dirs(self, dirs): self.include_dirs = filter_ordered(self.include_dirs + as_list(dirs)) diff --git a/devito/operator/operator.py b/devito/operator/operator.py index b3690caf74..8f3c02f983 100644 --- a/devito/operator/operator.py +++ b/devito/operator/operator.py @@ -811,7 +811,7 @@ def arguments(self, **kwargs): @cached_property def _soname(self): """A unique name for the shared object resulting from JIT compilation.""" - return Signer._digest(self, configuration) + return Signer._digest(self, configuration, self._compiler) @cached_property def _printer(self): diff --git a/tests/test_operator.py b/tests/test_operator.py index 4518b32429..e6fc86463a 100644 --- a/tests/test_operator.py +++ b/tests/test_operator.py @@ -161,6 +161,43 @@ def test_compiler_uniqueness(self): assert op0._compiler is not op2._compiler assert op1._compiler is not op2._compiler + @pytest.mark.parametrize('rpath', [False, True]) + def test_jit_library_dirs(self, rpath, tmp_path): + grid = Grid(shape=(3, 3, 3)) + u = TimeFunction(name='u', grid=grid) + eq = Eq(u.forward, u + 1) + + operators = [] + for name in ('lib0', 'lib1', 'lib1'): + op = Operator(eq, name='library_paths') + op._compiler.add_library_dirs([str(tmp_path/name)], rpath=rpath) + operators.append(op) + + op0, op1, op2 = operators + assert str(op0) == str(op1) == str(op2) + assert op0._soname != op1._soname + assert op1._soname == op2._soname + + @pytest.mark.parametrize('envvar, flags', [ + ('CFLAGS', ('-O1 -O2', '-O2 -O1')), + ('LDFLAGS', ('-Wl,-rpath,/lib0 -Wl,-rpath,/lib1', + '-Wl,-rpath,/lib1 -Wl,-rpath,/lib0')) + ]) + def test_jit_compiler_flags(self, envvar, flags, monkeypatch): + grid = Grid(shape=(3, 3, 3)) + u = TimeFunction(name='u', grid=grid) + eq = Eq(u.forward, u + 1) + + operators = [] + for value in (*flags, flags[-1]): + monkeypatch.setenv(envvar, value) + operators.append(Operator(eq, name='compiler_flags', compiler='custom')) + + op0, op1, op2 = operators + assert str(op0) == str(op1) == str(op2) + assert op0._soname != op1._soname + assert op1._soname == op2._soname + class TestCodeGen: