Git Product home page Git Product logo

macdeployqtfix's Introduction

macdeployqtfix

To bundle a Mac OSX application dynamically linked with Qt, there is macdeployqt.
To finish the job there is macdeployqtfix...

What does 'Finish the job' mean?

  • Find dependencies and rpaths of :
    • the main binary of the bundle (i.e your app)
    • the dependencies of your app, and their dependencies, and their... (you got it!)
    • the plugins present in the bundle
  • Copy into the bundle the missing QT libs on which your app depends, that should normally have been taken care of by macdeployqt
  • Fix incorrect permissions
  • Fix incorrect rpaths

Prerequisites

macdeployqtfix relies on otool and install_name_tool being on the PATH

Usage

โ— Use macdeployqt first, then call macdeployqtfix

$ python macdeployqtfix.py -h
usage: macdeployqtfix.py [-h] [-q] [-nl] [-v] exepath qtpath

finish the job started by macdeployqt!
 - find dependencies/rpaths  with otool
 - copy missed dependencies  with cp and mkdir
 - fix missed rpaths         with install_name_tool

 exit codes:
 - 0 : success
 - 1 : error
 

positional arguments:
  exepath             path to the binary depending on Qt
  qtpath              path of Qt libraries used to build the Qt application

optional arguments:
  -h, --help          show this help message and exit
  -q, --quiet         do not create log on standard output
  -nl, --no-log-file  do not create log file './macdeployqtfix.log'
  -v, --verbose       produce more log messages(debug log)

Example usage

Let's say that:

  • your Qt application is named APP
  • the bundle is located at /path/to/bundle/
  • the path to those Qt libs used to build your app is /usr/local/Cellar/qt5/5.5.0/
  1. Run macdeployqt first, as they say in the doc
  2. Finish the job by calling:
python macdeployqtfix.py /path/to/bundle/Contents/MacOS/APP /usr/local/Cellar/qt5/5.5.0/

macdeployqtfix's People

Contributors

arl avatar iltommi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

macdeployqtfix's Issues

Detect Qt5 prefix automatically with homebrew

Recommendation to use $(brew --prefix qt5)/bin/qmake -query QT_INSTALL_PREFIX to detect a sane default for qtpath so that automated build systems can use whichever qt version is available to the system.

Pardon my lack of python knowledge, the proof of concept is provided in shell script format.

#!/bin/bash

# wtfpl license

# If "qtpath" is already set internally, use the prefix provided
if [ -z "$qtpath" ]; then
   which brew > /dev/null 2>&1
   if [ $? -eq 0 ]; then
      # Homebrew is installed, the Qt "bin" prefix needs to be calculated first
      which qmake > /dev/null 2>&1
      if [ $? -ne 0 ]; then
          # Add Qt "bin" to the search path, so we can call "qmake -query"
          export PATH=PATH:$(brew --prefix qt5)/bin
      fi
   fi
   qtpath="$(qmake -query QT_INSTALL_PREFIX)/"
   echo $qtpath
fi

Sample output:

/usr/local/Cellar/qt5/5.6.1/

Add test/continuous integration

It would be quite simple to prepare a travis script that builds a Qt application, then checks that macdeployqtfix does its job.

Best thing would be to trigger the macdeployqt problem with a minimal qt command line app, so as to be able to check that it doesn't run, due to missing deps, after the macdeployqt step, but runs correctly, after the macdeployqtfix step.

Does not copy PlugIns

Hi,

first of all thank you for this nifty script. One problem I have, though. It does not copy the PlugIns/platforms libs. And get this error:

This application failed to start because it could not find or load the Qt platform plugin "cocoa".
Reinstalling the application may fix this problem. The program has unexpectedly finished.

problem with python and homebrew

HI,
thanks for your code, it saved my life!
I stll have something weird happening with my code.

The code (https://github.com/aflux/neutrino/) links on libPythonQt (http://pythonqt.sourceforge.net/) which links on Python.
I installed homebrew and compiled pythonqt by hand
Then I compile my code and run both macdeployqt and macdeployqtfix.py and everything is fine except the Python framework linked by pythonqt
As you can see the dependencies of both Pythonqt libs are still pointing to /usr/local/Frameworks (although Python Frameworks get copied in my .app)
It should be macdeployqt job to fix this, but it seems it has a lot of problems....

I ended up fixing this with install_name_tool, but I was wondering if it was possible to add a hook to your script to fix this issue too.

many thanks!


These are the dependencies of Pytohnqt:

otool -L lib/libPythonQt.dylib 
lib/libPythonQt.dylib:
    libPythonQt.1.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/local/Frameworks/Python.framework/Versions/2.7/Python (compatibility version 2.7.0, current version 2.7.0)
    /usr/local/opt/qt5/lib/QtWidgets.framework/Versions/5/QtWidgets (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtGui.framework/Versions/5/QtGui (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtCore.framework/Versions/5/QtCore (compatibility version 5.5.0, current version 5.5.0)
    /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration (compatibility version 1.0.0, current version 1.0.0)
    /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.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 104.1.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

otool -L lib/libPythonQt_QtAll.dylib 
lib/libPythonQt_QtAll.dylib:
    libPythonQt_QtAll.1.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/local/Frameworks/Python.framework/Versions/2.7/Python (compatibility version 2.7.0, current version 2.7.0)
    libPythonQt.1.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/local/opt/qt5/lib/QtWebKitWidgets.framework/Versions/5/QtWebKitWidgets (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtWidgets.framework/Versions/5/QtWidgets (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtGui.framework/Versions/5/QtGui (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtCore.framework/Versions/5/QtCore (compatibility version 5.5.0, current version 5.5.0)
    /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration (compatibility version 1.0.0, current version 1.0.0)
    /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
    /usr/local/opt/qt5/lib/QtWebKit.framework/Versions/5/QtWebKit (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtNetwork.framework/Versions/5/QtNetwork (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtSvg.framework/Versions/5/QtSvg (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtOpenGL.framework/Versions/5/QtOpenGL (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtMultimediaWidgets.framework/Versions/5/QtMultimediaWidgets (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtMultimedia.framework/Versions/5/QtMultimedia (compatibility version 5.5.0, current version 5.5.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/local/opt/qt5/lib/QtXmlPatterns.framework/Versions/5/QtXmlPatterns (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtSql.framework/Versions/5/QtSql (compatibility version 5.5.0, current version 5.5.0)
    /usr/local/opt/qt5/lib/QtXml.framework/Versions/5/QtXml (compatibility version 5.5.0, current version 5.5.0)
    /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 104.1.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

Thanks a lot!

Thanks a lot for this great tool that makes it possible for me to use macdeployqt on current versions of Qt with brew on Travis CI for https://github.com/pbek/QOwnNotes!

And a big thank you to @iltommi for fixing the problems with brew!

This was bugging me for ages in QOwnNotes! macdeployqt is still broken in Qt 5.8, but the app works like a charm after running macdeployqtfix! (Qt 5.5.1 on brew was the last version where macdeployqt worked.)

Failed to run on travis

Hi,

I used to use your tool for generating my app bundle on travis-ci. But lately some changes did break our build with such errors from macdeployqtfix:

python macdeployqtfix.py build/$APP.app/Contents/MacOS/[secure] /usr/local/Cellar/qt5/5.*/

Traceback (most recent call last):

  File "macdeployqtfix.py", line 15, in <module>

    import ipdb

ImportError: No module named ipdb

Any idea on the cause of that?

Thanks

Nothing done for libraries [fixed]

Hi,

the dependencies that the tool mainly finds start like @rpath/QtWidgets.framework/Versions/5/QtWidgets

However, they are not recognized by the tool to be a lib, so nothing happens.

The tool will add all platform files etc., but no lib, which is why the app will not start afterwards with the crash message that the library QtWidgets could not be found. Any ideas?

Edit:
Okay, it seemed that there was some error in macdeployqt already which lied in differing versions of Xcode and install_name_tool. The latter comes from command line tools, which need to be exactly the same as the ones of Xcode. Command line tools can be found here: https://developer.apple.com/download

Then, macdeployqt will have fewer errors and macdeployqtfix can do its job. Thank you for this great tool!

Doesn't work on Python 3.12

The script seems to fail running on Python 3.12:

Traceback (most recent call last):
  File "/Users/runner/work/Mudlet/b/ninja/macdeployqtfix.py", line 394, in <module>
    main()
  File "/Users/runner/work/Mudlet/b/ninja/macdeployqtfix.py", line 384, in main
    if fix_main_binaries():
       ^^^^^^^^^^^^^^^^^^^
  File "/Users/runner/work/Mudlet/b/ninja/macdeployqtfix.py", line 322, in fix_main_binaries
    if fix_binary(GlobalConfig.exepath):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/runner/work/Mudlet/b/ninja/macdeployqtfix.py", line 306, in fix_binary
    for dep in get_dependencies(binary):
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/runner/work/Mudlet/b/ninja/macdeployqtfix.py", line 63, in get_dependencies
    deps = [s.strip().split(' ')[0] for s in proc_out.stdout.splitlines()[1:] if s]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/runner/work/Mudlet/b/ninja/macdeployqtfix.py", line 63, in <listcomp>
    deps = [s.strip().split(' ')[0] for s in proc_out.stdout.splitlines()[1:] if s]
            ^^^^^^^^^^^^^^^^^^^^
TypeError: a bytes-like object is required, not 'str'
Error: Process completed with exit code 1.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.