macos - cx_freeze - Esta aplicación no se pudo iniciar porque no pudo encontrar o cargar el complemento de la plataforma Qt "cacao"
pyinstaller (3)
Al crear una aplicación con cx_Freeze
en MacOSX, todas las bibliotecas dependientes (archivos .so
en MacOSX) se empaquetan en el paquete de aplicaciones. Esto es lo que hace que la aplicación sea portátil para otros sistemas, sin requerir una segunda instalación de Qt.
Al iniciar la aplicación, las bibliotecas, por lo tanto, deben cargarse desde el paquete. Sin embargo, en su caso las bibliotecas del sistema todavía se están cargando:
/Users/.../build/coublet-0.5.70.app/Contents/MacOS/QtWidgets
/usr/local/Cellar/qt5/5.3.1/lib/QtWidgets.framework/Versions/5/QtWidgets
El resultado One of the two will be used. Which one is undefined.
One of the two will be used. Which one is undefined.
significa que cualquiera de estos podría ser cargado. Si elige el correcto, ¡genial! Si no lo hace, tiene dos conjuntos separados de bibliotecas cargando simultáneamente, y eso falla poco después. Como comentario adicional, puede encontrar que si prueba su Aplicación en otro sistema ¡funcionará bien! A veces
Para una visión general del problema, sugiero echar un vistazo al siguiente error # 33 .
Antes de que empieces
Asegúrese de cx_Freeze instalada una versión actualizada de cx_Freeze . Sugiero intentar clonar el repositorio e instalar desde allí.
En segundo lugar, asegúrese de que los complementos de Qt estén integrados correctamente en su aplicación. Cx_Freeze previamente buscó el archivo qt-menu.nib
para determinar si estaba construyendo una aplicación Qt. Esto ya no está disponible en Qt5, pero puedes pasarlo en la línea de comandos cuando crees tu aplicación. Establézcalo como lo desee, realmente no importa:
python setup.py bdist_mac --qt-menu-nib=/usr/local/Cellar/qt5/5.3.1/plugins/platforms/
Esto puede ser suficiente para solucionar su problema. Pero si no, tienes dos opciones:
Opción 1
Cada archivo de biblioteca contiene las rutas a sus dependencias. Si recibe este error, significa que algunas de esas rutas son a) siguen apuntando al archivo original, ob) no son lo suficientemente específicas (y se encuentran en su PATH
o DYLD_LIBRARY_PATH
). Sin embargo, puede volver a escribir rutas usando install_name_tool
desde la línea de comandos (como se describe here :
install_name_tool -change /usr/local/Cellar/qt5/5.3.1/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/QtWidgets build/MyApp.app/Contents/MacOS/qt_plugins/platforms/libqcocoa.dylib
install_name_tool -change /usr/local/Cellar/qt5/5.3.1/lib/QtCore.framework/Versions/5/QtCore @executable_path/QtCore build/MyApp.app/Contents/MacOS/qt_plugins/platforms/libqcocoa.dylib
install_name_tool -change /usr/local/Cellar/qt5/5.3.1/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport @executable_path/QtPrintSupport build/MyApp.app/Contents/MacOS/qt_plugins/platforms/libqcocoa.dylib
install_name_tool -change /usr/local/Cellar/qt5/5.3.1/lib/QtGui.framework/Versions/5/QtGui @executable_path/QtGui build/MyApp.app/Contents/MacOS/qt_plugins/platforms/libqcocoa.dylib
Esto reescribe las rutas en las bibliotecas para apuntar a la carpeta de la aplicación, usando @executable_path
como base. Tendrá que hacer esto para todas las rutas que encuentre cargando incorrectamente. Sugiero incluirlo en un script para que se ejecute automáticamente después de la compilación.
Si desea ver a qué bibliotecas hace referencia un archivo, puede usar otool
. Por ejemplo, en una aplicación mía exitosamente construida:
otool -L libqcocoa.dylib
libqcocoa.dylib:
@executable_path/../Resources/qt_plugins/platforms/libqcocoa.dylib (compatibility version 0.0.0, current version 0.0.0)
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 20.0.0)
...
Hubo una solución alternativa en el rastreador de problemas que sugiere que solo importar el módulo correcto en su aplicación hará que funcione, sin embargo, parece poco probable que haya creado una aplicación sin QtWidgets
.
opcion 2
Si lo anterior no funciona, hay otro enfoque que se describe here . Este es un enfoque un poco machacante, ya que simplemente evita la carga de complementos.
Agregue un archivo
qt.conf
lado del ejecutable (en el paquete.app
que contiene:
[Paths] Plugins = ''.''
QT_PLUGIN_PATH=""
variable de entornoQT_PLUGIN_PATH=""
(puede hacer esto dentro de su aplicación antes de importarPyQt
. O llame aQtGui.QApplication.setLibraryPaths([])
antes de crear su objeto de aplicación.
El resultado es que no hay complementos, por lo que su aplicación no tendrá acceso al estilo MacOSX Cocoa y a la interfaz de usuario (por ejemplo, archivos, cuadros de diálogo de colores).
Creo que hice todo lo posible en las últimas 20 horas, pero nada parece funcionar. Mi aplicación se está ejecutando y funciona, como debería ser, el único problema que tengo es que no puedo crear un paquete .app
partir de él. Intenté Py2App
y cx_Freeze
pero cx_Freeze
funciona. Debido al soporte multiplataforma, me quedaría con este último, si es posible.
El setup.py
ve así:
import sys
from cx_Freeze import setup, Executable
base = None
if sys.platform == ''win32'':
base = ''Win32GUI''
OPTIONS = {''build_exe'': {''includes'': [''sip'',
''PyQt5'',
''PyQt5.QtCore'',
''PyQt5.QtGui'',
''PyQt5.QtWidgets'',
''PyQt5.QtMultimediaWidgets'',
''PyQt5.QtMultimedia'',
''PyQt5.QtNetwork'']}}
EXECUTABLES = [Executable(''main.py'', base=base)]
NAME = ''coublet''
VERSION = ''0.5.70''
setup(name = NAME,
version = VERSION,
options = OPTIONS,
executables = EXECUTABLES)
El mensaje de error que tengo es este:
objc[28404]: Class NotificationReceiver is implemented in both
/Users/.../build/coublet-0.5.70.app/Contents/MacOS/QtWidgets and
/usr/local/Cellar/qt5/5.3.1/lib/QtWidgets.framework/Versions/5/QtWidgets. One of
the two will be used. Which one is undefined.
QObject::moveToThread: Current thread (0x7fc4b96e98b0) is not the object''s thread
(0x7fc4b95dbc80).
Cannot move to target thread (0x7fc4b96e98b0)
On Mac OS X, you might be loading two sets of Qt binaries into the same process.
Check that all plugins are compiled against the right Qt binaries. Export
DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.
This application failed to start because it could not find or load the Qt
platform plugin "cocoa".
Available platform plugins are: cocoa, minimal, offscreen.
Reinstalling the application may fix this problem.
Abort trap: 6
Mi sistema de información:
Mac OS X : 10.9.4
Python : 3.4.1
cx_Freeze : 0.9
PyQt5: : 5.3.1
- - -
Packages installed via: Homebrew and PIP
Estructura de .app
:
build/coublet-0.5.70.app
└── Contents
├── Frameworks
├── Info.plist
├── MacOS
│ ├── PyQt5.QtCore.so
│ ├── PyQt5.QtGui.so
│ ├── PyQt5.QtMultimedia.so
│ ├── PyQt5.QtMultimediaWidgets.so
│ ├── PyQt5.QtNetwork.so
│ ├── PyQt5.QtWidgets.so
│ ├── Python
│ ├── QtCore
│ ├── QtCore.so
│ ├── QtGui
│ ├── QtGui.so
│ ├── QtMultimedia
│ ├── QtMultimedia.so
│ ├── QtMultimediaWidgets
│ ├── QtMultimediaWidgets.so
│ ├── QtNetwork
│ ├── QtNetwork.so
│ ├── QtOpenGL
│ ├── QtWidgets
│ ├── QtWidgets.so
│ ├── _bisect.so
│ ├── _bz2.so
│ ├── _codecs_cn.so
│ ├── _codecs_hk.so
│ ├── _codecs_iso2022.so
│ ├── _codecs_jp.so
│ ├── _codecs_kr.so
│ ├── _codecs_tw.so
│ ├── _datetime.so
│ ├── _hashlib.so
│ ├── _heapq.so
│ ├── _json.so
│ ├── _lzma.so
│ ├── _md5.so
│ ├── _multibytecodec.so
│ ├── _opcode.so
│ ├── _pickle.so
│ ├── _posixsubprocess.so
│ ├── _random.so
│ ├── _scproxy.so
│ ├── _sha1.so
│ ├── _sha256.so
│ ├── _sha512.so
│ ├── _socket.so
│ ├── _ssl.so
│ ├── _struct.so
│ ├── array.so
│ ├── binascii.so
│ ├── grp.so
│ ├── imageformats
│ │ ├── libqdds.dylib
│ │ ├── libqgif.dylib
│ │ ├── libqicns.dylib
│ │ ├── libqico.dylib
│ │ ├── libqjp2.dylib
│ │ ├── libqjpeg.dylib
│ │ ├── libqmng.dylib
│ │ ├── libqsvg.dylib
│ │ ├── libqtga.dylib
│ │ ├── libqtiff.dylib
│ │ ├── libqwbmp.dylib
│ │ └── libqwebp.dylib
│ ├── libcrypto.1.0.0.dylib
│ ├── liblzma.5.dylib
│ ├── library.zip
│ ├── libreadline.6.dylib
│ ├── libssl.1.0.0.dylib
│ ├── main
│ ├── math.so
│ ├── platforms
│ │ ├── libqcocoa.dylib
│ │ ├── libqminimal.dylib
│ │ └── libqoffscreen.dylib
│ ├── pyexpat.so
│ ├── readline.so
│ ├── select.so
│ ├── sip.so
│ ├── termios.so
│ ├── time.so
│ ├── unicodedata.so
│ └── zlib.so
└── Resources
La pregunta es, creo, bastante obvia: ¿qué estoy haciendo mal? (¿o qué no estoy haciendo?)
Esto es adicional a la respuesta de @ mfitzp.
Este documento QT Plugins fue útil.
Para buscar las ubicaciones predeterminadas que su aplicación QT está intentando buscar, puede usar el siguiente comando:
$sudo dtruss MacOS/ncher
getattrlist("/ncher.app/0", 0x7FFF954B51A4, 0x7FFF5C8FDD20) = 0 0
getattrlist("/ncher.app/Contents/0", 0x7FFF954B51A4, 0x7FFF5C8FDD20) = 0 0
getattrlist("/ncher.app/Contents/MacOS/0", 0x7FFF954B51A4, 0x7FFF5C8FDD20) = 0 0
stat64("/ncher.app/Contents/MacOS/0", 0x7FFF5C8FDED8, 0x7FFF5C8FDD20) = 0 0
stat64("/ncher.app/Contents/MacOS/platforms/./0", 0x7FFF5C8FDF58, 0x7FFF5C8FDD20) = -1 Err#2
open("/dev/tty/0", 0x1000000, 0x1FF) = 5 0
fcntl(0x5, 0x2, 0x1) = 0 0
close(0x5) = 0 0
write_nocancel(0x2, "This application failed to start because it could not find or load the Qt platform plugin /"cocoa/"./n/nReinstalling the application may fix this problem./n/0", 0x97) = 151 0
sigprocmask(0x3, 0x7FFF5C8FE6B4, 0x0) = 0x0 0
__pthread_sigmask(0x3, 0x7FFF5C8FE6C0, 0x0) = 0 0
__pthread_kill(0x603, 0x6, 0x0) = 0 0
kevent64(0x4, 0x0, 0x0) = -1 Err#4
Puedes ver esta aplicación QT tratando de buscar en MacOS/platforms
, una vez que copié mi plugin libqcocoa.dylib (su ruta fue modificada por el comando install_name_tool
según la respuesta de @mfitzp) allí, mi aplicación funcionó como "charm".
Por cierto, es aconsejable que la guía de código de MAC tenga esta estructura de directorios correctamente configurada,
NO ncher.app/Contents/MacOS
Frameworks, complementos en el directorio ncher.app/Contents/MacOS
Tuve este problema en el contexto de simplemente iniciar una aplicación Qt Widgets de Qt Creator.
Lo que me ayudó fue establecer la variable QT_PLUGIN_PATH
en el valor <Qt-dir>/plugins
(donde <Qt-dir>
es la ruta absoluta a la carpeta en el directorio Qt que contiene, entre otros, bin
, doc
, include
, lib
y por supuesto, plugins
).
Esto probablemente no solucionó la causa raíz del problema, pero fue una solución rápida que funciona bien hasta el momento.