Repository: spack/spack

Issue:
Installation issue: emacs on OSX (gcc and clang)
<!-- Thanks for taking the time to report this build failure. To proceed with the report please:

1. Title the issue "Installation issue: emacs".
2. Provide the information required below.

We encourage you to try, as much as possible, to reduce your problem to the minimal example that still reproduces the issue. That would help us a lot in fixing it quickly and effectively! -->

### Steps to reproduce the issue

<!-- Fill in the exact spec you are trying to build and the relevant part of the error message -->
```console
$ spack spec emacs
Input spec
--------------------------------
emacs

Concretized
--------------------------------
emacs@26.3%gcc@8.2.0~X~tls toolkit=gtk arch=darwin-mojave-skylake
    ^libjpeg-turbo@2.0.3%gcc@8.2.0 arch=darwin-mojave-skylake
        ^cmake@3.17.1%gcc@8.2.0~doc+ncurses+openssl+ownlibs~qt arch=darwin-mojave-skylake
        ^nasm@2.14.02%gcc@8.2.0 arch=darwin-mojave-skylake
    ^ncurses@6.2%gcc@8.2.0~symlinks+termlib arch=darwin-mojave-skylake
        ^pkgconf@1.6.3%gcc@8.2.0 arch=darwin-mojave-skylake
    ^pcre@8.43%gcc@8.2.0~jit+multibyte+utf arch=darwin-mojave-skylake
    ^zlib@1.2.11%gcc@8.2.0+optimize+pic+shared arch=darwin-mojave-skylake

$ spack install emacs
==> Warning: Missing a source id for cmake@3.17.1
==> cmake@3.17.1 : externally installed in /usr/local
==> cmake@3.17.1 : already registered in DB
[+] /usr/local
[+] /Users/mthevenet/spack/opt/spack/darwin-mojave-skylake/gcc-8.2.0/nasm-2.14.02-mb3dueyzd37ac5w7mhft4g3l5rnsnuzb
[+] /Users/mthevenet/spack/opt/spack/darwin-mojave-skylake/gcc-8.2.0/pkgconf-1.6.3-drf5ew5vmgar2bjrm7dljatvaqaf3mnw
[+] /Users/mthevenet/spack/opt/spack/darwin-mojave-skylake/gcc-8.2.0/pcre-8.43-2hvx6sb3g77d2qqwf3vy2nmocxdlzpnf
[+] /Users/mthevenet/spack/opt/spack/darwin-mojave-skylake/gcc-8.2.0/zlib-1.2.11-yx7kxbuvqhwrvvnbafa3jyt2cufkgtgx
[+] /Users/mthevenet/spack/opt/spack/darwin-mojave-skylake/gcc-8.2.0/libjpeg-turbo-2.0.3-brijurey25n6mcg5w6y4akpsyad52xqh
[+] /Users/mthevenet/spack/opt/spack/darwin-mojave-skylake/gcc-8.2.0/ncurses-6.2-ornke2ybcblr6c7zpxrfqp4pn7swxij2
==> 86057: Installing emacs
==> Using cached archive: /Users/mthevenet/spack/var/spack/cache/_source-cache/archive/09/09c747e048137c99ed35747b012910b704e0974dde4db6696fde7054ce387591.tar.gz
==> Staging archive: /var/folders/m0/y8k7shfj4b992dt7xpyll04m0000gn/T/mthevenet/spack-stage/spack-stage-emacs-26.3-5j4daar727i3fkx2fenrw3rzro3ters6/emacs-26.3.tar.gz
==> Created stage in /var/folders/m0/y8k7shfj4b992dt7xpyll04m0000gn/T/mthevenet/spack-stage/spack-stage-emacs-26.3-5j4daar727i3fkx2fenrw3rzro3ters6
==> No patches needed for emacs
==> 86057: emacs: Building emacs [AutotoolsPackage]
==> 86057: emacs: Executing phase: 'autoreconf'
==> 86057: emacs: Executing phase: 'configure'
==> 86057: emacs: Executing phase: 'build'
==> Error: ProcessError: Command exited with status 2:
    'make' '-j8'

2 errors found in build log:
     685      CC       thread.o
     686      CC       systhread.o
     687      CC       terminfo.o
     688      CC       lastfile.o
     689      CCLD     temacs
     690    ld: warning: option -prebind is obsolete and being ignored
  >> 691    Undefined symbols for architecture x86_64:
     692      "_tgetent", referenced from:
     693          _init_tty in term.o
     694      "_tgetflag", referenced from:
     695          _init_tty in term.o
     696      "_tgetnum", referenced from:
     697          _init_tty in term.o

     ...

     712          _tty_turn_on_highlight in term.o
     713          _tty_turn_off_highlight in term.o
     714          _tty_turn_on_insert in term.o
     715          _turn_off_face in term.o
     716          ...
     717    ld: symbol(s) not found for architecture x86_64
  >> 718    collect2: error: ld returned 1 exit status
     719    make[1]: *** [Makefile:602: temacs] Error 1
     720    make[1]: Leaving directory '/private/var/folders/m0/y8k7shfj4b992dt7xpyll04m0000gn/T/mthevenet/spack-stage/spack-stage-emacs-26.3-5j4daar727i3fkx2fenrw3rzro3ters6/spack-src/src'
     721    make: *** [Makefile:421: src] Error 2

See build log for details:
  /var/folders/m0/y8k7shfj4b992dt7xpyll04m0000gn/T/mthevenet/spack-stage/spack-stage-emacs-26.3-5j4daar727i3fkx2fenrw3rzro3ters6/spack-build-out.txt

==> Error: Failed to install emacs due to ChildError: ProcessError: Command exited with status 2:
    'make' '-j8'
2 errors found in build log:
     685      CC       thread.o
     686      CC       systhread.o
     687      CC       terminfo.o
     688      CC       lastfile.o
     689      CCLD     temacs
     690    ld: warning: option -prebind is obsolete and being ignored
  >> 691    Undefined symbols for architecture x86_64:
     692      "_tgetent", referenced from:
     693          _init_tty in term.o
     694      "_tgetflag", referenced from:
     695          _init_tty in term.o
     696      "_tgetnum", referenced from:
     697          _init_tty in term.o

     ...

     712          _tty_turn_on_highlight in term.o
     713          _tty_turn_off_highlight in term.o
     714          _tty_turn_on_insert in term.o
     715          _turn_off_face in term.o
     716          ...
     717    ld: symbol(s) not found for architecture x86_64
  >> 718    collect2: error: ld returned 1 exit status
     719    make[1]: *** [Makefile:602: temacs] Error 1
     720    make[1]: Leaving directory '/private/var/folders/m0/y8k7shfj4b992dt7xpyll04m0000gn/T/mthevenet/spack-stage/spack-stage-emacs-26.3-5j4daar727i3fkx2fenrw3rzro3ters6/spack-src/src'
     721    make: *** [Makefile:421: src] Error 2

See build log for details:
  /var/folders/m0/y8k7shfj4b992dt7xpyll04m0000gn/T/mthevenet/spack-stage/spack-stage-emacs-26.3-5j4daar727i3fkx2fenrw3rzro3ters6/spack-build-out.txt
Traceback (most recent call last):
  File "/Users/mthevenet/spack/lib/spack/spack/build_environment.py", line 801, in child_process
    return_value = function()
  File "/Users/mthevenet/spack/lib/spack/spack/installer.py", line 1113, in build_process
    phase(pkg.spec, pkg.prefix)
  File "/Users/mthevenet/spack/lib/spack/spack/package.py", line 108, in phase_wrapper
    phase(spec, prefix)
  File "/Users/mthevenet/spack/lib/spack/spack/build_systems/autotools.py", line 290, in build
    inspect.getmodule(self).make(*self.build_targets)
  File "/Users/mthevenet/spack/lib/spack/spack/build_environment.py", line 131, in __call__
    return super(MakeExecutable, self).__call__(*args, **kwargs)
  File "/Users/mthevenet/spack/lib/spack/spack/util/executable.py", line 189, in __call__
    proc.returncode, long_msg)
spack.util.executable.ProcessError: Command exited with status 2:
    'make' '-j8'
```
### Information on your system

<!-- Please include the output of `spack debug report` -->
MacOS version 10.14.6
GCC was installed via Homebrew

[Here is a demonstrator that shows the same issue on macOS HighSierra with `clang-9.1.0-apple` as compiler.](https://github.com/ax3l/spack-emacs) (see [build](https://travis-ci.com/github/ax3l/spack-emacs/builds/160642074))

<!-- If you have any relevant configuration detail (custom `packages.yaml` or `modules.yaml`, etc.) you can add that here as well. -->

[packages.txt](https://github.com/spack/spack/files/4489278/packages.txt)
[compilers.txt](https://github.com/spack/spack/files/4489283/compilers.txt)

### Additional information

<!-- Please upload the following files. They should be present in the stage directory of the failing build. Also upload any config.log or similar file if one exists. -->
* [spack-build-out.txt](https://github.com/spack/spack/files/4489250/spack-build-out.txt)
* [spack-build-env.txt](https://github.com/spack/spack/files/4489255/spack-build-env.txt)

<!-- Some packages have maintainers who have volunteered to debug build failures. Run `spack maintainers <name-of-the-package>` and @mention them here if they exist. -->

### General information

<!-- These boxes can be checked by replacing [ ] with [x] or by clicking them after submitting the issue. -->
- [ ] I have run `spack debug report` and reported the version of Spack/Python/Platform
- [x] I have run `spack maintainers <name-of-the-package>` and @mentioned any maintainers
- [x] I have uploaded the build log and environment files
- [ ] I have searched the issues of this repo and believe this is not a duplicate



Discussion:
Note that
```
spack install emacs %clang
```
gives the same error. (`%clang` is `%clang@10.0.1-apple`)
Found a related issue on `conda-forge`:
- https://github.com/conda-forge/ncurses-feedstock/issues/36
- https://github.com/conda-forge/emacs-feedstock/pull/16

Maybe some dependency links against the system `ncurses` instead of the spack one (or does not link when needed at all). Seams to be the `-ltinfo` lib that is missing in some/one of the link steps.
Looking at Spack's `samtools` package right now. This also does some extra-handling for `ncurses` linking in its various flavors.

The problem seams to be occuring when `ncurses` is build with `+termlib` variant, which is by default `True`. The `pkg-config` file of `ncurses` seams to propagate this, but maybe we miss some flags/libs in our downstream-passing logic.
Plot twist: I just checked the sources of `emacs@26.3` and it does, accoring to configure, not even depend on `ncurses` directly.

If we remove the dependency, it builds on macOS.
It now has still the line
```
checking for library containing tputs... -lncurses
```
in `configure`, which likely picks up a system `ncurses`. So we could do the same work-around as `samtools`:

If we add to configure
```py
        if '+termlib' in spec['ncurses']:
            curses_lib = '-lncursesw -ltinfow'
        else:
            curses_lib = '-lncursesw'
        args.append('LIBS={0}'.format(curses_lib))
```

than configure reads
```
checking for library containing tputs... none required
```

and then fails with a linker error on its symbols (see initial error; `tgetent` and `tputs` are a `libtinfo` lib symbols from the `ncurses` package) xD
Since this looks like a emacs configuration error, it depends `ncurses` but does not expose configure-control.

One could experiment with the commented out Nextstep/[GNUstep](http://gnustep.org/) dependency (see `--without-ns`), but this is too deep of a rabbit hole for now.

Here is how homebrew builds `emacs`:
  https://github.com/Homebrew/homebrew-core/blob/master/Formula/emacs.rb

And this is how conda-forge does it:
  https://github.com/conda-forge/emacs-feedstock/blob/master/recipe

We'll link against the system `ncurses` now by commenting out the `depends_on('ncurses')` in `emacs`.

Resolving patch:
diff --git a/var/spack/repos/builtin/packages/emacs/package.py b/var/spack/repos/builtin/packages/emacs/package.py
--- a/var/spack/repos/builtin/packages/emacs/package.py
+++ b/var/spack/repos/builtin/packages/emacs/package.py
@@ -47,6 +47,13 @@ class Emacs(AutotoolsPackage, GNUMirrorPackage):
     depends_on('gnutls', when='+tls')
     depends_on('jpeg')
 
+    @when('platform=darwin')
+    def setup_build_environment(self, env):
+        # on macOS, emacs' config does search hard enough for ncurses'
+        # termlib `-ltinfo` lib, which results in linker errors
+        if '+termlib' in spec['ncurses']:
+            env.append_flags('LDFLAGS', '-ltinfo')
+
     def configure_args(self):
         spec = self.spec
 
diff --git a/var/spack/repos/builtin/packages/ncurses/package.py b/var/spack/repos/builtin/packages/ncurses/package.py
--- a/var/spack/repos/builtin/packages/ncurses/package.py
+++ b/var/spack/repos/builtin/packages/ncurses/package.py
@@ -28,7 +28,8 @@ class Ncurses(AutotoolsPackage, GNUMirrorPackage):
     variant('symlinks', default=False,
             description='Enables symlinks. Needed on AFS filesystem.')
     variant('termlib', default=True,
-            description='Enables termlib needs for gnutls in emacs.')
+            description='Enables termlib features. This is an extra '
+                        'lib and optional internal dependency.')
 
     depends_on('pkgconfig', type='build')
 


Test patch: