Repository: spack/spack

Issue:
Duplicate rpath error when creating build caches on macOS
### Steps to reproduce

I am having problems (and a question below) creating build caches on macOS, using `spack buildcache create -u -r -d /Users/heinzell/prod/spack-build-cache/` . This example error is for `libtiff`:
```
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/install_name_tool: "-rpath /Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/libjpeg-turbo-2.1.0-7gmqal5/lib @loader_path/../../libjpeg-turbo-2.1.0-7gmqal5/lib" specified more than once
Usage: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/install_name_tool [-change old new] ... [-rpath old new] ... [-add_rpath new] ... [-delete_rpath old] ... [-id name] input
==> Error: Command exited with status 1:
    'install_name_tool' '-change' '/Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/zlib-1.2.13-x4mtmmm/lib/libz.1.dylib' '@loader_path/../../zlib-1.2.13-x4mtmmm/lib/libz.1.dylib' '-rpath' '/Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/libjpeg-turbo-2.1.0-7gmqal5/lib' '@loader_path/../../libjpeg-turbo-2.1.0-7gmqal5/lib' '-rpath' '/Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/libtiff-4.4.0-7gbfmhw/lib' '@loader_path/.' '-rpath' '/Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/libtiff-4.4.0-7gbfmhw/lib64' '@loader_path/../lib64' '-rpath' '/Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/zlib-1.2.13-x4mtmmm/lib' '@loader_path/../../zlib-1.2.13-x4mtmmm/lib' '-rpath' '/Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/libjpeg-turbo-2.1.0-7gmqal5/lib' '@loader_path/../../libjpeg-turbo-2.1.0-7gmqal5/lib' '/var/folders/gb/w8lys0xn3c35rbw_5vfq4mkxxgj2gv/T/tmp3jk20l3u/libtiff-4.4.0-7gbfmhw/lib/libtiff.5.8.0.dylib'
```
More information:
```
> otool -L envs/skylab-dev/install/apple-clang/13.1.6/libtiff-4.4.0-7gbfmhw/lib/libtiff.5.8.0.dylib
envs/skylab-dev/install/apple-clang/13.1.6/libtiff-4.4.0-7gbfmhw/lib/libtiff.5.8.0.dylib:
	@rpath/libtiff.5.dylib (compatibility version 5.0.0, current version 5.8.0)
	/Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/zlib-1.2.13-x4mtmmm/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.13)
	@rpath/libjpeg.62.dylib (compatibility version 62.0.0, current version 62.3.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.100.3)
```
and
```
> otool -l envs/skylab-dev/install/apple-clang/13.1.6/libtiff-4.4.0-7gbfmhw/lib/libtiff.5.8.0.dylib
envs/skylab-dev/install/apple-clang/13.1.6/libtiff-4.4.0-7gbfmhw/lib/libtiff.5.8.0.dylib:
Load command 0
      cmd LC_SEGMENT_64
  cmdsize 472
  segname __TEXT
   vmaddr 0x0000000000000000
   vmsize 0x0000000000064000
  fileoff 0
 filesize 409600
  maxprot 0x00000005
 initprot 0x00000005
   nsects 5
    flags 0x0
Section
  sectname __text
   segname __TEXT
      addr 0x0000000000003140
      size 0x000000000003fd08
    offset 12608
     align 2^4 (16)
    reloff 0
    nreloc 0
     flags 0x80000400
 reserved1 0
 reserved2 0
Section
  sectname __stubs
   segname __TEXT
      addr 0x0000000000042e48
      size 0x00000000000001c2
    offset 273992
     align 2^1 (2)
    reloff 0
    nreloc 0
     flags 0x80000408
 reserved1 0 (index into indirect symbol table)
 reserved2 6 (size of stubs)
Section
  sectname __const
   segname __TEXT
      addr 0x0000000000043010
      size 0x000000000001aa44
    offset 274448
     align 2^4 (16)
    reloff 0
    nreloc 0
     flags 0x00000000
 reserved1 0
 reserved2 0
Section
  sectname __cstring
   segname __TEXT
      addr 0x000000000005da54
      size 0x00000000000060f8
    offset 383572
     align 2^0 (1)
    reloff 0
    nreloc 0
     flags 0x00000002
 reserved1 0
 reserved2 0
Section
  sectname __unwind_info
   segname __TEXT
      addr 0x0000000000063b4c
      size 0x00000000000004ac
    offset 408396
     align 2^2 (4)
    reloff 0
    nreloc 0
     flags 0x00000000
 reserved1 0
 reserved2 0
Load command 1
      cmd LC_SEGMENT_64
  cmdsize 232
  segname __DATA_CONST
   vmaddr 0x0000000000064000
   vmsize 0x0000000000004000
  fileoff 409600
 filesize 16384
  maxprot 0x00000003
 initprot 0x00000003
   nsects 2
    flags 0x10
Section
  sectname __got
   segname __DATA_CONST
      addr 0x0000000000064000
      size 0x0000000000000280
    offset 409600
     align 2^3 (8)
    reloff 0
    nreloc 0
     flags 0x00000006
 reserved1 75 (index into indirect symbol table)
 reserved2 0
Section
  sectname __const
   segname __DATA_CONST
      addr 0x0000000000064280
      size 0x00000000000038f0
    offset 410240
     align 2^4 (16)
    reloff 0
    nreloc 0
     flags 0x00000000
 reserved1 0
 reserved2 0
Load command 2
      cmd LC_SEGMENT_64
  cmdsize 312
  segname __DATA
   vmaddr 0x0000000000068000
   vmsize 0x0000000000004000
  fileoff 425984
 filesize 16384
  maxprot 0x00000003
 initprot 0x00000003
   nsects 3
    flags 0x0
Section
  sectname __data
   segname __DATA
      addr 0x0000000000068000
      size 0x0000000000000010
    offset 425984
     align 2^3 (8)
    reloff 0
    nreloc 0
     flags 0x00000000
 reserved1 0
 reserved2 0
Section
  sectname __bss
   segname __DATA
      addr 0x0000000000068010
      size 0x00000000000001a1
    offset 0
     align 2^4 (16)
    reloff 0
    nreloc 0
     flags 0x00000001
 reserved1 0
 reserved2 0
Section
  sectname __common
   segname __DATA
      addr 0x00000000000681b8
      size 0x0000000000000010
    offset 0
     align 2^3 (8)
    reloff 0
    nreloc 0
     flags 0x00000001
 reserved1 0
 reserved2 0
Load command 3
      cmd LC_SEGMENT_64
  cmdsize 72
  segname __LINKEDIT
   vmaddr 0x000000000006c000
   vmsize 0x0000000000018000
  fileoff 442368
 filesize 95384
  maxprot 0x00000001
 initprot 0x00000001
   nsects 0
    flags 0x0
Load command 4
          cmd LC_ID_DYLIB
      cmdsize 48
         name @rpath/libtiff.5.dylib (offset 24)
   time stamp 1 Wed Dec 31 17:00:01 1969
      current version 5.8.0
compatibility version 5.0.0
Load command 5
      cmd LC_DYLD_CHAINED_FIXUPS
  cmdsize 16
  dataoff 442368
 datasize 1400
Load command 6
      cmd LC_DYLD_EXPORTS_TRIE
  cmdsize 16
  dataoff 443768
 datasize 5216
Load command 7
     cmd LC_SYMTAB
 cmdsize 24
  symoff 450264
   nsyms 3153
  stroff 501336
 strsize 36416
Load command 8
            cmd LC_DYSYMTAB
        cmdsize 80
      ilocalsym 0
      nlocalsym 2810
     iextdefsym 2810
     nextdefsym 265
      iundefsym 3075
      nundefsym 78
         tocoff 0
           ntoc 0
      modtaboff 0
        nmodtab 0
   extrefsymoff 0
    nextrefsyms 0
 indirectsymoff 500712
  nindirectsyms 155
      extreloff 0
        nextrel 0
      locreloff 0
        nlocrel 0
Load command 9
     cmd LC_UUID
 cmdsize 24
    uuid 4DF6FFCF-793B-35BE-AD3D-22FD83521D2F
Load command 10
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform 1
    minos 12.0
      sdk 12.3
   ntools 1
     tool 3
  version 762.0
Load command 11
      cmd LC_SOURCE_VERSION
  cmdsize 16
  version 0.0
Load command 12
          cmd LC_LOAD_DYLIB
      cmdsize 176
         name /Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/zlib-1.2.13-x4mtmmm/lib/libz.1.dylib (offset 24)
   time stamp 2 Wed Dec 31 17:00:02 1969
      current version 1.2.13
compatibility version 1.0.0
Load command 13
          cmd LC_LOAD_DYLIB
      cmdsize 48
         name @rpath/libjpeg.62.dylib (offset 24)
   time stamp 2 Wed Dec 31 17:00:02 1969
      current version 62.3.0
compatibility version 62.0.0
Load command 14
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name /usr/lib/libSystem.B.dylib (offset 24)
   time stamp 2 Wed Dec 31 17:00:02 1969
      current version 1311.100.3
compatibility version 1.0.0
Load command 15
          cmd LC_RPATH
      cmdsize 160
         path /Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/libjpeg-turbo-2.1.0-7gmqal5/lib (offset 12)
Load command 16
          cmd LC_RPATH
      cmdsize 152
         path /Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/libtiff-4.4.0-7gbfmhw/lib (offset 12)
Load command 17
          cmd LC_RPATH
      cmdsize 152
         path /Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/libtiff-4.4.0-7gbfmhw/lib64 (offset 12)
Load command 18
          cmd LC_RPATH
      cmdsize 152
         path /Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/zlib-1.2.13-x4mtmmm/lib (offset 12)
Load command 19
          cmd LC_RPATH
      cmdsize 160
         path /Users/heinzell/work/spack-stack/spack-stack-build-and-source-cache/envs/skylab-dev/install/apple-clang/13.1.6/libjpeg-turbo-2.1.0-7gmqal5/lib (offset 12)
Load command 20
      cmd LC_FUNCTION_STARTS
  cmdsize 16
  dataoff 448984
 datasize 832
Load command 21
      cmd LC_DATA_IN_CODE
  cmdsize 16
  dataoff 449816
 datasize 448
```

### Error message

See above

### Information on your system

```
* **Spack:** 0.20.0.dev0 (7df3d0b0e1eb8962266f222ebfd8de9d513c3922)
* **Python:** 3.9.13
* **Platform:** darwin-monterey-x86_64
* **Concretizer:** clingo
```

### General information

- [X] I have run `spack debug report` and reported the version of Spack/Python/Platform
- [X] I have searched the issues of this repo and believe this is not a duplicate
- [X] I have run the failing commands in debug mode and reported the output


Discussion:

Resolving patch:
diff --git a/lib/spack/spack/relocate.py b/lib/spack/spack/relocate.py
--- a/lib/spack/spack/relocate.py
+++ b/lib/spack/spack/relocate.py
@@ -3,6 +3,7 @@
 #
 # SPDX-License-Identifier: (Apache-2.0 OR MIT)
 import collections
+import itertools
 import multiprocessing.pool
 import os
 import re
@@ -299,17 +300,24 @@ def modify_macho_object(cur_path, rpaths, deps, idpath, paths_to_paths):
     if idpath:
         new_idpath = paths_to_paths.get(idpath, None)
         if new_idpath and not idpath == new_idpath:
-            args += ["-id", new_idpath]
+            args += [("-id", new_idpath)]
+
     for dep in deps:
         new_dep = paths_to_paths.get(dep)
         if new_dep and dep != new_dep:
-            args += ["-change", dep, new_dep]
+            args += [("-change", dep, new_dep)]
 
+    new_rpaths = []
     for orig_rpath in rpaths:
         new_rpath = paths_to_paths.get(orig_rpath)
         if new_rpath and not orig_rpath == new_rpath:
-            args += ["-rpath", orig_rpath, new_rpath]
+            args_to_add = ("-rpath", orig_rpath, new_rpath)
+            if args_to_add not in args and new_rpath not in new_rpaths:
+                args += [args_to_add]
+                new_rpaths.append(new_rpath)
 
+    # Deduplicate and flatten
+    args = list(itertools.chain.from_iterable(llnl.util.lang.dedupe(args)))
     if args:
         args.append(str(cur_path))
         install_name_tool = executable.Executable("install_name_tool")


Test patch: