Часто, при попытке запуска Qt-зависимого приложения на "чистой" системе невозможна из-за отсутствия на ней redistributive paket MS Visual Studio ***. Это тем более становиться неожиданным, когда сам проект компилировался в операционной системе с заведомо установленной студией и никаких проблем не вызывал.
Простое решение - поставить статическую сбоку библиотек в настройке проекта - помогает только для MFC/ATL (не CLR) проектов. Но не для Qt! А всё потому, что изначально, библиотеки Qt:Framework Only для работы в MS Visual Studio содержат зависимости от msvc*.dll.
Задача: убрать зависимость Qt библиотек и приложений, их использующих, от динамических библиотек MS Visual Studio (msvc*.dll).
Все действия проводим до конфигурирования командой configure!
qmake.conf
Для начала изменим файл qmake.conf. Откройте его по адресу
msvc | Visual Studio 6 |
---|---|
msvc.net | Visual Studio.NET 2002-2003 |
msvc2005 | Visual Studio.NET 2005 |
msvc2008 | Visual Studio.NET 2008 |
Потребуется внести следующие изменения:
Заменить
QMAKE_CFLAGS_RELEASE = -O2 -MD
QMAKE_CFLAGS_DEBUG = -Zi -MDd
На
QMAKE_CFLAGS_RELEASE = -O2 -MT
QMAKE_CFLAGS_DEBUG = -Zi -MTd
Этими ключами мы даем понять компилятору, что при сборке Qt необходимо статически прилинковать все необходимые библиотеки компилятора.
Но при попытке откомпилировать Qt, мы получим ошибку от mt.exe. Читаем дальше.
Manifest
Manifest - это файл, в котором, грубо говоря, описываются все зависимости приложения. При использовании статической компиляции библиотек компилятора, Manifest становится ненужным и не генерируется. И при попытке mt.exe присоединить его к проекту и получается ошибка. Чтобы избавится от этой проблемы, необходимо слегка изменить некоторые файлы.
Способ №1
В уже открытом нами файле qmake.conf:
Заменить
CONFIG += qt warn_on release incremental flat link_prl precompile_header autogen_precompile_source copy_dir_files
debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
На
CONFIG += qt warn_on release incremental flat link_prl precompile_header autogen_precompile_source copy_dir_files
debug_and_release debug_and_release_target
Т.е. удалить embed_manifest_dll embed_manifest_exe
Данными изменениями мы в явном виде запрещаем подключения манифестов к проекту.
Способ №2
Зайдем в директорию
Заменить
QMAKE_POST_LINK = $$quote(mt.exe -nologo -manifest \"$$replace(OBJECTS_DIR,/,\\)\\$${NOPATH_TARGET}.intermediate.manifest\"
-outputresource:$(DESTDIR_TARGET);1$$escape_expand(\n\t))
На
QMAKE_POST_LINK = $$quote(@if exist \"$$replace(OBJECTS_DIR,/,\\)\\$${NOPATH_TARGET}.intermediate.manifest\" mt.exe -nologo
-manifest \"$$replace(OBJECTS_DIR,/,\\)\\$${NOPATH_TARGET}.intermediate.manifest\" -outputresource:$(DESTDIR_TARGET);
1$$escape_expand(\n\t))
Тоже самое проделываем для файла embed_manifest_dll.prf
В измененной строке nmake проверит, сгенерирован ли манифест, и только в этом случае добавит его к проекту. Способ является более универсальным, хотя в большинстве случаев принципиальной разницы между ними нет.
Итог
Теперь осталось только запустить configure.exe с необходимыми вам ключами (включая -static), а затем использовать nmake. Все проекты, создаваемые при помощи qmake, уже будут иметь необходимые настройки.
Проверить проделанную работу можно, используя Total Commander. Достаточно только выделить любое приложение, откомпилированое с данной версией Qt, нажать F3 и во вкладке Dll Dependency убедится в отсутствии в списке MSVCR**.dll.
Опыт применения
Проделанные действия для Qt libraries 4.6.3 for Windows (VS 2008, 194 MB) в приложении к MS Visual Studio 2005 не привели к желаемому результату. Зависимость от MSVCR90.dll, которая наблюдается в Qt4.6.3 изменилась на зависимость от MSVCR80.dll. И, что бы в этом убедится, достаточно запустить компиляцию и дождаться появления (обновления) moc.exe в папке BIN. И F3 в Total Commander сразу подскажет стоит ли продолжать компиляцию.
Тем не менее, следующие действия решили проблему:
1. Выполнить замену ключей компилятора MD на MT и MDd на MTd, как описано выше.
2. Дописать в строке для линковщика QMAKE_LFLAGS = /NOLOGO /DELAYLOAD:\"OleAcc.dll\". Честно говоря, необходимость в этом действии сомнительна. Однако, строка параметров линковщика для проекта, созданного в MS Visual Studio 2005, для Shared... и Static... отличаются именно на /DELAYLOAD:\"OleAcc.dll\"
3. К параметрам configure.exe необходимо добавить ключ -no-crt. Без него линковщик спотыкается на MT (MTd) и выдаёт невообразимые ошибки. Это вызвано тем, что, вероятно, где-то в ключах компилятора прячется -clr, который и не даёт сделать статическую сборку.
Примечание. Применение ключа -static не обязательно для данной задачи. Манифесты так же трогать не обязательно.
Для удобства можно применить *.bat файл, следующего содержания:
::все переменные создадутся локально и будут безболезненно убраны
setlocal
::если у вас когда-то был QNX IDE это поможет
set MAKEFLAGS=
::переменные окружения от студии
call "C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat" x86
::путь куда установилась библиотека
set QTDIR=c:\Qt\4.6.3
set PATH=c:\Qt\4.6.3\bin;%PATH%
::собственно, для чего компилируется
set QMAKESPEC=win32-msvc2005
::перейти в папку с библиотекой
cd %QTDIR%
::на всякий случай %)
nmake confclean
::для ускорения процесса применены -fast -no-qmake
::(повторно компилировать qmake.exe нет необходимости).
configure -debug-and-release -opensource -fast -no-qmake -no-crt
::И без -static всё успешно компирирует
::А вот и причина приводящая к появлению большого количества свободного времени :)
nmake
::Это на случай запуска не из консоли.
pause
::Все переменные окружения безопасно изымаются.
endlocal
Если применялся -static, то в свойствах нового проекта: "Configuration Properties" -> "C/C++" -> "Code Generation" -> параметр "Runtime Library" должен быть выставлен на "Multi-threaded (/MT)".