Steve Christensen wrote:
The important thing to note is that the install name is only used at runtime to locate the libraries in their installed locations.
I may be misunderstanding this statement, but it seems wrong.
Do an 'otool -D' on one or more of the libs in the SDK frameworks. You should find that they all have paths in /System/Library/Frameworks/, i.e. their actual runtime location, NOT their location in an SDK directory.
In particular, "only used at runtime" directly contradicts the slightly later statement:
The install name gets stuffed into your executable at link time and used at runtime to locate the specific library so it can resolve the symbols.
This is correct. The install-name DOES get stored into your executable (or lib) at link time. Since the linker does this at link time, it's wrong to say "the install name is *only* used at runtime" [emphasis added]. In reality, install name is used at link time AND at runtime.
Because of this, the install-name of all the libs your executable links against must be correct AT LINK TIME. Furthermore, install-names must reflect the INTENDED RUNTIME environment, and NOT the existing link-time environment. If that isn't so, then a patchup must occur with install_name_tool. Frankly, it's easier to prevent the problem than to patch it, though. Simply make it so all link-time install-names correctly reference the intended runtime install-names. For example, the SDK's do this.
This should be clear in that you typically link against frameworks in one of the SDK directories, but at runtime your executable finds the ones in /System/Library/ Frameworks.
This seems wrong, too. The libs in an SDK are basically just symbols and inter-library references, i.e. references to other libs via install-names. The inter-lib references are the actual runtime locations, and NOT the SDK locations.
In general, one should think about libs and frameworks and install-names from the "bottom up". That is, think about what happens starting with the framework library file and work up to its direct clients, then its indirect clients, rather than thinking about what happens from your code and working down into the libs and frameworks.
Starting from the OP's library "C", and knowing that the linker will copy the install-name exactly as given in C's library-file, what does "C" have to tell its clients? Two things: 1. its own install-name. 2. the install-names of libraries it references (e.g. "D" and "E").
So with "C" as an example, what did "D" and "E" have to tell their client, "C", in order for "C" to link correctly? The same thing: its own install-name, and the install-names of its sub-libs. Eventually you'll get to a lib that only has to provide its own install-name, or a small set of circular references.
For now, suppose that "C" doesn't refer to any other libs, i.e. no "D" or "E". So it only has to provide its own install-name. Knowing that the linker will embed that install-name in libraries farther up the line, what should "C" have as its install-name? Simple: its actual runtime install-name. Very important: runtime, NOT link time.
When "B" links to "C", the linker will then copy C's embedded install-name into "B". So, if C's install-name is wrong when it's being linked, then all its transitive clients (A and B) will have the wrong install-name. So you better make sure C is correct first. If you do, then there's no need for any post-linking install-name cleanup, because all the libs that were linked were correct to begin with. In other words, instead of thinking about how to fix A referring to B referring to C, think about how to make C correct, so B will be correct, and A will be correct.
oz(prevention) > lb(cure).
2. Run install_name_tool to change C's install name to @loader_path/../Frameworks/C.dylib.
I think @loader_path/C.dylib would be better.
Again, going back to the principle of working up instead of down, what does the OP want to accomplish here? If B and C are in the same location, then it shouldn't matter where that location is, whether in a dir named "Frameworks" or not. If B and C are intended to be adjacent, then injecting ../Frameworks/ in their install-names seems a bit silly.
The only reason I can think of to embed a "../Frameworks" in C's install-name is if you want to require "C" to ONLY be used from a Frameworks directory. That seems like an unnecessary restriction to me. YMMV.
By the way, if one is building library C from source, then it should be built with the correct install-name in the first place, rather than running a patchup pass with install_name_tool.
There is an Xcode target setting for specifying the target's install-name when it's built. Enter "install" into the Settings search-box and note the Installation Directory or INSTALL_PATH setting. Enter "@loader_path" here.
The only reason to apply install_name_tool to a library C would be if one is starting from an already-built version. In that case, it is advisable to check the libs it refers to, as well.
-- GG
|