full - qt para c++
Cómo copiar las DLL de tiempo de ejecución de Qt a la salida del proyecto (4)
Tengo un proyecto simple creado en Qt Creator (instalado usando Qt SDK 1.1.4). Funciona bien desde dentro de Qt Creator, pero si luego navego al directorio de salida en Windows y hago doble clic en el EXE, obtendré un error como:
The program can''t start because QtCored4.dll is missing from your computer.
Try reinstalling the program to fix this problem.
Eso es obviamente porque Qt no está en mi PATH (y no quiero que lo sea, en caso de que tenga múltiples versiones de Qt en mi computadora), y Qt Creator / qmake no copió las DLL de Qt en la salida del proyecto .
Lo que me gustaría hacer es usar qmake para copiar los archivos Qt necesarios en el directorio de salida del proyecto, donde sea que esté. ¿Cómo hago esto?
(Intenté crear un objetivo personalizado en qmake, pero no estoy llegando demasiado lejos ...)
ACTUALIZACIÓN, 19 de julio de 2016: solo para aclarar, la publicación anterior se refería a Qt4. En Qt5, en su lugar deberías buscar llamar a windeployqt
. Esta herramienta Qt5 leerá su archivo binario, determinará qué archivos de tiempo de ejecución de Qt5 necesita y los copiará en su directorio binario. También tenga en cuenta que fijará rutas absolutas en la biblioteca Qt5 :: Core que son específicas de su PC, por lo que el uso de esta herramienta es básicamente obligatorio a menos que desee proporcionar un archivo qt.conf
usted mismo.
Me encontré con el mismo problema y la solución de jwernerny me ayudó mucho. Sin embargo, estaba usando Shadow Build en Window 7 y necesitaba un poco más de tweeking.
También necesitaba configurar el DESTDIR
acuerdo con la configuración actual.
En mi caso, quería copiar los archivos *.qml
, así es como lo logré:
CONFIG(release, debug|release): DESTDIR = $$OUT_PWD/release
CONFIG(debug, debug|release): DESTDIR = $$OUT_PWD/debug
QmlFiles.path = $$DESTDIR/Qml
QmlFiles.files += $$files(Qml/*.qml)
INSTALLS += QmlFiles
EDITAR:
Como uso Shadow Build, necesito usar $$OUT_PWD
para obtener la carpeta de salida.
OK, aquí hay un truco feo:
# Copy required DLLs to output directory
CONFIG(debug, debug|release) {
QtCored4.commands = copy /Y %QTDIR%//bin//QtCored4.dll debug
QtCored4.target = debug/QtCored4.dll
QtGuid4.commands = copy /Y %QTDIR%//bin//QtGuid4.dll debug
QtGuid4.target = debug/QtGuid4.dll
QMAKE_EXTRA_TARGETS += QtCored4 QtGuid4
PRE_TARGETDEPS += debug/QtCored4.dll debug/QtGuid4.dll
} else:CONFIG(release, debug|release) {
QtCore4.commands = copy /Y %QTDIR%//bin//QtCore4.dll release
QtCore4.target = release/QtCore4.dll
QtGui4.commands = copy /Y %QTDIR%//bin//QtGui4.dll release
QtGui4.target = release/QtGui4.dll
QMAKE_EXTRA_TARGETS += QtCore4 QtGui4
PRE_TARGETDEPS += release/QtCore4.dll release/QtGui4.dll
} else {
error(Unknown set of dependencies.)
}
Aquí hay algo de lo que no me gusta de él:
- Utiliza la variable de entorno% QTDIR%; esta variable no se evalúa hasta que realmente se ejecuta el comando de copia. Parece que algo parecido a QMAKE_LIBS_QT_DLL sería más apropiado, pero no pude QMAKE_LIBS_QT_DLL por alguna razón.
- Nombres de "depuración" y "liberación" codificados; parece que debería haber algún tipo de variable para usar para eso.
- Llamar al medio ambiente mediante el uso del comando "copiar".
Aceptaré otra respuesta si alguien puede limpiar esto un poco, por ejemplo, al acortarlo y / o abordar algunas de mis preocupaciones, o simplemente encontrar una mejor manera en general.
Un método un poco más limpio, pero requerirá hacer una make install
después de una make
. Funcionará en Windows, pero necesitaría ajustes para otras plataformas.
debug { DESTDIR = debug }
release { DESTDIR = release }
debug_and_release { DESTDIR = bin }
myqtlibs.path = $$DESTDIR
myqtlibs.files = $$QMAKE_LIBDIR_QT/*.dll junk.txt fred.out
myqtlibs.CONFIG = no_check_exist
INSTALLS += myqtlibs
Si qmake se ejecuta solo para la depuración, todos los resultados entrarán en ./debug. Si es solo para lanzamiento, todos los resultados entran ./release. Si ambos, entonces en ./bin.
Me di cuenta de que habilitar la creación de sombras en QtCreator hacía que el ejecutable no terminara en el DESTDIR. No estoy muy seguro de por qué.
Copie dependencias con windeployqt
# Deployment - Automatically Detect and Copy Dependencies to Build Folder
TARGET_CUSTOM_EXT = .exe
DEPLOY_COMMAND = windeployqt
CONFIG( debug, debug|release ) {
# debug
DEPLOY_TARGET = $$shell_quote($$shell_path($${OUT_PWD}/debug/$${TARGET}$${TARGET_CUSTOM_EXT}))
} else {
# release
DEPLOY_TARGET = $$shell_quote($$shell_path($${OUT_PWD}/release/$${TARGET}$${TARGET_CUSTOM_EXT}))
}
# Uncomment the following line to help debug the deploy command when running qmake
#warning($${DEPLOY_COMMAND} $${DEPLOY_TARGET})
QMAKE_POST_LINK = $${DEPLOY_COMMAND} $${DEPLOY_TARGET}
o Copiar dependencias manualmente
# Deployment - Copy Dependencies to Build Folder
dlls.path = $${DESTDIR}
dlls.files += $$[QT_INSTALL_BINS]/icudt51.dll
dlls.files += $$[QT_INSTALL_BINS]/icuin51.dll
dlls.files += $$[QT_INSTALL_BINS]/icuuc51.dll
dlls.files += $$[QT_INSTALL_BINS]/libgcc_s_dw2-1.dll
dlls.files += $$[QT_INSTALL_BINS]/libstdc++-6.dll
dlls.files += $$[QT_INSTALL_BINS]/libwinpthread-1.dll
dlls.files += $$[QT_INSTALL_BINS]/Qt5Core.dll
dlls.files += $$[QT_INSTALL_BINS]/Qt5Network.dll
dlls.files += $$[QT_INSTALL_BINS]/Qt5Gui.dll
dlls.files += $$[QT_INSTALL_BINS]/Qt5Widgets.dll
dllA.path += $${DESTDIR}/platforms
dllA.files += $$[QT_INSTALL_PLUGINS]/platforms/qwindows.dll
dllB.path += $${DESTDIR}/plugins/imageformats/
dllB.files += $$[QT_INSTALL_PLUGINS]/imageformats/qico.dll
dllB.files += $$[QT_INSTALL_PLUGINS]/imageformats/qwbmp.dll
INSTALLS += dlls dllA dllB
Referenciando: http://doc.qt.io/qt-5/qmake-variable-reference.html#deployment
En caso de que necesite identificar prerrequisitos / dependencias multiplataforma, consulte los requisitos previos de CMake getPrerequisites()
. Utiliza dumpbin
, objbin
, ldd
, otool
para la identificación de dependencias.
Referencias: https://cmake.org/cmake/help/v3.0/module/GetPrerequisites.html