install_name_tool changes not propagating on distribution - xcode

I am wrapping a python GUI into an application using py2app. On porting to another machine I noticed that I was having a dependency issue with libpng12.0.dylib. This is stored provided by the system, with X11, and is therefore not traditionally bundled by py2app.
Another dylib (which is bundled) requires a newer version of libpng. Using the commands below I attempted to link to a copy of libpng that I will include with the OS X. This works wonderfully locally, but when I attempt to copy the app, it reverts to the old path. The commands below should explain this better.
Copy my libpng to the Framework directory of my app.
cp /usr/X11/lib/libpng12.0.dylib dist/PyStretch.app/Contents/Frameworks/
Look at the paths of the dependencies of libgdal.1.dylib (which requires the newer libpng)
mbp:pystretch drferling$ otool -L
dist/PyStretch.app/Contents/MacOS/../Frameworks/libgdal.1.dylib
dist/PyStretch.app/Contents/MacOS/../Frameworks/libgdal.1.dylib:
#executable_path/../Frameworks/libgdal.1.dylib (compatibility version 18.0.0, current version 18.1.0)
...CLIPPED
/usr/X11/lib/libpng12.0.dylib (compatibility version 47.0.0, current version 47.0.0)
#executable_path/../Frameworks/libcfitsio.dylib (compatibility version 0.0.0, current version 0.0.0)
So libpng is linked to a system install. We need to change that to be linked to a local (to the app) installation.
install_name_tool -change /usr/X11/lib/libpng12.0.dylib #executable_path/../Frameworks/libpng12.0.dylib dist/PyStretch.app/Contents/MacOS/../Frameworks/libgdal.1.dylib
We then need to verify that that worked.
mbp:pystretch drferling$ otool -L
dist/PyStretch.app/Contents/MacOS/../Frameworks/libgdal.1.dylib dist/PyStretch.app/Contents/MacOS/../Frameworks/libgdal.1.dylib:
#executable_path/../Frameworks/libgdal.1.dylib (compatibility version 18.0.0, current version 18.1.0)
...CLIPPED
#executable_path/../Frameworks/libpng12.0.dylib (compatibility version 47.0.0, current version 47.0.0)
#executable_path/../Frameworks/libcfitsio.dylib (compatibility version 0.0.0, current version 0.0.0)
So it worked. libpng is now linked to the included copy, not the system copy.
I then copy the app over to another machine for testing and the libpng reverts to being statically linked to the system installation of libpng!
Why?
I also tried using install_tool_name -id, but the results are the same. The linking of my dylib keeps changing when I copy the app to another machine.

Related

IDL fails due to wrong libfreetype.6.dylib version on MacOS when called from Matlab

This is another interesting version of a libfreetype.6.dylib version incompatibility. Having figured it out, I feel it is worth documenting ...
The setup is as follows:
MacOS 10.9.5
IDL 8.3
Matlab 2013b
Matlab is used to create a shell script on the fly which in turn will call an IDL .sav file. The shell script is then called via the unix() command in Matlab.
When running the generated shell script from the shell, all works fine. When trying to run it from Matlab via the unix() command, a libfreetype.6.dylib version issue appears:
dyld: Library not loaded: /opt/X11/lib/libfreetype.6.dylib
Incompatible library version: libidl.8.3.dylib requires version 15.0.0 or later, but libfreetype.6.dylib provides version 10.0.0
As has been stated in other posts on similar effects but with other applications, the error message is misleading as the program evidently never tries to actually load /opt/X11/lib/libfreetype.6.dylib
The version of /opt/X11/lib/libfreetype.6.dylib can be checked via the otool:
otool -L libfreetype.6.dyliblibfreetype.6.dylib:
/opt/X11/lib/libfreetype.6.dylib (compatibility version 18.0.0, current version 18.2.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
/usr/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.5)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
Obviously the version provided by X11 is higher than what is required by IDL.
To fix this just copy /opt/X11/lib/libfreetype.6.dylib into /Applications/exelis/idl83/bin/bin.darwin.x86_64
Note: the libfreetype.6.dylib does not exist in the IDL application file hierarchy at all, so, presumably, some linking with the X11 provided library version must go wrong ... fixing that would probably be a cleaner solution.

Best way to deploy GStreamer framework with a Mac OS X application?

So the GStreamer documentation for 1.0+ seems to be...lacking to say the least. The GStreamer SDK has some helpul tips, but unforutnately they fall short.
So, here's what I've done. I've built an application that calls upon GStreamer in /Library/GStreamer.Framework/
I build using command-line tools. This is the only way I can build this application. I can't use the XCode GUI.
I want to submit this app to the store, but to do so I can't submit it as a package (so I can bundle the GStreamer package installer) which means I'll have to bundle GStreamer.framework with my application.
In the GStreamer SDK docs above, you will notice a tool called osxrelocator.py. This is great, because it changes all refrences of /Library/GStreamer.Framework to #executable_path/../Frameworks/GStreamer.framework/
BUT
Unfortunately all of the GStreamer .dylibs have an issue... You need to use install_name_tool -id to change their paths because install_name_tool -change doesn't change the paths to themselves!
So, for example using otool:
$ otool -L Application.app/Contents/Frameworks/GStreamer.framework/Versions/1.0/lib/libgstreamer-1.0.0.dylib
Application.app/Contents/Frameworks/GStreamer.framework/Versions/1.0/lib/libgstreamer-1.0.0.dylib:
Library/Frameworks/GStreamer.framework/Versions/1.0/lib/libgstreamer-1.0.0.dylib (compatibility version 402.0.0, current version 402.0.0)
Library/Frameworks/Frameworks/GStreamer.framework/Versions/1.0/lib/libgobject-2.0.0.dylib (compatibility version 4001.0.0, current version 4001.0.0)
Library/Frameworks/GStreamer.framework/Versions/1.0/lib/libffi.6.dylib (compatibility version 7.0.0, current version 7.1.0)
Library/Frameworks/GStreamer.framework/Versions/1.0/lib/libgmodule-2.0.0.dylib (compatibility version 4001.0.0, current version 4001.0.0)
Library/Frameworks/Frameworks/GStreamer.framework/Versions/1.0/lib/libglib-2.0.0.dylib (compatibility version 4001.0.0, current version 4001.0.0)
Library/Frameworks/Frameworks/GStreamer.framework/Versions/1.0/lib/libintl.8.dylib (compatibility version 10.0.0, current version 10.2.0)
Library/Frameworks/Frameworks/GStreamer.framework/Versions/1.0/lib/libiconv.2.dylib (compatibility version 8.0.0, current version 8.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 855.14.0)
Then using osxrelocator.py (which invokes install_name_tool -change):
./osxrelocator.py Application.app/Contents/MacOS /Library/Frameworks/GStreamer.framework/Versions/Current/lib #executable_path/../Frameworks/GStreamer.framework/Versions/Current/lib -r
Gives:
$ otool -L Application.app/Contents/Frameworks/GStreamer.framework/Versions/1.0/lib/libgstreamer-1.0.0.dylib
Application.app/Contents/Frameworks/GStreamer.framework/Versions/1.0/lib/libgstreamer-1.0.0.dylib:
/Library/Frameworks/GStreamer.framework/Versions/1.0/lib/libgstreamer-1.0.0.dylib (compatibility version 402.0.0, current version 402.0.0)
#executable_path/../Frameworks/GStreamer.framework/Versions/1.0/lib/libgobject-2.0.0.dylib (compatibility version 4001.0.0, current version 4001.0.0)
#executable_path/../Frameworks/GStreamer.framework/Versions/1.0/lib/libffi.6.dylib (compatibility version 7.0.0, current version 7.1.0)
#executable_path/../Frameworks/GStreamer.framework/Versions/1.0/lib/libgmodule-2.0.0.dylib (compatibility version 4001.0.0, current version 4001.0.0)
#executable_path/../Frameworks/GStreamer.framework/Versions/1.0/lib/libglib-2.0.0.dylib (compatibility version 4001.0.0, current version 4001.0.0)
#executable_path/../Frameworks/GStreamer.framework/Versions/1.0/lib/libintl.8.dylib (compatibility version 10.0.0, current version 10.2.0)
#executable_path/../Frameworks/GStreamer.framework/Versions/1.0/lib/libiconv.2.dylib (compatibility version 8.0.0, current version 8.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 855.14.0)
Notice that first line where the .dylib references itself? That's doesn't change to #executable_path/../Frameworks/GStreamer.framework/ unless you invoke install_name_tool -id. And this happens with EVERY .dylib in the GStreamer framework! There are hundreds of them and I'm sure doing this manually is definitely going to cause errors.
Hopefully I've made my issue clear. Does anyone have any suggestions as to what to do?
Thanks!
I created a simple Xcode project to show you how to bundle the framework:
https://github.com/corrosion/gstreamer-osx-bundle.git
For library relocation use:
https://github.com/tito/osxrelocator
Setup to build a project with XCode:
Install gstreamer-1.0-1.5.2-x86_64.pkg
Install gstreamer-1.0-devel-1.5.2-x86_64.pkg
Move /Library/Frameworks/GStreamer.framework to $(PROJECT_DIR)/GStreamer-devel.framework
Go to the $(PROJECT_DIR) and run the following commands:
osxrelocator ./GStreamer-devel.framework/Versions/Current /Library/Frameworks/GStreamer.framework/pwd/GStreamer-devel.framework/
install_name_tool -id #executable_path/../Frameworks/GStreamer.framework/GStreamer ./GStreamer-devel.framework/Versions/Current/GStreamer
Add "$(PROJECT_DIR)/GStreamer-devel.framework/Headers" to Header Search Paths
Add "GStreamer-devel.framework/GStreamer" file to the Xcode project
Prepare the runtime framework:
Install gstreamer-1.0-1.5.2-x86_64.pkg
Move /Library/Frameworks/GStreamer.framework to $(PROJECT_DIR)/GStreamer.framework
Do some clean up of the framework:
rm ./GStreamer.framework/Headers ./GStreamer.framework/Commands
rm ./GStreamer.framework/Versions/Current/Commands
rm -r ./GStreamer.framework/Versions/Current/bin/
rm -r ./GStreamer.framework/Versions/Current/etc/
rm -r ./GStreamer.framework/Versions/Current/share/
Relocate the framework's .dylibs:
osxrelocator -r ./GStreamer.framework/Versions/Current /Library/Frameworks/GStreamer.framework/ #executable_path/../Frameworks/GStreamer.framework/
Since gst-plugin-scanner is executed during gst_init it also has to be able to find all libraries.
So create link to "Frameworks" in the libexec directory to resolve #executable_path/../Frameworks/GStreamer.framework/
ln -sf ../../../../ GStreamer.framework/Versions/Current/libexec/Frameworks
In the project's Build Phases settings create new Copy Files Phase and copy the GStreamer.framework to Fameworks
Set GST_PLUGIN_SCANNER and GST_PLUGIN_SYSTEM_PATH environment variables in code before calling gst_init():
// Setup GSTreamer environment
NSString *frameworksPath = [[NSBundle mainBundle] privateFrameworksPath];
NSString *scannerPath = [NSString stringWithFormat:#"%#/%s", frameworksPath,
"GStreamer.framework/Versions/1.0/libexec/gstreamer-1.0/gst-plugin-scanner"];
NSString *pluginsPath = [NSString stringWithFormat:#"%#/%s", frameworksPath,
"GStreamer.framework/Versions/1.0/lib"];
setenv("GST_PLUGIN_SCANNER", [scannerPath UTF8String], 1);
setenv("GST_PLUGIN_SYSTEM_PATH", [pluginsPath UTF8String], 1);
// Initialize GStreamer
gst_init(&argc, (char ***) &argv);

OSX 10.8 has libpng compatibility 27. Mavericks has 25. What is going on?

I am trying to compile an application on 10.8, and it binds to a libpng15.15 library that, according to otool, has compatibility version 27. The library is located in /opt/X11/lib
$ otool -L libpng15.15.dylib
libpng15.15.dylib:
/opt/X11/lib/libpng15.15.dylib (compatibility version 27.0.0, current version 27.0.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
Now, when I try to copy my executable to another mac and run it, I get a message that this mac libpng provides version 25.0.0, and thus can't run. The library is in /usr/X11/lib. This mac was a 10.6.8, it's not a developer machine, and was upgraded to 10.9 with the Apple Store download.
How is it possible that a 10.9 has a libpng compatibility version lower than 10.8?
Edit: I discovered that probably it's due to the fact that I need header files for the X11 libraries, so I installed XQuartz. However, XQuartz also upgrades the libraries with a higher compatibility version. This does not introduce any problem for the local system, but when I have to deploy on Mavericks it won't work, unless I install XQuartz there as well. Is there a better way to solve this problem, short of copying the header files manually?
If you have a symlink from /usr/X11 to /opt/X11, then you have most likely installed something using a third-party installer (brew or ports?) that has taken over your Apple-installed /usr/X11 location. Apple doesn't create, much less add anything into /opt, and it certainly doesn't put the X11 binaries or libraries there.
So, you are basically running 2 different environments on those machines, the 10.6.8 machine which has had system binaries overridden by a third-party installer, and a 10.9(.1?) machine which has not had these overridden.
Checking on existing, clean (i.e. no X11 ports installed), Apple developer tools installed versions of 10.9.1 and 10.6.8 that I'm currently running, I see the following:
10.6.8:
/usr/X11/lib/libpng12.0.dylib (compatibility version 47.0.0, current version 47.0.0)
/usr/X11/lib/libpng.3.dylib (compatibility version 50.0.0, current version 50.0.0)
10.9.1:
/usr/X11/lib/libpng12.0.dylib (compatibility version 48.0.0, current version 48.0.0)
/usr/X11/lib/libpng.3.dylib (compatibility version 51.0.0, current version 51.0.0)
/usr/X11/lib/libpng15.15.dylib (compatibility version 25.0.0, current version 25.0.0)
For thoroughness, I checked our clean installs of 10.7 and 10.8, which were both:
/usr/X11/lib/libpng12.0.dylib (compatibility version 47.0.0, current version 47.0.0)
/usr/X11/lib/libpng.3.dylib (compatibility version 50.0.0, current version 50.0.0)
/usr/X11/lib/libpng15.15.dylib (compatibility version 20.0.0, current version 20.0.0)
My suggestion would be to rebuild if you can on a machine which doesn't have /usr/X11 patched out, or (if that's not a possibility), consider the possibility of installing the same overrides on the target that have been done on the source.

I can't run Qt app on other mac

I make a simple Qt app on mac with Qt 5.1. I deploy it by using macdeployqt but when I run it on other mac.
I run otool -L with my app and It says
/Users/aratn0n/Qt//5.1.0/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets (compatibility version 5.1.0, current version 5.1.0)
/Users/aratn0n/Qt//5.1.0/clang_64/lib/QtGui.framework/Versions/5/QtGui (compatibility version 5.1.0, current version 5.1.0)
/Users/aratn0n/Qt//5.1.0/clang_64/lib/QtCore.framework/Versions/5/QtCore (compatibility version 5.1.0, current version 5.1.0)
/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
It seems it uses the library from my machine so when I run it on other machine it can't use the Qt library in the Frameworks folder within the app bundle.
How can I fix it?
I currently don't have a solution, but I ran into the same issue that you had when running macdeployqt. Based on another post, the reason why macdeployqt does not change the paths to local frameworks (#executable_path/../Frameworks/...) is because of the double slash in the paths of the Qt libraries. You need to manually run install_name_tool to correct the double slashes
install_name_tool -change /Users/<USERNAME>/Qt5.1.0//5.1.0/clang_64/lib/QtQuick.framework/Versions/5/QtQuick /Users/<USERNAME>/Qt5.1.0/5.1.0/clang_64/lib/QtQuick.framework/Versions/5/QtQuick <EXECUTABLE>
Sorry I can't help anymore, but this is as far as I've got to deploying my app on Mac OS X. Unfortunately for me, when I remove/rename my installed Qt library, my app no longer works because it can't find the libraries set up by macdeployqt.
if you intend to use qt as a dynamic library then you will have to distribute the dylib...
it is much simpler to use it as a static library. also you don't gain much from having a shared library if you aren't sharing it, so if you just have one process, build qt as a static lib and link it against your product, then there won't be a runtime dependency on an external lib.
It appears that macdeployqt hasn't done its job.
It should copy the required Qt libraries into the app bundle and set the paths for you.
Either look into why it's failing, or copy the files yourself and update the paths with install_name_tool
It's a bug in the installation of Qt that stops macdeployqt running properly in 5.1.0 as mentioned in the answer by user kimbaudi.
It has been fixed in 5.1.1.
If for some reason you must use 5.1.0 then run macdeployqt and you will find the Qt frameworks have been copied to the bundle.
You will then need to cd to the Frameworks directory in the bundle and rewrite the link path via commands of the form
install_name_tool -change /Users/username/Source/Qt5//5.1.0/clang_64/lib/QtGui.framework/Versions/5/QtGui #executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui QtCore
You'll need to do it for every Qt framework to rewrite the dependencies on each other and also all the dylibs in the PlugIns directory as well as the executable.

How to Install KDE Marble as a library on OSX?

I've been looking at using KDE's MarbleWidget in an application on OSX. However, the instructions located here: http://marble.kde.org/sources.php only seem to build marble.app and install it. I haven't been able to figure out how to get includes and libs installed under /usr/local.
Any ideas?
I can only give advice on Linux version, but I imagine it's similar.
The installation process should also create the library files which you can use in your own application. To copy them to the folder /usr/local, you can follow something like this:
http://code.google.com/p/tonatiuh/wiki/InstallingMarbleForLinux
Then you can follow the following to setup a basic application:
http://techbase.kde.org/Projects/Marble/MarbleCPlusPlus
Basically you have to locate the library files and copy & paste to correct directory. Hope that helps.
edit You should initially follow the cmake instructions at: http://techbase.kde.org/Projects/Marble/MacCompiling
You might need to modify CMakeLists.txt: make sure both lines that set CMAKE_OSX_ARCHITECTURES. I had to do this, anyway: setting this variable to something sensible for your OSX platform works too, but it seems like cmake is smart enough to guess the appropriate architecture by default. And passing -DCMAKE_OSX_ARCHITECTURES on the command line didn't seem to work.
Then run make, make install.
There are instructions here on which files need to be copied where:
https://code.google.com/p/tonatiuh/wiki/InstallingMarbleForMac
You'll need to do a few things after that. The file libmarblewidget.15.dylib (which you'll have copied to /usr/local/lib/marble) needs to be fixed so that it knows where it is. The Qt page on deploying applications for OSX (http://qt-project.org/doc/qt-4.8/deployment-mac.html) has a more extensive guide on how to do this, but basically you just have to use install_name_tool to tell the library where it now lives. If you use otool to check its status, you'll get something like:
kagutsuchi$ otool -L /usr/local/lib/libmarblewidget.15.dylib
/usr/local/lib/marble/libmarblewidget.15.dylib:
/marble/build/dir/src/lib/marble/libmarblewidget.15.dylib (compatibility version 15.0.0, current version 0.15.0)
/Developer/QtSDK/Desktop/Qt/4.8.0/gcc/lib/QtCore.framework/Versions/4/QtCore (compatibility version 4.8.0, current version 4.8.0)
/Developer/QtSDK/Desktop/Qt/4.8.0/gcc/lib/QtDBus.framework/Versions/4/QtDBus (compatibility version 4.8.0, current version 4.8.0)
/Developer/QtSDK/Desktop/Qt/4.8.0/gcc/lib/QtGui.framework/Versions/4/QtGui (compatibility version 4.8.0, current version 4.8.0)
/Developer/QtSDK/Desktop/Qt/4.8.0/gcc/lib/QtXml.framework/Versions/4/QtXml (compatibility version 4.8.0, current version 4.8.0)
/Developer/QtSDK/Desktop/Qt/4.8.0/gcc/lib/QtSvg.framework/Versions/4/QtSvg (compatibility version 4.8.0, current version 4.8.0)
/Developer/QtSDK/Desktop/Qt/4.8.0/gcc/lib/QtNetwork.framework/Versions/4/QtNetwork (compatibility version 4.8.0, current version 4.8.0)
/Developer/QtSDK/Desktop/Qt/4.8.0/gcc/lib/QtScript.framework/Versions/4/QtScript (compatibility version 4.8.0, current version 4.8.0)
/Developer/QtSDK/Desktop/Qt/4.8.0/gcc/lib/QtWebKit.framework/Versions/4/QtWebKit (compatibility version 4.8.0, current version 4.8.0)
/Developer/QtSDK/Desktop/Qt/4.8.0/gcc/lib/QtDeclarative.framework/Versions/4/QtDeclarative (compatibility version 4.8.0, current version 4.8.0)
/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices (compatibility version 1.0.0, current version 41.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 52.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 635.15.0)
The second line (/marble/build/dir/src/lib/marble/libmarblewidget.15.dylib ...) is a problem, because this isn't the current location of the library. You can change it with:
kagutsuchi$ sudo install_name_tool -id /usr/local/lib/marble/libmarblewidget.15.dylib /usr/local/lib/marble/libmarblewidget.15.dylib
The argument after -id is the new identifier. The next argument is the file you're modifying, so you could also do:
kagutsuchi$ cd /usr/local/lib/marble
kagutsuchi$ sudo install_name_tool -id /usr/local/lib/marble/libmarblewidget.15.dylib libmarblewidget.15.dylib
You'll also need to modify the plugins once you've copied them over to /usr/local/bin/marble so that they know where to look for libmarblewidget.15.dylib, again with install_name_tool:
kagutsuchi$ cd /usr/local/lib/marble
kagutsuchi$ for sofile in `ls *.so`; do sudo install_name_tool -change /marble/build/dir/src/marble/build/src/lib/libmarblewidget.15.dylib /usr/local/lib/marble/libmarblewidget.15.dylib $sofile; done
You should be able to use the same value for /marble/build/dir that worked for fixing libmarblewidget.15.dylib.
This should all work. If you check these files with otool -L they should now be looking in the right place for the library. You should also be able to get your Qt code to compile, providing you've got the right INCLUDEPATH and LIBS stuff in your .pro file.
HOWEVER... I'm stuck at this point. I've got my code to compile, but when I try to get it to run the MarbleWidget I create isn't looking in the right place for the plugins. I'm going to post a question on the plugin subject and see if I can get some help.

Resources