From f29dd48101b1669b861a0410f60e2ab44dfd54db Mon Sep 17 00:00:00 2001
From: Patrick Gartung <gartung@fnal.gov>
Date: Sat, 1 Aug 2020 18:02:39 -0500
Subject: [PATCH] Add bindist tests for macOS.

---
 lib/spack/spack/test/bindist.py               | 26 ++++-----
 .../builtin.mock/packages/corge/package.py    | 54 +++++++++++++------
 .../builtin.mock/packages/garply/package.py   | 33 +++++++++---
 .../builtin.mock/packages/quux/package.py     | 46 +++++++++++-----
 4 files changed, 109 insertions(+), 50 deletions(-)

diff --git a/lib/spack/spack/test/bindist.py b/lib/spack/spack/test/bindist.py
index f561077edd..a7995ca43b 100644
--- a/lib/spack/spack/test/bindist.py
+++ b/lib/spack/spack/test/bindist.py
@@ -7,6 +7,7 @@
 This test checks creating and install buildcaches
 """
 import os
+import sys
 import py
 import pytest
 import argparse
@@ -158,8 +159,14 @@ def install_dir_non_default_layout(tmpdir):
     spack.store.layout = real_layout
 
 
-@pytest.mark.requires_executables(
-    '/usr/bin/gcc', 'patchelf', 'strings', 'file')
+args = ['strings', 'file']
+if sys.platform == 'darwin':
+    args.extend(['/usr/bin/clang++', 'install_name_tool'])
+else:
+    args.extend(['/usr/bin/g++', 'patchelf'])
+
+
+@pytest.mark.requires_executables(*args)
 @pytest.mark.disable_clean_stage_check
 @pytest.mark.maybeslow
 @pytest.mark.usefixtures('default_config', 'cache_directory',
@@ -177,7 +184,6 @@ def test_default_rpaths_create_install_default_layout(tmpdir,
     cspec = Spec('corge')
     cspec.concretize()
 
-    # Install patchelf needed for relocate in linux test environment
     iparser = argparse.ArgumentParser()
     install.setup_parser(iparser)
     # Install some packages with dependent packages
@@ -253,8 +259,7 @@ def test_default_rpaths_create_install_default_layout(tmpdir,
     mirror.mirror(mparser, margs)
 
 
-@pytest.mark.requires_executables(
-    '/usr/bin/gcc', 'patchelf', 'strings', 'file')
+@pytest.mark.requires_executables(*args)
 @pytest.mark.disable_clean_stage_check
 @pytest.mark.maybeslow
 @pytest.mark.nomockstage
@@ -302,8 +307,7 @@ def test_default_rpaths_install_nondefault_layout(tmpdir,
     mirror.mirror(mparser, margs)
 
 
-@pytest.mark.requires_executables(
-    '/usr/bin/gcc', 'patchelf', 'strings', 'file')
+@pytest.mark.requires_executables(*args)
 @pytest.mark.disable_clean_stage_check
 @pytest.mark.maybeslow
 @pytest.mark.nomockstage
@@ -356,8 +360,7 @@ def test_relative_rpaths_create_default_layout(tmpdir,
     spack.stage.purge()
 
 
-@pytest.mark.requires_executables(
-    '/usr/bin/gcc', 'patchelf', 'strings', 'file')
+@pytest.mark.requires_executables(*args)
 @pytest.mark.disable_clean_stage_check
 @pytest.mark.maybeslow
 @pytest.mark.nomockstage
@@ -382,7 +385,6 @@ def test_relative_rpaths_install_default_layout(tmpdir,
         ['add', '--scope', 'site', 'test-mirror-rel', 'file://%s' % mirror_path_rel])
     mirror.mirror(mparser, margs)
 
-    # Install patchelf needed for relocate in linux test environment
     iparser = argparse.ArgumentParser()
     install.setup_parser(iparser)
 
@@ -422,8 +424,7 @@ def test_relative_rpaths_install_default_layout(tmpdir,
     mirror.mirror(mparser, margs)
 
 
-@pytest.mark.requires_executables(
-    '/usr/bin/gcc', 'patchelf', 'strings', 'file')
+@pytest.mark.requires_executables(*args)
 @pytest.mark.disable_clean_stage_check
 @pytest.mark.maybeslow
 @pytest.mark.nomockstage
@@ -449,7 +450,6 @@ def test_relative_rpaths_install_nondefault(tmpdir,
         ['add', '--scope', 'site', 'test-mirror-rel', 'file://%s' % mirror_path_rel])
     mirror.mirror(mparser, margs)
 
-    # Install patchelf needed for relocate in linux test environment
     iparser = argparse.ArgumentParser()
     install.setup_parser(iparser)
 
diff --git a/var/spack/repos/builtin.mock/packages/corge/package.py b/var/spack/repos/builtin.mock/packages/corge/package.py
index 48f9ac8e6e..3bd8b34e47 100644
--- a/var/spack/repos/builtin.mock/packages/corge/package.py
+++ b/var/spack/repos/builtin.mock/packages/corge/package.py
@@ -6,6 +6,7 @@
 
 from spack import *
 import os
+import sys
 
 
 class Corge(Package):
@@ -101,7 +102,6 @@ class Corge
     return 0;
 }
 '''
-        mkdirp(prefix.lib64)
         mkdirp('%s/corge' % prefix.include)
         mkdirp('%s/corge' % self.stage.source_path)
         with open('%s/corge_version.h' % self.stage.source_path, 'w') as f:
@@ -113,6 +113,8 @@ class Corge
         with open('%s/corge/corgegator.cc' % self.stage.source_path, 'w') as f:
             f.write(corgegator_cc)
         gpp = which('/usr/bin/g++')
+        if sys.platform == 'darwin':
+            gpp = which('/usr/bin/clang++')
         gpp('-Dcorge_EXPORTS',
             '-I%s' % self.stage.source_path,
             '-I%s' % spec['quux'].prefix.include,
@@ -127,22 +129,42 @@ class Corge
             '-O2', '-g', '-DNDEBUG', '-fPIC',
             '-o', 'corgegator.cc.o',
             '-c', 'corge/corgegator.cc')
-        gpp('-fPIC', '-O2', '-g', '-DNDEBUG', '-shared',
-            '-Wl,-soname,libcorge.so', '-o', 'libcorge.so', 'corge.cc.o',
-            '-Wl,-rpath,%s:%s::::' %
-            (spec['quux'].prefix.lib64, spec['garply'].prefix.lib64),
-            '%s/libquux.so' % spec['quux'].prefix.lib64,
-            '%s/libgarply.so' % spec['garply'].prefix.lib64)
-        gpp('-O2', '-g', '-DNDEBUG', '-rdynamic',
-            'corgegator.cc.o', '-o', 'corgegator',
-            '-Wl,-rpath,%s:%s:%s:::' % (prefix.lib64,
-                                        spec['quux'].prefix.lib64,
-                                        spec['garply'].prefix.lib64),
-            'libcorge.so',
-            '%s/libquux.so' % spec['quux'].prefix.lib64,
-            '%s/libgarply.so' % spec['garply'].prefix.lib64)
+        if sys.platform == 'darwin':
+            gpp('-fPIC', '-O2', '-g', '-DNDEBUG', '-dynamiclib',
+                '-install_name', '@rpath/libcorge.dylib',
+                '-o', 'libcorge.dylib', 'corge.cc.o',
+                '-Wl,-rpath,%s' % spec['quux'].prefix.lib64,
+                '-Wl,-rpath,%s' % spec['garply'].prefix.lib64,
+                '%s/libquux.dylib' % spec['quux'].prefix.lib64,
+                '%s/libgarply.dylib' % spec['garply'].prefix.lib64)
+            gpp('-O2', '-g', '-DNDEBUG', '-rdynamic',
+                'corgegator.cc.o', '-o', 'corgegator',
+                '-Wl,-rpath,%s' % prefix.lib64,
+                '-Wl,-rpath,%s' % spec['quux'].prefix.lib64,
+                '-Wl,-rpath,%s' % spec['garply'].prefix.lib64,
+                'libcorge.dylib',
+                '%s/libquux.dylib' % spec['quux'].prefix.lib64,
+                '%s/libgarply.dylib' % spec['garply'].prefix.lib64)
+            mkdirp(prefix.lib64)
+            copy('libcorge.dylib', '%s/libcorge.dylib' % prefix.lib64)
+        else:
+            gpp('-fPIC', '-O2', '-g', '-DNDEBUG', '-shared',
+                '-Wl,-soname,libcorge.so', '-o', 'libcorge.so', 'corge.cc.o',
+                '-Wl,-rpath,%s:%s::::' %
+                (spec['quux'].prefix.lib64, spec['garply'].prefix.lib64),
+                '%s/libquux.so' % spec['quux'].prefix.lib64,
+                '%s/libgarply.so' % spec['garply'].prefix.lib64)
+            gpp('-O2', '-g', '-DNDEBUG', '-rdynamic',
+                'corgegator.cc.o', '-o', 'corgegator',
+                '-Wl,-rpath,%s' % prefix.lib64,
+                '-Wl,-rpath,%s' % spec['quux'].prefix.lib64,
+                '-Wl,-rpath,%s' % spec['garply'].prefix.lib64,
+                'libcorge.so',
+                '%s/libquux.so' % spec['quux'].prefix.lib64,
+                '%s/libgarply.so' % spec['garply'].prefix.lib64)
+            mkdirp(prefix.lib64)
+            copy('libcorge.so', '%s/libcorge.so' % prefix.lib64)
         copy('corgegator', '%s/corgegator' % prefix.lib64)
-        copy('libcorge.so', '%s/libcorge.so' % prefix.lib64)
         copy('%s/corge/corge.h' % self.stage.source_path,
              '%s/corge/corge.h' % prefix.include)
         mkdirp(prefix.bin)
diff --git a/var/spack/repos/builtin.mock/packages/garply/package.py b/var/spack/repos/builtin.mock/packages/garply/package.py
index 8fa0778287..289e172c91 100644
--- a/var/spack/repos/builtin.mock/packages/garply/package.py
+++ b/var/spack/repos/builtin.mock/packages/garply/package.py
@@ -6,6 +6,7 @@
 
 from spack import *
 import os
+import sys
 
 
 class Garply(Package):
@@ -73,7 +74,6 @@ class Garply
         garply_version_h = '''const int garply_version_major = %s;
 const int garply_version_minor = %s;
 '''
-        mkdirp(prefix.lib64)
         mkdirp('%s/garply' % prefix.include)
         mkdirp('%s/garply' % self.stage.source_path)
         with open('%s/garply_version.h' % self.stage.source_path, 'w')  as f:
@@ -86,6 +86,8 @@ class Garply
                   self.stage.source_path, 'w') as f:
             f.write(garplinator_cc)
         gpp = which('/usr/bin/g++')
+        if sys.platform == 'darwin':
+            gpp = which('/usr/bin/clang++')
         gpp('-Dgarply_EXPORTS',
             '-I%s' % self.stage.source_path,
             '-O2', '-g', '-DNDEBUG', '-fPIC',
@@ -96,13 +98,28 @@ class Garply
             '-O2', '-g', '-DNDEBUG', '-fPIC',
             '-o', 'garplinator.cc.o',
             '-c', '%s/garply/garplinator.cc' % self.stage.source_path)
-        gpp('-fPIC', '-O2', '-g', '-DNDEBUG', '-shared',
-            '-Wl,-soname,libgarply.so', '-o', 'libgarply.so', 'garply.cc.o')
-        gpp('-O2', '-g', '-DNDEBUG', '-rdynamic',
-            'garplinator.cc.o', '-o', 'garplinator',
-            '-Wl,-rpath,%s' % prefix.lib64,
-            'libgarply.so')
-        copy('libgarply.so', '%s/libgarply.so' % prefix.lib64)
+        if sys.platform == 'darwin':
+            gpp('-fPIC', '-O2', '-g', '-DNDEBUG', '-dynamiclib',
+                '-Wl,-headerpad_max_install_names', '-o', 'libgarply.dylib',
+                '-install_name', '@rpath/libgarply.dylib',
+                'garply.cc.o')
+            gpp('-O2', '-g', '-DNDEBUG', '-Wl,-search_paths_first',
+                '-Wl,-headerpad_max_install_names',
+                'garplinator.cc.o', '-o', 'garplinator',
+                '-Wl,-rpath,%s' % prefix.lib64,
+                'libgarply.dylib')
+            mkdirp(prefix.lib64)
+            copy('libgarply.dylib', '%s/libgarply.dylib' % prefix.lib64)
+        else:
+            gpp('-fPIC', '-O2', '-g', '-DNDEBUG', '-shared',
+                '-Wl,-soname,libgarply.so',
+                '-o', 'libgarply.so', 'garply.cc.o')
+            gpp('-O2', '-g', '-DNDEBUG', '-rdynamic',
+                'garplinator.cc.o', '-o', 'garplinator',
+                '-Wl,-rpath,%s' % prefix.lib64,
+                'libgarply.so')
+            mkdirp(prefix.lib64)
+            copy('libgarply.so', '%s/libgarply.so' % prefix.lib64)
         copy('garplinator', '%s/garplinator' % prefix.lib64)
         copy('%s/garply/garply.h' % self.stage.source_path,
              '%s/garply/garply.h' % prefix.include)
diff --git a/var/spack/repos/builtin.mock/packages/quux/package.py b/var/spack/repos/builtin.mock/packages/quux/package.py
index 6db243f154..80508d3b55 100644
--- a/var/spack/repos/builtin.mock/packages/quux/package.py
+++ b/var/spack/repos/builtin.mock/packages/quux/package.py
@@ -6,6 +6,7 @@
 
 from spack import *
 import os
+import sys
 
 
 class Quux(Package):
@@ -87,7 +88,6 @@ class Quux
         quux_version_h = '''const int quux_version_major = %s;
 const int quux_version_minor = %s;
 '''
-        mkdirp(prefix.lib64)
         mkdirp('%s/quux' % prefix.include)
         with open('%s/quux_version.h' % self.stage.source_path, 'w')  as f:
             f.write(quux_version_h % (self.version[0], self.version[1:]))
@@ -98,6 +98,8 @@ class Quux
         with open('%s/quux/quuxifier.cc' % self.stage.source_path, 'w') as f:
             f.write(quuxifier_cc)
         gpp = which('/usr/bin/g++')
+        if sys.platform == 'darwin':
+            gpp = which('/usr/bin/clang++')
         gpp('-Dquux_EXPORTS',
             '-I%s' % self.stage.source_path,
             '-I%s' % spec['garply'].prefix.include,
@@ -110,18 +112,36 @@ class Quux
             '-O2', '-g', '-DNDEBUG', '-fPIC',
             '-o', 'quuxifier.cc.o',
             '-c', 'quux/quuxifier.cc')
-        gpp('-fPIC', '-O2', '-g', '-DNDEBUG', '-shared',
-            '-Wl,-soname,libquux.so', '-o', 'libquux.so', 'quux.cc.o',
-            '-Wl,-rpath,%s:%s::::' % (prefix.lib64,
-                                      spec['garply'].prefix.lib64),
-            '%s/libgarply.so' % spec['garply'].prefix.lib64)
-        gpp('-O2', '-g', '-DNDEBUG', '-rdynamic',
-            'quuxifier.cc.o', '-o', 'quuxifier',
-            '-Wl,-rpath,%s:%s::::' % (prefix.lib64,
-                                      spec['garply'].prefix.lib64),
-            'libquux.so',
-            '%s/libgarply.so' % spec['garply'].prefix.lib64)
-        copy('libquux.so', '%s/libquux.so' % prefix.lib64)
+        if sys.platform == 'darwin':
+            gpp('-fPIC', '-O2', '-g', '-DNDEBUG',
+                '-dynamiclib', '-Wl,-headerpad_max_install_names',
+                '-o', 'libquux.dylib',
+                '-install_name', '@rpath/libcorge.dylib',
+                'quux.cc.o', '-Wl,-rpath,%s' % prefix.lib64,
+                '-Wl,-rpath,%s' % spec['garply'].prefix.lib64,
+                '%s/libgarply.dylib' % spec['garply'].prefix.lib64)
+            gpp('-O2', '-g', '-DNDEBUG',
+                'quuxifier.cc.o', '-o', 'quuxifier',
+                '-Wl,-rpath,%s' % prefix.lib64,
+                '-Wl,-rpath,%s' % spec['garply'].prefix.lib64,
+                'libquux.dylib',
+                '%s/libgarply.dylib' % spec['garply'].prefix.lib64)
+            mkdirp(prefix.lib64)
+            copy('libquux.dylib', '%s/libquux.dylib' % prefix.lib64)
+        else:
+            gpp('-fPIC', '-O2', '-g', '-DNDEBUG', '-shared',
+                '-Wl,-soname,libquux.so', '-o', 'libquux.so', 'quux.cc.o',
+                '-Wl,-rpath,%s:%s::::' % (prefix.lib64,
+                                          spec['garply'].prefix.lib64),
+                '%s/libgarply.so' % spec['garply'].prefix.lib64)
+            gpp('-O2', '-g', '-DNDEBUG', '-rdynamic',
+                'quuxifier.cc.o', '-o', 'quuxifier',
+                '-Wl,-rpath,%s:%s::::' % (prefix.lib64,
+                                          spec['garply'].prefix.lib64),
+                'libquux.so',
+                '%s/libgarply.so' % spec['garply'].prefix.lib64)
+            mkdirp(prefix.lib64)
+            copy('libquux.so', '%s/libquux.so' % prefix.lib64)
         copy('quuxifier', '%s/quuxifier' % prefix.lib64)
         copy('%s/quux/quux.h' % self.stage.source_path,
              '%s/quux/quux.h' % prefix.include)
-- 
GitLab