Repository: spack/spack

Issue:
Incorrect parsing of errors in build log
Spack's error detection is a little too sensitive. It erroneously picked up the following lines and marked them as errors:

```
10 errors found in build log:
     29     libtoolize: copying file 'm4/ltversion.m4'
     30     libtoolize: copying file 'm4/lt~obsolete.m4'
     31     autoreconf: running: /Users/Adam/spack/opt/spack/darwin-highsierra-x86_64/clang-9.0.0-apple/autoconf-2.69-2pkhucokgg4327geidao7hfcjnhtcipg/bin/au
            toconf --force
     32     autoreconf: running: /Users/Adam/spack/opt/spack/darwin-highsierra-x86_64/clang-9.0.0-apple/autoconf-2.69-2pkhucokgg4327geidao7hfcjnhtcipg/bin/au
            toheader --force
     33     autoreconf: running: automake --add-missing --copy --force-missing
     34     configure.ac:6: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated.  For more info, see:
  >> 35     configure.ac:6: https://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_005fINIT_005fAUTOMAKE-invocation
  >> 36     configure.ac:7: installing './compile'
  >> 37     configure.ac:7: installing './config.guess'
  >> 38     configure.ac:7: installing './config.sub'
  >> 39     configure.ac:6: installing './install-sh'
  >> 40     configure.ac:6: installing './missing'
...
```
This was discovered while working on a new package. I'll submit it when I get the bugs worked out, but the package looks like:
```python
from spack import *                                                             
                                                                                
                                                                                
class Fyba(AutotoolsPackage):                                                   
    """OpenFYBA is the source code release of the FYBA library, distributed     
    by the National Mapping Authority of Norway (Statens kartverk) to read      
    and write files in the National geodata standard format SOSI."""            
                                                                                
    homepage = "https://github.com/kartverket/fyba"                             
    url      = "https://github.com/kartverket/fyba/archive/4.1.1.tar.gz"        
                                                                                
    version('4.1.1', 'ab687582efdef26593796271529a10cb')                        
                                                                                
    # configure: error: cannot find install-sh or install.sh                    
    force_autoreconf = True                                                     
                                                                                
    depends_on('autoconf', type='build')                                        
    depends_on('automake', type='build')                                        
    depends_on('libtool',  type='build')                                        
    depends_on('m4',       type='build')
```
The error messages can be reproduced by trying to build this package on macOS. 

@tgamblin 


Discussion:
Did the build fail because of this? The error parsing doesn’t determine whether the build succeeds or fails; the return code does. If a bad return code comes back, it shows what it thinks the errors are.

If you look at the ctest parsing logic in the externals you can probably find which expression is triggering this and add an exception for it (there are both matching and exception regexes).
The build didn't fail because of this, it failed for other reasons. I'll see if I can find which expression triggered this match.
Cool. Also feel free to change the code if you want better debugging. It’s in externals because it has the CMake license and it’s just a straight translation from CTest’s parsing, but there’s no upstream to update from and no reason you can’t change it directly.
Encountered this problem again with `fyba`:
```
130 errors found in build log:
     12      libtoolize: linking file `m4/ltoptions.m4'
     13      libtoolize: linking file `m4/ltsugar.m4'
     14      libtoolize: linking file `m4/ltversion.m4'
     15      libtoolize: linking file `m4/lt~obsolete.m4'
     16      ==> '/usr/bin/aclocal'
     17      configure.ac:7: warning: AC_LANG_CONFTEST: no AC_LANG_SOURCE call detected in body
  >> 18      autoconf/lang.m4:198: AC_LANG_CONFTEST is expanded from...
  >> 19      autoconf/general.m4:2671: _AC_LINK_IFELSE is expanded from...
  >> 20      autoconf/general.m4:2681: AC_LINK_IFELSE is expanded from...
  >> 21      /usr/share/aclocal/libtool.m4:1022: _LT_SYS_MODULE_PATH_AIX is expanded from...
  >> 22      /usr/share/aclocal/libtool.m4:4161: _LT_LINKER_SHLIBS is expanded from...
  >> 23      /usr/share/aclocal/libtool.m4:5236: _LT_LANG_C_CONFIG is expanded from...
  >> 24      /usr/share/aclocal/libtool.m4:138: _LT_SETUP is expanded from...
  >> 25      /usr/share/aclocal/libtool.m4:67: LT_INIT is expanded from...
  >> 26      configure.ac:7: the top level
```
Another thing to note is that it only picks up error messages, not warning messages. I thought we also looked for warning messages? At least, there is logic in place to do that.

I'm trying to find which regexes are triggering these matches and it seems like anything that looks like `file:number: ` is being captured. That might not be a terrible idea, although it will certainly lead to a lot of false positives. I guess it depends on how important false positives are compared to false negatives.

Resolving patch:
diff --git a/lib/spack/external/ctest_log_parser.py b/lib/spack/external/ctest_log_parser.py
--- a/lib/spack/external/ctest_log_parser.py
+++ b/lib/spack/external/ctest_log_parser.py
@@ -116,18 +116,15 @@ def match(self, text):
             'Error:', 'error', 'undefined reference', 'multiply defined')),
         "([^:]+): error[ \\t]*[0-9]+[ \\t]*:",
         "([^:]+): (Error:|error|undefined reference|multiply defined)",
-        "([^ :]+) : (error|fatal error|catastrophic error)",
+        "([^ :]+) ?: (error|fatal error|catastrophic error)",
         "([^:]+)\\(([^\\)]+)\\) ?: (error|fatal error|catastrophic error)"),
-    prefilter(
-        lambda s: s.count(':') >= 2,
-        "[^ :]+:[0-9]+: [^ \\t]"),
     "^[Bb]us [Ee]rror",
     "^[Ss]egmentation [Vv]iolation",
     "^[Ss]egmentation [Ff]ault",
     ":.*[Pp]ermission [Dd]enied",
     "^Error ([0-9]+):",
     "^Fatal",
-    "^Error: ",
+    "^[Ee]rror: ",
     "^Error ",
     "[0-9] ERROR: ",
     "^\"[^\"]+\", line [0-9]+: [^Ww]",


Test patch: