Opened 10 years ago

Closed 10 years ago

Last modified 7 years ago

#44504 closed enhancement (fixed)

rev-upgrade: print a different message if a library exists, but has a bad install name

Reported by: cooljeanius (Eric Gallager) Owned by: neverpanic (Clemens Lang)
Priority: Normal Milestone: MacPorts 2.4.0
Component: base Version: 2.3.1
Keywords: rev-upgrade Cc:
Port:

Description

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...
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:

Change History (5)

comment:1 in reply to:  description Changed 10 years ago by ryandesign (Ryan Carsten Schmidt)

Replying to egall@…:

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)

This is confusing.

The error message is technically correct. There is no file "libcfg+.0.6.2.dylib" in whatever directory it's looking in, which is evidently not the directory that file is in. But the message is confusing in that it's not made clear that the expected value is an absolute path to a file, not just a filename.

comment:2 Changed 10 years ago by neverpanic (Clemens Lang)

Cc: cal@… removed
Milestone: MacPorts Future
Owner: changed from macports-tickets@… to cal@…
Status: newassigned

There's port rev-upgrade --id-loadcmd-check, which checks the library IDs and would have warned you about a relative path in libcfg+.0.6.2.dylib. It isn't enabled by default because it's really only useful for maintainers.

Nevertheless, r122825.

comment:3 Changed 10 years ago by neverpanic (Clemens Lang)

Resolution: fixed
Status: assignedclosed

comment:4 in reply to:  2 Changed 10 years ago by cooljeanius (Eric Gallager)

Replying to cal@…:

There's port rev-upgrade --id-loadcmd-check, which checks the library IDs and would have warned you about a relative path in libcfg+.0.6.2.dylib.

Cool, I was unaware of this option. I see now that it is documented in the manpage and port help rev-upgrade though...

Nevertheless, r122825.

Thanks!

comment:5 Changed 7 years ago by jmroot (Joshua Root)

Milestone: MacPorts FutureMacPorts 2.4.0
Note: See TracTickets for help on using tickets.