Repository: spack/spack

Issue:
Octave installation links to Spack compiler wrapper which is unusable outside of Spack.
Spack uses a wrapper script to easily switch between different compilers and to add specific flags for runtime library linking. Some applications, like Octave and Python, will record the compiler path and will use it to install sub-modules. If these compiler wrappers are used outside of Spack they will fail because they do not know how to link back to the original compiler. 

When Spack installs Python it runs a post install script on the config and Makefiles to replace any mention of the wrapper with the original compiler. However, with Octave the reference to the compiler is stored within the `mkoctfile` binary and the `liboctinterp.so` library. For example:

```
$ mkoctfile -p CXX
/home/paul/Projects/spack/lib/spack/env/gcc/g++
$ strings mkoctfile | grep g++
/home/paul/Projects/spack/lib/spack/env/gcc/g++
```

To workaround this I edited the binary file to replace the path to the wrapper with the real compiler path. I don't this should be recommend as an Octave post install step.


Discussion:
#4470 is about to go in -- will this help in the case of Octave?
#4470 doesn't make any changes to the Octave package. It makes it easier to filter compiler wrappers out of text files, but that isn't the case here.
> #4470 is about to go in

:sob: 
Cross-referencing a possible solution to this issue: https://github.com/spack/spack/issues/14702#issuecomment-580967373

Resolving patch:
diff --git a/var/spack/repos/builtin/packages/octave/package.py b/var/spack/repos/builtin/packages/octave/package.py
--- a/var/spack/repos/builtin/packages/octave/package.py
+++ b/var/spack/repos/builtin/packages/octave/package.py
@@ -2,17 +2,23 @@
 # Spack Project Developers. See the top-level COPYRIGHT file for details.
 #
 # SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
-from spack import *
+import os.path
+import shutil
 import sys
+import tempfile
+
+import spack.util.environment
 
 
 class Octave(AutotoolsPackage, GNUMirrorPackage):
     """GNU Octave is a high-level language, primarily intended for numerical
-    computations. It provides a convenient command line interface for solving
-    linear and nonlinear problems numerically, and for performing other
-    numerical experiments using a language that is mostly compatible with
-    Matlab. It may also be used as a batch-oriented language."""
+    computations.
+
+    It provides a convenient command line interface for solving linear and
+    nonlinear problems numerically, and for performing other numerical
+    experiments using a language that is mostly compatible with Matlab.
+    It may also be used as a batch-oriented language.
+    """
 
     homepage = "https://www.gnu.org/software/octave/"
     gnu_mirror_path = "octave/octave-4.0.0.tar.gz"
@@ -89,6 +95,57 @@ class Octave(AutotoolsPackage, GNUMirrorPackage):
     depends_on('suite-sparse', when='+suitesparse')
     depends_on('zlib',         when='+zlib')
 
+    def patch(self):
+        # Filter mkoctfile.in.cc to use underlying compilers and not
+        # Spack compiler wrappers. We are patching the template file
+        # and not mkoctfile.cc since the latter is generated as part
+        # of the build.
+        mkoctfile_in = os.path.join(
+            self.stage.source_path, 'src', 'mkoctfile.in.cc'
+        )
+        quote = lambda s: '"' + s + '"'
+        entries_to_patch = {
+            r'%OCTAVE_CONF_MKOCTFILE_CC%': quote(self.compiler.cc),
+            r'%OCTAVE_CONF_MKOCTFILE_CXX%': quote(self.compiler.cxx),
+            r'%OCTAVE_CONF_MKOCTFILE_F77%': quote(self.compiler.f77),
+            r'%OCTAVE_CONF_MKOCTFILE_DL_LD%': quote(self.compiler.cxx),
+            r'%OCTAVE_CONF_MKOCTFILE_LD_CXX%': quote(self.compiler.cxx)
+        }
+
+        for pattern, subst in entries_to_patch.items():
+            filter_file(pattern, subst, mkoctfile_in)
+
+    @run_after('install')
+    @on_package_attributes(run_tests=True)
+    def check_mkoctfile_works_outside_of_build_env(self):
+        # Check that mkoctfile is properly configured and can compile
+        # Octave extensions outside of the build env
+        mkoctfile = Executable(os.path.join(self.prefix, 'bin', 'mkoctfile'))
+        helloworld_cc = os.path.join(
+            os.path.dirname(__file__), 'helloworld.cc'
+        )
+        tmp_dir = tempfile.mkdtemp()
+        shutil.copy(helloworld_cc, tmp_dir)
+
+        # We need to unset these variables since we are still within
+        # Spack's build environment when running tests
+        vars_to_unset = ['CC', 'CXX', 'F77', 'FC']
+
+        with spack.util.environment.preserve_environment(*vars_to_unset):
+            # Delete temporarily the environment variables that point
+            # to Spack compiler wrappers
+            for v in vars_to_unset:
+                del os.environ[v]
+            # Check that mkoctfile outputs the expected value for CC
+            cc = mkoctfile('-p', 'CC', output=str)
+            msg = "mkoctfile didn't output the expected CC compiler"
+            assert self.compiler.cc in cc, msg
+
+            # Try to compile an Octave extension
+            shutil.copy(helloworld_cc, tmp_dir)
+            with working_dir(tmp_dir):
+                mkoctfile('helloworld.cc')
+
     def configure_args(self):
         # See
         # https://github.com/macports/macports-ports/blob/master/math/octave/


Test patch: