changeset 3214:0e32c67b78ca

[Darwin] Python script for fixing "dyld: Library not loaded" errors
author Anirudha Bose <ani07nov@gmail.com>
date Sat, 21 Sep 2013 16:28:11 +0530
parents a4692f0e6932
children d1fb703f2cd0
files darwin_files/standalone.py
diffstat 1 files changed, 62 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/darwin_files/standalone.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+##
+## This Python script can be used to rewrite dylib references in Mach-O headers
+## and resolve the dynamic shared library install names which originally point
+## to the libraries in MXE $(HOST_LIBDIR).
+##
+## Requirements:
+## * Python 2.7
+## * Macholib (pip install http://pypi.python.org/pypi/macholib)
+##
+## Usage:
+## * python -mmacholib find [path to Resources directory of .app] | python standalone.py
+##
+## Example:
+## * python -mmacholib find ./Octave-3.7.5.app/Contents/Resources/ | python standalone.py
+##
+## Important Notes:
+## * Octave should be compiled with the option -headerpad_max_install_names in the LDFLAGS.
+## * The script must be executed as root, if Octave was compiled with root permissions.
+## * Before applying this script, make sure the bin and lib directory is present inside the
+##   Resources folder.
+## * Shared libraries like libcholmod.so, libumfpack.so, and others which end with .so
+##   extension are not assigned any path in the Mach-O headers during compilation. This is
+##   likely to happen while using MXE. This script can fix such errors too, but make sure
+##   you do not use this script on the same App Bundle more than once.
+
+__author__ = "Anirudha Bose"
+__email__ = "ani07nov@gmail.com"
+
+from __future__ import print_function
+
+import os
+import sys
+
+from macholib.MachO import MachO
+
+def dylibs_fix(path):
+    print(path)
+    m = MachO(path)
+    for header in m.headers:
+        seen = set()
+        for idx, name, other in header.walkRelocatables():
+            if other not in seen:
+                seen.add(other)
+                relative_name = other[other.find("lib"):]
+                if other.startswith("/Users"):
+                        command = 'install_name_tool -change "%s" "@executable_path/../%s" ./%s\n'%(other,relative_name,path)
+                        print(command)
+                        os.system(command)
+                elif other.endswith(".so"):
+                        command = 'install_name_tool -change "%s" "@executable_path/../lib/%s" ./%s\n'%(other,other,path)
+                        print(command)
+                        os.system(command)
+def main():
+        for path in sys.stdin:
+                dylibs_fix(path)
+
+if __name__ == '__main__':
+    try:
+        sys.exit(main())
+    except KeyboardInterrupt:
+        pass