[MacPorts] #44504: rev-upgrade: print a different message if a library exists, but has a bad install name
MacPorts
noreply at macports.org
Wed Jul 30 18:40:55 PDT 2014
#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
More information about the macports-tickets
mailing list