#44504: rev-upgrade: print a different message if a library exists, but has a bad install name -------------------------+-------------------------------- Reporter: egall@… | Owner: macports-tickets@… Type: enhancement | Status: new Priority: Normal | Milestone: Component: base | Version: 2.3.1 Keywords: rev-upgrade | Port: -------------------------+-------------------------------- I recently ran into an issue where... well before I describe it, some backstory. I have a port for an old version of gnutls (specifically gnutls2) that I have configured to build against a port for libcfgplus. It builds successfully against it, but upon `rev-upgrade`, I started seeing messages like this: {{{ Could not open libcfg+.0.6.2.dylib: Error opening or reading file (referenced from /opt/local/lib/gnutls2/bin/certtool2) DEBUG: Marking /opt/local/lib/gnutls2/bin/certtool2 as broken }}} This is confusing. My first instinct was to just revbump without thinking, as that is what I normally do with `rev-upgrade` issues. But then when it still failed and I actually stopped to think, my first thought was, "How is that happening? I have libcfgplus installed, and gnutls2 successfully built against it, so why is rev-upgrade failing to find it?" So I verified my installation: {{{ $ stat /opt/local/lib/libcfg+.0.6.2.dylib 234881026 19178807 -rw-r--r-- 1 root admin 0 76276 "Jul 30 17:42:23 2014" "Apr 6 12:58:22 2014" "Apr 6 12:58:26 2014" "Apr 6 12:58:22 2014" 4096 152 0 /opt/local/lib/libcfg+.0.6.2.dylib $ port contents libcfgplus | grep dylib /opt/local/lib/libcfg+.0.6.2.dylib /opt/local/lib/libcfg+.dylib $ port contents libcfgplus | grep dylib | xargs /usr/bin/file /opt/local/lib/libcfg+.0.6.2.dylib: Mach-O universal binary with 2 architectures /opt/local/lib/libcfg+.0.6.2.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64 /opt/local/lib/libcfg+.0.6.2.dylib (for architecture i386): Mach-O dynamically linked shared library i386 /opt/local/lib/libcfg+.dylib: Mach-O universal binary with 2 architectures /opt/local/lib/libcfg+.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64 /opt/local/lib/libcfg+.dylib (for architecture i386): Mach-O dynamically linked shared library i386 }}} So after verifying that the library that `rev-upgrade` thought was missing was actually present after all, I tried to think of why `rev-upgrade` might have been failing to find it. The first explanation I came up with was to blame `dyld`, so I tried messing around with the `DYLD_FALLBACK_LIBRARY_PATH` environment variable, but that was hack-ish and failed to lead anywhere. Next I assumed that it was because of the "`+`" in the library name, but I had other libraries installed with "`+`"-es in their names, and they were okay, so I ruled out that possibility. Then I looked closer and next decided to try verifying the actual linking: {{{ $ otool -L /opt/local/lib/gnutls2/bin/certtool2 /opt/local/lib/gnutls2/bin/certtool2: /opt/local/lib/gnutls2/lib/libgnutls.26.dylib (compatibility version 49.0.0, current version 49.3.0) /opt/local/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.8) /opt/local/lib/libintl.8.dylib (compatibility version 10.0.0, current version 10.2.0) /opt/local/lib/libreadline.6.dylib (compatibility version 6.0.0, current version 6.3.0) /opt/local/lib/libgcrypt.11.dylib (compatibility version 20.0.0, current version 20.2.0) /opt/local/lib/libgpg-error.0.dylib (compatibility version 11.0.0, current version 11.0.0) libcfg+.0.6.2.dylib (compatibility version 0.0.0, current version 0.0.0) /opt/local/lib/liblzo2.2.dylib (compatibility version 3.0.0, current version 3.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.11) /opt/local/lib/libp11-kit.0.dylib (compatibility version 1.0.0, current version 1.0.0) }}} The libcfg+ entry looked weird, so I double-checked the install names: {{{ $ port contents libcfgplus | grep dylib | xargs otool -D /opt/local/lib/libcfg+.0.6.2.dylib: libcfg+.0.6.2.dylib /opt/local/lib/libcfg+.dylib: libcfg+.0.6.2.dylib }}} I inferred from this that the weird install names must be the issue, so I threw some code into my Portfile to fix the install names, upgraded, and that fixed things. However, this could have been a lot simpler to figure out if the error message had given me some more accurate information. Although I am not entirely sure how exactly `rev-upgrade` would go about determining in an automated fashion if an error was due to a bad install name vs. an actually missing file though... The method I used manually requires knowing which port a missing library is supposed to come from, and I cannot think of a way that MacPorts could be expected to know this itself... searching to try to find it would probably be a waste of time and resources... [[BR]] How about this for a heuristic: If an install name is missing any path separators, then it is probably relative, and therefore we can probably assume that it is bad. `rev-upgrade` already does some parsing of the install names when deciding to skip ones containing `@rpath` or `@executable_path`, so perhaps while scanning for those, it could also add a check for a '`/`' character, and then print a warning if the install name is missing one? btw, apparently there were some other issues with `rev-upgrade` and bad install names previously as well that probably could have also benefitted from this being clarified: - #33044 - #34465 - #35042 -- Ticket URL: <https://trac.macports.org/ticket/44504> MacPorts <http://www.macports.org/> Ports system for OS X