Using otool (recursively) to find the shared libraries needed by the application

I have a Cocoa application that uses otool to find the necessary shared libraries that the application needs to function properly. For example, let's say I ran otool -L in an application that uses QTKit.framework. I get a list of shared libraries used by the program (including the main frameworks such as Cocoa.framework and AppKit.framework):

/System/Library/Frameworks/QTKit.framework/Versions/A/QTKit (compatibility version 1.0.0, current version 1.0.0) /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 476.0.0) /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 949.0.0) ..... and so on for a bunch of other frameworks 

Which shows that the application uses QTKit.framework. However, if I use otool -L again in the binary for QTKit.framework (/System/Library/Frameworks/QTKit.framework/Versions/A/QTKit), I get the following:

 /System/Library/Frameworks/QTKit.framework/Versions/A/QTKit (compatibility version 1.0.0, current version 1.0.0) /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox (compatibility version 1.0.0, current version 1.0.0) /System/Library/PrivateFrameworks/CoreMedia.framework/Versions/A/CoreMedia (compatibility version 1.0.0, current version 1.0.0) /System/Library/PrivateFrameworks/MediaToolbox.framework/Versions/A/MediaToolbox (compatibility version 1.0.0, current version 1.0.0) /System/Library/PrivateFrameworks/VideoToolbox.framework/Versions/A/VideoToolbox (compatibility version 1.0.0, current version 1.0.0) /System/Library/PrivateFrameworks/CoreMediaIOServices.framework/Versions/A/CoreMediaIOServices (compatibility version 1.0.0, current version 1.0.0) /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 751.0.0) /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1038.0.0) /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0) /System/Library/Frameworks/QuickTime.framework/Versions/A/QuickTime (compatibility version 1.0.0, current version 1584.0.0) /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio (compatibility version 1.0.0, current version 1.0.0) /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0) /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore (compatibility version 1.2.0, current version 1.6.0) /System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface (compatibility version 1.0.0, current version 1.0.0) /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox (compatibility version 1.0.0, current version 435.0.0) /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 123.0.0) /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0) /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices (compatibility version 1.0.0, current version 44.0.0) /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 550.0.0) /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices (compatibility version 1.0.0, current version 38.0.0) /System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo (compatibility version 1.2.0, current version 1.6.0) 

This shows the loading of additional frameworks that were shown by the initial otool output in the application binary. Is there a way to make otool work recursively, that is, it grabs the frameworks needed for the application, then comes in and looks for each of these frameworks for dependencies?

+4
source share
1 answer

No, you will have to run otool many times or include its syntax code ( here ). Don't forget about managing @executable_path .

Here it is in Python (without @executable_path , canonicalization, or filenames-with-spaces), as this was easier than trying to debug the pseudo-code:

 import subprocess def otool(s): o = subprocess.Popen(['/usr/bin/otool', '-L', s], stdout=subprocess.PIPE) for l in o.stdout: if l[0] == '\t': yield l.split(' ', 1)[0][1:] need = set(['/Applications/iTunes.app/Contents/MacOS/iTunes']) done = set() while need: needed = set(need) need = set() for f in needed: need.update(otool(f)) done.update(needed) need.difference_update(done) for f in sorted(done): print f 
+8
source

All Articles