using sip-wheel on MacOS

Phil Thompson phil at riverbankcomputing.com
Wed Apr 29 09:02:27 BST 2020


On 29/04/2020 02:52, Steve Borho wrote:
>> On Apr 28, 2020, at 3:46 PM, Phil Thompson 
>> <phil at riverbankcomputing.com> wrote:
>> 
>> On 28/04/2020 18:49, Steve Borho wrote:
>>>> On Apr 28, 2020, at 3:58 AM, Phil Thompson 
>>>> <phil at riverbankcomputing.com> wrote:
>>>> On 28/04/2020 04:55, Steve Borho wrote:
>>>>> Hello,
>>>>> On Linux and Windows I can use sip-wheel to build binary wheels 
>>>>> that
>>>>> will gladly use the Qt libraries packaged by PyQt5, by compiling
>>>>> against the same local version of Qt.
>>>>> But when I try this on Mac, it is linking in the full paths to the
>>>>> local (homebrew) Qt libraries
>>>>> $ otool -L foo.cpython-37m-darwin.so
>>>>> foo.cpython-37m-darwin.so:
>>>>> 	/usr/local/opt/qt/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport
>>>>> (compatibility version 5.14.0, current version 5.14.1)
>>>>> 	/usr/local/opt/qt/lib/QtOpenGL.framework/Versions/5/QtOpenGL
>>>>> (compatibility version 5.14.0, current version 5.14.1)
>>>>> 	/usr/local/opt/qt/lib/QtWidgets.framework/Versions/5/QtWidgets
>>>>> (compatibility version 5.14.0, current version 5.14.1)
>>>>> 	/usr/local/opt/qt/lib/QtDataVisualization.framework/Versions/5/QtDataVisualization
>>>>> (compatibility version 5.14.0, current version 5.14.1)
>>>>> 	/usr/local/opt/qt/lib/QtGui.framework/Versions/5/QtGui 
>>>>> (compatibility
>>>>> version 5.14.0, current version 5.14.1)
>>>>> I see that sip-wheel has an option for:
>>>>> --target-qt-dir DIR   the Qt libraries will be found in DIR when 
>>>>> the wheel
>>>>>                       is installed
>>>>> but it is not clear how to target the PyQt5 packaged Qt libraries.
>>>>> Has anyone else tackled this?  Thanks
>>>> Assuming you are going to package a Qt installation with your wheel 
>>>> using pyqt-bundle at a later stage then pass '--target-qt-dir 
>>>> Qt/lib'.
>>>> This will be documented in the next release of the PyQt docs.
>>> Ideally the binaries in the wheel would use the Qt libraries in
>>> ../PyQt5/Qt/lib/* from site-packages.
>>> Does my app need to package its own copy of the Qt libraries if it
>>> compiles its own shared library?
>>> I just realized my Linux wheels have the same issue.  They are not
>>> using PyQt5/Qt/lib, they are relying on the Qt libraries being 
>>> present
>>> where they were compiled.
>> 
>> I'm not sure what it is you are trying to achieve. The wheels on PyPI 
>> are created by running sip-wheel using the --target-qt-dir. The wheel 
>> is compiled against a local Qt installation but targeted for a bundled 
>> copy of Qt. That wheel, if installed, would not run. pyqt-bundle is 
>> then run to bundle a copy of that local Qt installation to create a 
>> new wheel (the one uploaded to PyPI).
> 
> I have a PyQt application which implements some plotters in C++ and we
> compile these into a shared library that links against several Qt
> libraries. sip creates the Python bindings for it
> 
> When the application is installed as a wheel, ideally the plotter
> shared library would link with the same Qt libraries that PyQt5 is
> using, under site-packages/PyQt5/Qt/lib.
> 
> Any Qt libraries I package with my application could possibly be
> incompatible with those that PyQt5 was compiled against and shipped
> with.  Is it typical for apps that use both PyQt5 from Python and the
> link to native Qt libraries to just ship the whole shebang (app + qt +
> pyqt) in one wheel?  I’m curious how this is generally solved.

If you are relying on the PyQt5 wheels from PyPI then obviously you need 
to build against a compatible version of Qt. If you are using Qt 
libraries that are not bundled with the PyQt5 wheels then you will need 
to bundle them yourself in your own wheels.

> I actually have this almost working by adding this bit of shenanigans
> to the main.py script:
> 
> import os
> # relaunch the executable with site-packages/PyQt5/Qt/lib in library 
> path
> if 'APP_LIBPATH_HACK' not in os.environ:
>     sitepackages = os.path.dirname(os.path.dirname(__file__))
>     import sys
>     if sys.platform in ('linux', 'darwin'):
>         pyqt5 = os.path.join(sitepackages, 'PyQt5', 'Qt', 'lib')
>     else:
>         pyqt5 = os.path.join(sitepackages, 'PyQt5', 'Qt', 'bin')
>     if os.path.isdir(pyqt5):
>         if sys.platform == 'linux':
>             os.environ['LD_LIBRARY_PATH'] = pyqt5
>         elif sys.platform == 'darwin':
>             os.environ['DYLD_FRAMEWORK_PATH'] = pyqt5
>         else:
>             os.environ['PATH'] = os.pathsep.join((pyqt5, 
> os.environ['PATH']))
>         os.environ['APP_LIBPATH_HACK'] = '1'
>         os.execv(sys.argv[0], sys.argv)
> 
> It feels dirty, and doesn’t quite work because our plotter is linking
> against QtDataVisualization and this Qt library is not packaged with
> PyQt5, I presume because there are no Python bindings for it yet.  Is
> support for QtDataVisualization on the roadmap?

PyQtDataVisualization was first released in March 2014.

Phil


More information about the PyQt mailing list