Runpath Search Paths can't find library even with #rpath/library.dylib - xcode

I've been banging my head against the wall on this for hours. I've been playing around with CMUSphinx's pocketsphinx library, running on OSX 10.10/XCode 7.2,and want to get my .app bundle to work on computers besides my own. Most importantly, there are three dynamic libraries that have to be embedded in the .app bundle(libpocketsphinx.3.dylib, libsphinxad.3.dylib, and libsphinxbase.3.dylib), and then loaded using Runpath Search Paths settings in XCode.
I've read just about everything I can find on how to get this to work. I should note that the .app bundle compiles/runs as intended on my own machine. I've made sure that the libraries are copied into the .app bundle's /Contents/Frameworks folder. The libraries are not using references, but are copied into my source folder (as per a forum post on this exact issue on CMUSphinx's page). I've tried just about every combination of using install_name_tool for #rpath/libraryname.dylib, as well as #loader_path and #executable_path in both the executable (so changing it in XCode to #whatever_path/../Frameworks), as well as the three library files. I also have tried #loader_path/Frameworks per another post here, but no luck.
Whats weird is the error I'm getting seems like it is loading libsphinxad.3.dylib, as both libsphinxad.3.dylib and libsphinxad.3.dylib rely on libsphinxbase.3.dylib, but I get this error in the crash report:
Dyld Error Message:
Library not loaded: /usr/local/lib/libsphinxbase.3.dylib
Referenced from: /Volumes/SunGate/VoiceCommander.app/Contents/Frameworks/libsphinxad.3.dylib
Reason: image not found
Note, the /Volumes/SunGate/ is just a drive on another machine I'm testing this on.
I would really appreciate help with this! I will do my best to provide any other information that might help solve this!

I found this lib by using the "find" command on my system. Not surprisingly it was here
sphinxbase/src/libsphinxbase/.libs/libsphinxbase.3.dylib
I linked it to /usr/local/lib/
ln -s sphinxbase/src/libsphinxbase/.libs/libsphinxbase.3.dylib /usr/local/lib/libsphinxbase.3.dylib
And all set to go!

Related

dylib to dylib pathing on mac osx, how to make rpath work on mac?

We have a project which dynamically links against several dylibs. When copy the build to another mac. One need to run "otool" over the dylibs and executable in order to fix the shared library paths in them during "install".
Looks like OSX had some strange requirements for DLL to DLL pathing that made relative paths not work in them (i.e: using rpath). My questions here:
what is the the normal way to ship a software on mac? i.e: when running either a .pkg or .dmg installer, how one make sure the dylibs installed are able to link against each other in relative path? the dylib path must be fixed with either the rpath or some post install scripts
if we are not allowed to run a post install script to fix this, what are the other options?
Relative paths should work just fine. For example assume a macOS application bundle. The application lives in Contents/MacOS while the library lives in Contents/Frameworks. In this case you would relink the application's libraries to something like this #executable_path/../Frameworks/library.so. If you don't use an application bundle but have all files in the same directory simple using #executable_path should work too.
No need to use #rpath in these examples. you can use this too but it requires the application to define this path. This may be helpful if you want to distribute a library and people are supposed to link to your library. That way they can give an #rpath in their application to find the library without otool-ing them.
And you of course you make these changes before your package up your application into a .dmg or .pkg.

MacOSX screensaver not loading due to Library not loaded: #rpath/libswiftAppKit.dylib

We have a working Mac OS X screensaver as a standalone Xcode project, but we needed to have it as a target in another Xcode project that also contains a related app.
I added a target for a screensaver, copied the code, added to that target, etc, etc. The code is the same one that works in the other screensaver, but on this one, it generates the following error:
2015-03-10 09:43:24.766 System Preferences[32495]: Error loading /Users/pupeno/Library/Screen Savers/Ninja.saver/Contents/MacOS/Ninja: dlopen(/Users/pupeno/Library/Screen Savers/Ninja.saver/Contents/MacOS/Ninja, 265): Library not loaded: #rpath/libswiftAppKit.dylib
Referenced from: /Users/pupeno/Library/Screen Savers/Ninja.saver/Contents/MacOS/Ninja
Reason: image not found
2015-03-10 09:43:24.766 System Preferences[32495]: ScreenSaverModules: can't get principalClass for /Users/pupeno/Library/Screen Savers/Ninja.saver
The library in question is definitely there:
$ ls -w1 Library/Screen\ Savers/Ninja.saver/Contents/Frameworks/
libswiftAppKit.dylib
libswiftCore.dylib
libswiftCoreGraphics.dylib
libswiftDarwin.dylib
libswiftDispatch.dylib
libswiftFoundation.dylib
libswiftObjectiveC.dylib
libswiftQuartzCore.dylib
libswiftSecurity.dylib
Any ideas what might be causing this?
The problem was that the Runpath Search Path, for some reason, in this new target, was blank. I fixed this problem by adding this:
#executable_path/../Frameworks #loader_path/../Frameworks
to it (which I took from the working screensaver configuration). This is how it looks like:
Like Pablo said, you need the following as your Runtime Search Path:
#executable_path/../Frameworks #loader_path/../Frameworks
This should be the default. Make sure it's there though. You also need to set Embedded Content Contains Swift Code to YES if you're using Swift. That took me awhile to figure out.
(Xcode should totally infer this. Oh well. I filed a radar for this awhile.)

Signing Firemonkey-generated dylib on Mac OS X

When I try to run codesign on a dylib created by Embarcadero's Firemonkey I get an error message:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate:
file not in an order that can be processed (local relocation entries
out of place): /Users/jwwalker/Documents/libV35SS.dylib
It might be related to this question: Reliable Deployment of Delphi-Generated Dylib on OSX
However, I tried reordering the load commands to make LC_ID_DYLIB come first, as was apparently the solution for that question, and it didn't help. Is there some other way to do binary editing on the file to fix it? Any clues as to the "right" location of the local relocation entries?
Using information from the Mach-o File Format Reference, I put together a tool that (at least in the case of my fairly small and simple dylib) rearranges data in the dylib to make it palatable to codesign. I released my code as open source.
The solution for the other question was patching the paths of the used dylibs directly in the dylib. That was basically doing manually what install_name_tool was supposed to do. But that won't help you for codesigning. That would basically mean you'd have to write your own code signing tool, but then it is still not certain that OSX will accept the signature of a "broken dylib".
You could take a closer look at the following source file. This is the best I've found so far about the correct order and the structure of the dylib.
http://www.opensource.apple.com/source/cctools/cctools-855/libstuff/checkout.c
Fixing this issue manually will probably be a big challenge. I guess you'd have to take the dylib apart and rewrite it:
https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
You might want to vote for this QC and tell Embarcadero that they must fix this if they want to support deployment to OSX 10.9.5 or Yosemite:
Report No: 125607 Status: Open
[MacOS] can not codesign libmidas.dylib for Apple Mac Store
http://qc.embarcadero.com/wc/qcmain.aspx?d=125607
QCWIN:Defect_No=125607

Reliable Deployment of Delphi-Generated Dylib on OSX

I would like to deploy a .dylib on OSX, which has been created with Delphi. This .dylib should be loadable by third-party applications.
This is going to seem like a duplicate question, but after plenty of searching, I can't find an answer for it. It's the same issue as this: https://forums.embarcadero.com/thread.jspa?messageID=592417
The problem is that the .dylib requires libcgunwind.1.0.dylib, but that it cannot find it when being run from a third-party application. As a test, I tried copying libcgunwind.1.0.dylib into usr/lib, and that worked. When OSX cannot locate the .dylib, it will always search in usr/lib. Unfortunately, I do not want to do this as a final solution, because it would require elevated permissions, and seems like a heavy handed way of dealing with a simple problem.
Inspecting a bit closer, I used otool to inspect my .dylib, and it gave me the following path: #rpath/libcgunwind.1.0.dylib.
The trouble is, there's no accounting for what paths will be listed in #rpath, when your .dylib is being run by a third-party application. For this to work, the application would always have to provide an absolute path to libcgunwind.1.0.dylib.
The obvious solution is to use install_name_tool to replace #rpath with #loader_path. If my logic is correct, this should cause my .dylib to always find libcgunwind.1.0.dylib, as long as they are in the same folder. This makes sense, as the .dylib ought to be in charge of finding its own dependencies.
So, I tried the following command line:
install_name_tool -change #rpath/libcgunwind.1.0.dylib #loader_path/libcgunwind.1.0.dylib libTest.dylib
and received this message:
install_name_tool: file not in an order that can be processed (local relocation entries out of place): libTest.dylib
I did some searching around for this error message, and I haven't been able to find any information on it. I have to assume that install_name_tool is expecting some specific conventions found in a gcc or llvm built .dylib, and that Delphi's compiler is not providing those conventions.
I did some digging around in Delphi's compiler dccosx, and checked the command-line arguments Delphi is sending to it, but I can't find any useful options. This way of using libcgunwind.1.0.dylib, seems to be implicit to the compiler, and not something I can adjust.
I'm not suggesting that this is the right way to tackle the issue, these are just the latest things that I've tried. If you can come up with a different way of working around the problem, please share your ideas!
The install_name_tool seems to require that certain parts of the dylib are in a certain order like "local relocation entries" then "symbol table", "local symbols", ... The error message means that this order is not as expected.
My suggestion is that you try to patch the dylib file. I do that all the time with OSX executables because I need to tell them which dylib versions they are compatible with. This fixes a couple of bugs in a Delphi OSX application. A dylib has a very similar structure as the executable. My experience is that patching these files is not as complicated as it sounds.
You can find the description of the file structure here:
https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
The LC_LOAD_DYLIB section is what you'll need to look at. You should be able to replace the dylib names with something longer as this section usually has some extra padding.

embedding multiple cross referencing frameworks in app bundle

so first off, I want to say that this question:
Bundle framework with application in XCode
and this question:
OSX: changing path of .framework
were both extremely helpful getting me up to this point, but I'm still not quite there.
So, like both the Original Posters for the two previous questions, I'm trying to embed a framework inside my app bundle. Or, rather, the issue is that I'm trying to embed MULTIPLE frameworks in my app bundle, some of which depend on eachother. I believe that even though my application can successfully find the frameworks (i've changed the install directory so the frameworks know where they are), the ones that reference each other are still looking for the frameworks to be installed in the normal ~/Library/Frameworks directory.
This is the output I'm getting when trying to run my app:
Dyld Error Message:
Library not loaded: #rpath/SDL.framework/Versions/A/SDL
Referenced from: /Users/Daly/Library/Developer/Xcode/DerivedData/Coin_Checkers_2-cibyiolfgsmcicdrcfxufftxzbsk/Build/Products/Debug/Coin Checkers 2.app/Contents/MacOS/../Frameworks/SDL_image.framework/SDL_image
Reason: image not found
Binary Images:
0x7fff5fc00000 - 0x7fff5fc3be0f dyld 132.1 (???) <29DECB19-0193-2575-D838-CF743F0400B2> /usr/lib/dyld
It seems to me that It's correctly loading SDL_image, but failing when SDL_image references SDL. Is there any similar trick I can use to direct the SDL_image framework to the correct location for my embedded SDL framework?
Thanks a bunch!
Oh, never mind. I hadn't seen this question until it showed up in the related section on the side:
Embedding frameworks in a Mac App Bundle
Apparently all I needed to do was set the runpath searchpath, and that solved all my problems. I had tried setting the Frameworks search path, but that didn't seem to help.
In fact, I redownloaded the frameworks to see if the install_name_tool steps were even necessary, and it seems they are not. they worked without it. Interesting.

Resources