Am Freitag, 3. Juli 2009 schrieb Giovanni Bajo:
> On 7/3/2009 3:42 PM, Hans-Peter Jansen wrote:
> > Hi Giovanni,
> >
> > $ python tools/pyinstaller/bindepend.py dist/CReport/PyQt4.QtCore.so
> > dist/CReport/PyQt4.QtCore.so
> > ['/Library/Frameworks/QtCore.framework/Versions/4/QtCore',
> > '/usr/lib/libz.1.dylib', '/usr/lib/libSystem.B.dylib',
> > '/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Ap
> >plicationServices', '/usr/lib/libstdc++.6.dylib',
> > '/usr/lib/libgcc_s.1.dylib']
>
> OK, this requires some Mac Guru to tell us how dyld resolves the
> dependencies at runtime. I thought otool -L always output absolute
> paths, but if that's not the case, how are we supposed to find out the
> absolute paths?
>
> I don't have a Mac right now. Maybe someone can chime in?

As you know, I'm in no way a Mac Guru, but I'am able to read man pages, 
which ought to be sufficient in this case:

       DYLD_FRAMEWORK_PATH
              This is a colon separated list of directories that contain  
frameworks.
              The  dynamic  linker  searches these directories before it 
searches for
              the framework by its install name.  It allows you to test new  
versions
              of  existing  frameworks.  (A  framework is a library install 
name that
              ends in the form XXX.framework/Versions/YYY/XXX  or  
XXX.framework/XXX,
              where XXX and YYY are any name.)

              For  each  framework  that a program uses, the dynamic linker 
looks for
              the framework in each directory in DYLD_FRAMEWORK_PATH in turn.  
If  it
              looks  in all the directories and can't find the framework, it 
searches
              the directories in DYLD_LIBRARY_PATH in turn. If it  still  can't 
 find
              the   framework,  it  then  searches  
DYLD_FALLBACK_FRAMEWORK_PATH  and
              DYLD_FALLBACK_LIBRARY_PATH in turn.

              Use the -L option to otool(1).  to discover the frameworks  and  
shared
              libraries that the executable is linked against.

       DYLD_FALLBACK_FRAMEWORK_PATH
              This  is a colon separated list of directories that contain 
frameworks.
              It is used as the default location for frameworks not  found  in  
their
              install path.

              By  default,  it  is set to 
/Library/Frameworks:/Network/Library/Frame-
              works:/System/Library/Frameworks

Given that info, and leaving DYLD_LIBRARY_PATH, DYLD_FALLBACK_LIBRARY_PATH 
and DYLD_ROOT_PATH alone, it boils down to this patch:

Index: bindepend.py
===================================================================
--- bindepend.py        (Revision 59)
+++ bindepend.py        (Arbeitskopie)
@@ -354,6 +354,12 @@
     """Find the binary dependencies of PTH.
 
         This implementation is for otool platforms"""
+    # dyld searches these paths for framework libs
+    # we ignore DYLD_FALLBACK_LIBRARY_PATH for now (man dyld)
+    fwpaths = ['/Library/Frameworks', '/Network/Library/Frameworks', 
'/System/Library/Frameworks']
+    for p in reversed(os.environ.get('DYLD_FRAMEWORK_PATH', '').split(':')):
+        if p:
+            fwpaths.insert(0, p)
     rslt = []
     for line in os.popen('otool -L "%s"' % pth).readlines():
         m = re.search(r"\s+(.*?)\s+\(.*\)", line)
@@ -363,6 +369,13 @@
                 rel_path = lib.replace("@executable_path",".")
                 rel_path = os.path.join(os.path.dirname(pth), rel_path)
                 lib = os.path.abspath(rel_path)
+            elif not os.path.isabs(lib):
+                # lookup matching framework path, if relative pathname
+                for p in fwpaths:
+                    fwlib = os.path.join(p, lib)
+                    if os.path.exists(fwlib):
+                        lib = fwlib
+                        break
             if os.path.exists(lib):
                 rslt.append(lib)
             else:


For your convenience, it's also attached.

>
> In one-dir mode, I *believe* that workpath is empty (I'm not sure I
> fully understand the code in there). Try putting some debug messages in
> there to debug.
>
> Anyway, to test if it's the right approach, it is of course sufficient
> to manually set DYLD_LIBRARY_PATH:
>
>   $ DYLD_LIBRARY_PATH=`pwd` ./myapp
>
> If this works, at least we know that we don't need to play any
> install_name_tool game.

I'm pretty confident, taht it will, given that all this is documented:

       DYLD_LIBRARY_PATH
              This is a colon separated list of directories that  contain  
libraries.
              The  dynamic  linker  searches these directories before it 
searches the
              default locations for libraries. It allows you to test new 
versions  of
              existing libraries.

              For  each  library that a program uses, the dynamic linker looks 
for it
              in each directory in DYLD_LIBRARY_PATH in turn. If it still can't 
 find
              the   library,   it   then  searches  
DYLD_FALLBACK_FRAMEWORK_PATH  and
              DYLD_FALLBACK_LIBRARY_PATH in turn.

              Use the -L option to otool(1).  to discover the frameworks  and  
shared
              libraries that the executable is linked against.


> >>> I think, this deserves a mac related option (one may don't want to
> >>> ship Qt), but by default the libs should be included. Using
> >>> qt4_plugins may deserve another option, since they need the same
> >>> treatment as above, and on that way pull nearly the full distribution
> >>> into the bundle.
> >>
> >> This is a totally different topic, as PyInstaller treats qt4_plugins
> >> mostly as data files.

That's the culprit!

> >> We'll have to find out why hook-PyQt4.Qt*.py 
> >> don't find the Qt4 plugins directory.
> >
> > It looks like QT_PLUGIN_PATH is set correctly, and they also appear
> > altogether, but those plugins bind with nearly all Qt libs in
> > existence, and this dependancy is not handled correctly, yet.
>
> This should be fixed wherever we fix the PyQt <-> Qt dependency, that is
> with DYLD_LIBRARY_PATH (hopefully).

Of course it won't, since you _still_ cannot fix a _missing_ library with
playing environmental games ;-) The PyQt <-> Qt dependency is resolved with 
the attached patch.
 
You will notice, when this starts to work, because the size of your app
will grow considerably (as long as your app doesn't use QtNetwork, QtSql, 
QtXml, QtSvg, or Qt3Support, yet). They all get pulled with the full 
qt4_plugins support (see my list), but as you said before, they're handled 
as data files ATM, which is the root of the problem. 

Pete

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"PyInstaller" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/PyInstaller?hl=en
-~----------~----~----~----~------~----~------~--~---

Index: bindepend.py
===================================================================
--- bindepend.py	(Revision 59)
+++ bindepend.py	(Arbeitskopie)
@@ -354,6 +354,12 @@
     """Find the binary dependencies of PTH.
 
         This implementation is for otool platforms"""
+    # dyld searches these paths for framework libs
+    # we ignore DYLD_FALLBACK_LIBRARY_PATH for now (man dyld)
+    fwpaths = ['/Library/Frameworks', '/Network/Library/Frameworks', '/System/Library/Frameworks']
+    for p in reversed(os.environ.get('DYLD_FRAMEWORK_PATH', '').split(':')):
+        if p:
+            fwpaths.insert(0, p)
     rslt = []
     for line in os.popen('otool -L "%s"' % pth).readlines():
         m = re.search(r"\s+(.*?)\s+\(.*\)", line)
@@ -363,6 +369,13 @@
                 rel_path = lib.replace("@executable_path",".")
                 rel_path = os.path.join(os.path.dirname(pth), rel_path)
                 lib = os.path.abspath(rel_path)
+            elif not os.path.isabs(lib):
+                # lookup matching framework path, if relative pathname
+                for p in fwpaths:
+                    fwlib = os.path.join(p, lib)
+                    if os.path.exists(fwlib):
+                        lib = fwlib
+                        break
             if os.path.exists(lib):
                 rslt.append(lib)
             else:

Reply via email to