Repository: spack/spack

Issue:
Rust and libgit don't link against libssh 2 on Darwin
<!--*Thanks for taking the time to report this build failure. To proceed with the
report please:*
1. Title the issue "Installation issue: libgit2, rust".
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!
-->


### Spack version
<!-- Add the output to the command below -->
```console
$ spack --version
0.14.1-524-dd7a413f4

```

### Steps to reproduce the issue

```console
$ spack install rust
```
Then we try to build a package that depends on rust lets say, bat, I discovered this since I am adding exa after I pull request a fix for this
```console
$ spack install bat
==> Error: ProcessError: Command exited with status -6:
    '/Users/dsmc/Documents/Projects/spack/opt/spack/darwin-catalina-x86_64/clang-11.0.3-apple/rust-1.42.0-bstzydu5kantx3k4npotzo5mqqw3fafw/bin/cargo' 'install' '--root' '/Users/dsmc/Documents/Projects/spack/opt/spack/darwin-catalina-x86_64/clang-11.0.3-apple/bat-0.12.1-s5i5r54odl3npgdn3xdt4cuv56lgk77h' '--path' '.'
See build log for details:
  /var/folders/7j/xtfr4qsx53x0__w8gqxpkll40000gn/T/dsmc/spack-stage/spack-stage-bat-0.12.1-s5i5r54odl3npgdn3xdt4cuv56lgk77h/spack-build-out.txt

==> Error: Failed to install bat due to ChildError: ProcessError: Command exited with status -6:
    '/Users/dsmc/Documents/Projects/spack/opt/spack/darwin-catalina-x86_64/clang-11.0.3-apple/rust-1.42.0-bstzydu5kantx3k4npotzo5mqqw3fafw/bin/cargo' 'install' '--root' '/Users/dsmc/Documents/Projects/spack/opt/spack/darwin-catalina-x86_64/clang-11.0.3-apple/bat-0.12.1-s5i5r54odl3npgdn3xdt4cuv56lgk77h' '--path' '.'See build log for details:
  /var/folders/7j/xtfr4qsx53x0__w8gqxpkll40000gn/T/dsmc/spack-stage/spack-stage-bat-0.12.1-s5i5r54odl3npgdn3xdt4cuv56lgk77h/spack-build-out.txt
Traceback (most recent call last):
  File "/Users/dsmc/Documents/Projects/spack/lib/spack/spack/build_environment.py", line 801, in child_process
    return_value = function()
  File "/Users/dsmc/Documents/Projects/spack/lib/spack/spack/installer.py", line 1113, in build_process
    phase(pkg.spec, pkg.prefix)
  File "/Users/dsmc/Documents/Projects/spack/lib/spack/spack/package.py", line 108, in phase_wrapper
    phase(spec, prefix)
  File "/Users/dsmc/Documents/Projects/spack/var/spack/repos/builtin/packages/bat/package.py", line 22, in install
  File "/Users/dsmc/Documents/Projects/spack/lib/spack/spack/util/executable.py", line 189, in __call__
    proc.returncode, long_msg)
spack.util.executable.ProcessError: Command exited with status -6:
    '/Users/dsmc/Documents/Projects/spack/opt/spack/darwin-catalina-x86_64/clang-11.0.3-apple/rust-1.42.0-bstzydu5kantx3k4npotzo5mqqw3fafw/bin/cargo' 'install' '--root' '/Users/dsmc/Documents/Projects/spack/opt/spack/darwin-catalina-x86_64/clang-11.0.3-apple/bat-0.12.1-s5i5r54odl3npgdn3xdt4cuv56lgk77h' '--path' '.'
```
So then we can do a cat to the file that contains the error and we see this:
```console
3xdt4cuv56lgk77h/spack-build-out.txt
==> 33175: bat: Executing phase: 'install'
==> [2020-04-05-20:10:12.346754, 33188] '/Users/dsmc/Documents/Projects/spack/opt/spack/darwin-catalina-x86_64/clang-11.0.3-apple/rust-1.42.0-bstzydu5kantx3k4npotzo5mqqw3fafw/bin/cargo' 'install' '--root' '/Users/dsmc/Documents/Projects/spack/opt/spack/darwin-catalina-x86_64/clang-11.0.3-apple/bat-0.12.1-s5i5r54odl3npgdn3xdt4cuv56lgk77h' '--path' '.'
dyld: Library not loaded: libssh2.1.dylib
  Referenced from: /Users/dsmc/Documents/Projects/spack/opt/spack/darwin-catalina-x86_64/clang-11.0.3-apple/rust-1.42.0-bstzydu5kantx3k4npotzo5mqqw3fafw/bin/cargo
  Reason: image not found```

### Platform and user environment

<!-- Please report your OS here:
```commandline
$ uname -a 
Darwin epicMac 19.4.0 Darwin Kernel Version 19.4.0: Wed Mar  4 22:28:40 PST 2020; root:xnu-6153.101.6~15/RELEASE_X86_64 x86_64
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.4
BuildVersion:	19E266
``` 

### Additional information

Well we can fix this error by using otool to change the dylib paths, as seen in the following example:

```console
install_name_tool -change libssh2.1.dylib /Users/dsmc/Documents/Projects/spack/opt/spack/darwin-catalina-x86_64/clang-11.0.3-apple/libssh2-1.8.0-bwme3nb5vpustesfddxwqbevjk5zm2gd/lib/libssh2.1.0.1.dylib  /Users/dsmc/Documents/Projects/spack/opt/spack/darwin-catalina-x86_64/clang-11.0.3-apple/libgit2-1.0.0-sdlgezlhpbkjm37oiortjy5d3yxqx56p/lib/libgit2.1.0.0.dylib
```

I will be pushing a pull request to fix this issue, just addressing it so I can reference it.


### General information

- [x] I have run `spack --version` and reported the version of Spack
- [x] I have searched the issues of this repo and believe this is not a duplicate



Discussion:
I'm seeing the same issue, trying to use rust on OS X 10.13.6 to build ripgrep (working on an update).  

I see it when trying to simply invoke cargo.

FWIW:

```
(alice)[16:58:23]spack>>otool -L  /Users/hartzell/tmp/spack/opt/spack/darwin-highsierra-x86_64/clang-10.0.0-apple/rust-1.42.0-w7lqwovgrxhkq4ujjgkrpmpu6cvxck7l/bin/cargo
/Users/hartzell/tmp/spack/opt/spack/darwin-highsierra-x86_64/clang-10.0.0-apple/rust-1.42.0-w7lqwovgrxhkq4ujjgkrpmpu6cvxck7l/bin/cargo:
	@rpath/libgit2.1.0.dylib (compatibility version 1.0.0, current version 1.0.0)
	libssh2.1.dylib (compatibility version 1.0.0, current version 1.0.1)
	/usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
	/usr/local/opt/openssl@1.1/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
	/Users/hartzell/tmp/spack/opt/spack/darwin-highsierra-x86_64/clang-10.0.0-apple/zlib-1.2.11-caosjr5fcruvzyocttnqqkpackpwyzpz/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
	/usr/lib/libcurl.4.dylib (compatibility version 7.0.0, current version 9.0.0)
	/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1455.12.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)
	/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
```

Transliterating your workaround into:

```
install_name_tool -change libssh2.1.dylib $(spack location -i libssh2)/lib/libssh2.1.0.1.dylib  $(spack location -i libgit2)/lib/libgit2.1.0.0.dylib
```

didn't result in a working copy of cargo.
Would you mind trying this 2 tests:

https://github.com/DiegoMagdaleno/spack/commit/4afeeb9d70c3d6ee9d8292c5fb15dadafa1d0b7f
https://github.com/DiegoMagdaleno/spack/commit/8b5dbcdae08f8204c99e2543f8f73d38d960dd42
I've grabbed the interesting bits (the changes to the libgit2 and rust packages) and am taking a test run.  I already have similar changes for the LLVM thing and the other change seem to be whitespace.
These two changes from [your comment above](https://github.com/spack/spack/issues/15887#issuecomment-611258259), plus fixes for the `llvm` bit that I already have, successfully build my Work In Progress update to the ripgrep package on an OS X 10.13.6 system.

I'm not sure what's going on with the LLVM bit.  I was involved in adding it a while back.   Now it doesn't seem to be needed (or functional) and I'm not sure what changed....  That's a different question.

I don't understand what's going on, but these changes seem to be patching over a problem instead of fixing the Root Cause.

@ax3l, @trws -- do you have any insights about this?


```diff
diff --git a/var/spack/repos/builtin/packages/libgit2/package.py b/var/spack/repos/builtin/packages/libgit2/package.py
index dcd5259a2..633369490 100644
--- a/var/spack/repos/builtin/packages/libgit2/package.py
+++ b/var/spack/repos/builtin/packages/libgit2/package.py
@@ -4,6 +4,7 @@
 # SPDX-License-Identifier: (Apache-2.0 OR MIT)

 from spack import *
+import sys


 class Libgit2(CMakePackage):
@@ -96,3 +97,22 @@ def cmake_args(self):
             '-DBUILD_CLAR={0}'.format('ON' if self.run_tests else 'OFF'))

         return args
+
+    # This fixes a linking error on Darwin based operating systems
+    # as far as i know this issue happened on Darwin 19, in macOS versions
+    # macOS catalina, this should link the symbol to its correct place.
+
+    # I dont know if the issue
+    # is present on other operating systems, so for now
+    # we only execute this if is platform is Darwin, also install_name_tool is
+    # a mach tool only.
+    @run_after('install')
+    def fix_linking(self):
+        if sys.platform == 'darwin':
+            install_name_tool = which('install_name_tool')
+            install_name_tool('-change', 'libssh2.1.dylib',
+                              '{0}'.format(
+                                  self.spec['libssh2'].prefix.lib
+                                  + '/libssh2.1.0.1.dylib'),
+                              '{0}'.format(
+                                  prefix.lib + '/libgit2.1.0.0.dylib'))
diff --git a/var/spack/repos/builtin/packages/rust/package.py b/var/spack/repos/builtin/packages/rust/package.py
index 59e827f67..d18f6a538 100644
--- a/var/spack/repos/builtin/packages/rust/package.py
+++ b/var/spack/repos/builtin/packages/rust/package.py
@@ -5,6 +5,7 @@

 from spack import *
 from six import iteritems
+import sys


 class Rust(Package):
@@ -456,3 +457,15 @@ def build(self, spec, prefix):

     def install(self, spec, prefix):
         python('./x.py', 'install')
+
+    # Cargo didn't linked against libssh in Darwin. This fixes that issue.
+    @run_after('install')
+    def darwin_fix_linking(self):
+        if sys.platform == 'darwin':
+            install_name_tool = which('install_name_tool')
+            install_name_tool('-change', 'libssh2.1.dylib',
+                              '{0}'.format(
+                                  self.spec['libssh2'].prefix.lib
+                                  + '/libssh2.1.0.1.dylib'),
+                              '{0}'.format(
+                                  prefix.bin + '/cargo'))
```
It looks to me like we have an rpath issue, perhaps both that cargo is not getting the rpaths it needs, and further may not be providing them.  Not sure why, haven't been in that code for a while, but that's what this looks like.

Resolving patch:
diff --git a/var/spack/repos/builtin/packages/libgit2/package.py b/var/spack/repos/builtin/packages/libgit2/package.py
--- a/var/spack/repos/builtin/packages/libgit2/package.py
+++ b/var/spack/repos/builtin/packages/libgit2/package.py
@@ -57,6 +57,7 @@ class Libgit2(CMakePackage):
     # Build Dependencies
     depends_on('cmake@2.8:', type='build', when="@:0.28")
     depends_on('cmake@3.5:', type='build', when="@0.99:")
+    depends_on('pkgconfig', type='build')
 
     # Runtime Dependencies
     depends_on('libssh2', when='+ssh')
diff --git a/var/spack/repos/builtin/packages/libssh2/package.py b/var/spack/repos/builtin/packages/libssh2/package.py
--- a/var/spack/repos/builtin/packages/libssh2/package.py
+++ b/var/spack/repos/builtin/packages/libssh2/package.py
@@ -28,3 +28,9 @@ def cmake_args(self):
         spec = self.spec
         return [
             '-DBUILD_SHARED_LIBS=%s' % ('YES' if '+shared' in spec else 'NO')]
+
+    @run_after('install')
+    def darwin_fix(self):
+        # The shared library is not installed correctly on Darwin; fix this
+        if self.spec.satisfies('platform=darwin'):
+            fix_darwin_install_name(self.prefix.lib)


Test patch: