[GPL v3]

Порт QtCreator под Windows 2000

Описание


Цель проекта: Сделать возможным работу с QtCreator под Windows 2000.

Лицензия: GNU GPL v3, т.к. используются наработки проекта ReactOS.

Так уж сложилось, что Windows 2000 мною все еще используется (Windows 98 тоже, но это совсем другая история). Но, когда внезапно потребовалось запустить QtCreator, это оказалось непростой задачей. Бинарные сборки не устанавливались и не запускались под этой ОС, сборка из исходных кодов также не была успешной. Поэтому было решено выполнить полноценное (насколько это возможно) портирование. Также было решено портировать и jom.

Исследования исходного кода показали, что проблема заключается в использовании Qt и QtCreator`ом функций из WinAPI, которых еще не существовало в Windows 2000. Ситуация осложнялась тем, что функций в WinAPI много, а внятной документации на них - мало. Кроме того, на MSDN содержится заведомо неверная информация о том, какая ОС что имеет. Для многих функций указано, что минимальная версия системы - Windows XP/Windows Server 2003, однако они присутствовали еще в Windows 2000, а может быть и раньше.

Тем не менее, удалось составить действительно отсутствующих функций. Эти функции с указанием статуса портирования приведены в таблице*:

Где Функция Реализация Примечание
Qt SetDllDirectoryW не соответствует спецификациям добавляет путь в PATH, при поиске все равно туда дойдет рано или поздно
Qt, jom rand_s полноценная не является криптографически безопасной, но кому это нужно?
jom StringCchPrintf полноценная отсутствовала в MinGW, взята из MSVC
QtCreator CheckRemoteDebuggerPresent полноценная реализована через NtQueryInformationProcess на основе кода из ReactOS
QtCreator DebugActiveProcessStop заглушка возвращает ошибку (ERROR_ACCESS_DENIED), рабочая реализация маловероятна**
QtCreator DebugBreakProcess заглушка возвращает ошибку (ERROR_ACCESS_DENIED), рабочая реализация маловероятна
QtCreator GetNativeSystemInfo полноценная реализована через GetSystemInfo
QtCreator GetProcessId полноценная реализована через NtQueryInformationProcess на основе кода из ReactOS
QtCreator SHParseDisplayName полноценная реализована на основе кода из ReactOS

* Данная таблица верна для Qt-4.8.7 и QtCreator-3.2.2.
** Эта функция используется для вызова отладчика при запуске консольных приложений. Технически, можно попробовать реализовать иной алгоритм вызова отладчика, ведь это как-то реализовано в том же Code::Blocks. Однако, этим сейчас некому заниматься.

Вместо некоторых функций сейчас пока заглушки, однако то, что есть, уже позволяет почти полноценно использовать QtCreator по прямому назначению.

Скриншоты

Скриншот работы  Работа отладчика


Поддерживаемые платформы



Загрузка

Исходный код (оригинальный):
https://fami.codefreak.ru/osp/qtcreator-w2k/files/v0.5/sources/original/

Исходный код (пропатченный):
https://fami.codefreak.ru/osp/qtcreator-w2k/files/v0.5/sources/patched/

Патчи:
https://fami.codefreak.ru/osp/qtcreator-w2k/files/v0.5/sources/patches/

Бинарные сборки:
https://fami.codefreak.ru/osp/qtcreator-w2k/files/v0.5/binaries/

Toolchain:
https://fami.codefreak.ru/osp/qtcreator-w2k/files/toolchain/


Список изменений

[v0.5] - 16 Jul 2015 Предыдущие версии
[v0.4] - 18 Nov 2014
  • QtCreator обновлен до версии 3.2.2
  • jom обновлен до последней версии в git
  • Иконки файловых ассоциаций заменены на 8-битные
[v0.3] - 27 Aug 2014
  • QtCreator обновлен до версии 3.2.0
  • jom обновлен до последней версии в git
  • Прекращена поддержка MSVC 2005 и старых MinGW (увы, слишком много c++11 в новой версии)
  • Добавлена реализация SHParseDisplayName
[v0.2] - 26 Aug 2014
  • Добавлена реализация CheckRemoteDebuggerPresent
  • Поправлена реализация SetDllDirectoryW (теперь приоритет у нового пути наибольший)
  • Ошибки в заглушках теперь ERROR_ACCESS_DENIED
[v0.1] - 02 Aug 2014
  • Первый работоспособный релиз


Инструкции по сборке

Для сборки потребуется: Примечание 1: Show/Hide
для MinGW 4.8.1 потребовался следующий патч (баг 2250, в toolchain уже исправлено):
diff --git a/include/math.h b/include/math.h
index 5f5f28e..42935aa 100644
--- a/include/math.h
+++ b/include/math.h
@@ -630,10 +630,14 @@ extern long double __cdecl fabsl (long double x);
 /* 7.12.7.3  */
 extern double __cdecl hypot (double, double); /* in libmoldname.a */
 extern float __cdecl hypotf (float, float);
+/* MinGW bug: */
+/* http://sourceforge.net/p/mingw/bugs/2250/ */
+/*
 #ifndef __NO_INLINE__
 __CRT_INLINE float __cdecl hypotf (float x, float y)
 { return (float)(_hypot (x, y)); }
 #endif
+*/
 extern long double __cdecl hypotl (long double, long double);
 
 /* 7.12.7.4 The pow functions. Double in C89 */

Примечание 2: уже не актуально, но вдруг кто использует старый MinGW Show/Hide
для MinGW 4.8.1 потребовался следующий патч (баг 2047, в toolchain уже исправлено):
diff -Nur MinGW-4.8.1_orig/include/wtypes.h MinGW-4.8.1/include/wtypes.h
--- MinGW-4.8.1_orig/include/wtypes.h	2013-09-23 02:56:39.000000000 +0700
+++ MinGW-4.8.1/include/wtypes.h	2014-08-03 03:22:52.684587100 +0700
@@ -21,6 +21,13 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  */
+/**
+* Must include rpc.h and rpcndr.h before defining header guard due to circular
+* dependencies.
+*/
+#include <rpc.h>
+#include <rpcndr.h>
+
 #ifndef _WTYPES_H
 #define _WTYPES_H
 #pragma GCC system_header

Примечание 3: уже не актуально, но вдруг кто использует старый MinGW Show/Hide
с версии v0.3 для MinGW 4.8.1 потребуется еще и этот патч (баг 2024, в toolchain уже исправлено):
diff -Nur MinGW-4.8.1_orig/include/io.h MinGW-4.8.1/include/io.h
--- MinGW-4.8.1_orig/include/io.h	2013-09-23 02:42:01.000000000 +0700
+++ MinGW-4.8.1/include/io.h	2014-08-26 23:21:34.846371400 +0700
@@ -298,8 +298,8 @@
 }
 
 #ifndef __NO_MINGW_LFS
-__CRT_INLINE off64_t lseek64 (int, off64_t, int);
-__CRT_INLINE off64_t lseek64 (int fd, off64_t offset, int whence) {
+__CRT_INLINE _off64_t lseek64 (int, _off64_t, int);
+__CRT_INLINE _off64_t lseek64 (int fd, _off64_t offset, int whence) {
   return _lseeki64(fd, (__int64) offset, whence);
 }
 #endif


Далее будем предполагать, что:

MinGW 4.8.1

Не забываем, что нужен mingw32-make из MinGW-w64, а также fart.exe где-нибудь в PATH. Пусть сам MinGW расположен в C:\MinGW-4.8.1, а mingw32-make - в C:\MinGW-4.8.1\bin

Открываем Command Prompt и используем следующие команды:
set QTSRCF=Qt\4.8.7-src
set QTSRC=C:\%QTSRCF%
set QTDSTF=Qt\qt4.8.7-mingw481
set QTDST=C:\%QTDSTF%
set MINGWDIR=C:\MinGW-4.8.1
set CREATORSRC=C:\Qt\qtcreator-3.2.2-src
set CREATORDST=C:\Qt\qtcreator-3.2.2
set JOMSRC=C:\Qt\jom
set PATH=%QTSRC%\bin;%MINGWDIR%\bin;%PATH%

cd /D %QTSRC%
configure -D W2K_COMPAT -D WINVER=0x0500 -D _WIN32_WINNT=0x0500 -platform win32-g++ -debug-and-release -qt-zlib -qt-libpng -qt-libmng -qt-libtiff -qt-libjpeg -opensource -no-sse2 -no-sse -no-3dnow -nomake demos -nomake examples -confirm-license -no-s60 -no-phonon -no-phonon-backend
mingw32-make
fart -c -i -r Makefile* $(INSTALL_ROOT)\%QTSRCF% $(INSTALL_ROOT)\%QTDSTF%
set INSTALL_ROOT=
mingw32-make install
copy %MINGWDIR%\bin\libgcc_s_dw2-1.dll %QTDST%\bin\
copy "%MINGWDIR%\bin\libstdc++-6.dll" %QTDST%\bin\

xcopy /E %QTSRC%\demos\* %QTDST%\demos\
xcopy /E %QTSRC%\examples\* %QTDST%\examples\

echo [Paths]> %QTDST%\bin\qt.conf
echo Prefix = ..>> %QTDST%\bin\qt.conf
echo Translations = translations>> %QTDST%\bin\qt.conf
echo Documentation = doc>> %QTDST%\bin\qt.conf
echo Headers = include>> %QTDST%\bin\qt.conf
echo Libraries = lib>> %QTDST%\bin\qt.conf
echo Binaries = bin>> %QTDST%\bin\qt.conf
echo Plugins = plugins>> %QTDST%\bin\qt.conf
echo Imports = imports>> %QTDST%\bin\qt.conf
echo Data = .>> %QTDST%\bin\qt.conf
echo Settings = .>> %QTDST%\bin\qt.conf
echo Examples = .>> %QTDST%\bin\qt.conf
echo Demos = .>> %QTDST%\bin\qt.conf

cd /D %CREATORSRC%
qmake -r CONFIG+="release" CONFIG+="w2k_compat" DEFINES+="NDEBUG" qtcreator.pro
mingw32-make

mingw32-make install INSTALL_ROOT=%CREATORDST%
copy %MINGWDIR%\bin\libgcc_s_dw2-1.dll %CREATORDST%\bin\
copy "%MINGWDIR%\bin\libstdc++-6.dll" %CREATORDST%\bin\
copy %QTSRC%\lib\QtCore4.dll %CREATORDST%\bin\
copy %QTSRC%\lib\QtGui4.dll %CREATORDST%\bin\
copy %QTSRC%\lib\QtNetwork4.dll %CREATORDST%\bin\
copy %QTSRC%\lib\QtScript4.dll %CREATORDST%\bin\
copy %QTSRC%\lib\QtCLucene4.dll %CREATORDST%\bin\
copy %QTSRC%\lib\QtDesigner4.dll %CREATORDST%\bin\
copy %QTSRC%\lib\QtDesignerComponents4.dll %CREATORDST%\bin\
copy %QTSRC%\lib\QtHelp4.dll %CREATORDST%\bin\
copy %QTSRC%\lib\QtSql4.dll %CREATORDST%\bin\
copy %QTSRC%\lib\QtSvg4.dll %CREATORDST%\bin\
copy %QTSRC%\lib\QtWebKit4.dll %CREATORDST%\bin\
copy %QTSRC%\lib\QtXml4.dll %CREATORDST%\bin\
copy %QTSRC%\translations\*.qm %CREATORDST%\share\qtcreator\translations\

cd /D %JOMSRC%
qmake -r CONFIG+="release" CONFIG+="w2k_compat" DEFINES+="NDEBUG" jom.pro
mingw32-make

copy %JOMSRC%\bin\jom.exe %CREATORDST%\bin\
Для большей универсальности можно с помощью VS2005 x64 собрать win64interrupt для отладки 64-битных приложений.

Открываем Visual Studio 2005 x64 Cross Tools Command Prompt и используем следующие команды:
set CREATORSRC=C:\Qt\qtcreator-3.2.2-src
set CREATORDST=C:\Qt\qtcreator-3.2.2
 
cd /D %CREATORSRC%\src\tools\wininterrupt
cl -o %CREATORDST%\bin\win64interrupt.exe wininterrupt.c
Готово.