Пишем легаси с нуля на С++, не вызывая подозрение у санитаров. 04 — Компиляторная археология

от автора

Приветствую, Хабравчане!

Я сейчас добавляю возможность вывода изображений с помощью GDI и XLib. Но до конца код не готов. Но решил пока кода мало попробовать его собрать на нескольких старых компиляторах 30-ти летней давности. И только такой путь может дать нормальный бинарник работающий на системах Windows 98, 95.

Для загрузки графики использую stb_image. В итоге получилось так. Правда в оригинале цвет должен быть красным, а не синим. Но пока вывод изображений не закончен.

Основная репа RetroFan.

Картинка выводится с масштабированием GDI.

А, должен выглядеть так:

Для моих целей подойдет не каждый старый компилятор, а только с поддержкой namespace и каким то подобием поддержки шаблонов.

Со сцены сразу уходят Borland C++ компиляторы до версии 4.0

Решил начать с Visual C++ 4.0.

Всё это непотребство тестирую и компилирую на Windows XP установленную на VirtualBox 7.1.4. Я выбрал VirtualBox, потому, что он поддерживаете общие папки. Что позволяет предаваться ретро программированию с комфортом. Разрабатывая код на современных системах, в современном IDE.

Устанавливаем.

Что бы не привязываться к системе сборки от майков, вида nmake и создавать проект непосредственно в студии. Буду собирать простым bat файлом. Подаем ключи и файлы компилятору.

call "c:\msdev\bin\VCVARS32.BAT"  cl /O2 -GX -FeLDL_Win.exe -I..\LDL\include ..\LDL_Win.cpp ..\LDL\source\*.cpp ..\LDL\source\Windows\*.cpp /link gdi32.lib winmm.lib user32.lib opengl32.lib cl /O2 -GX -FeLDL_Img.exe -I..\LDL\include ..\LDL_Img.cpp ..\LDL\source\*.cpp ..\LDL\source\Windows\*.cpp /link gdi32.lib winmm.lib user32.lib opengl32.lib  pause 

Ошибок конечно навалили:) Начнем разбираться.

Скрытый текст
 Z:\make>call "c:\msdev\bin\VCVARS32.BAT"  Usage: vcvars32 [target]     Where target is one of the following: x86, m68k, mppc. No target specified.  Selecting x86 as default target.  Setting environment for building x86 target LDL_Win.cpp ..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list ..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename' ..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list ..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared ..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<' ..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<' ..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory  BaseRndr.cpp ..\LDL\include\LDL/Color.hpp(30) : fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory  BaseWin.cpp ..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list ..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename' ..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list ..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared ..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<' ..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<' ..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory  Eventer.cpp ..\LDL\include\LDL/RngBuf.hpp(35) : error C2952: template declaration must specify parameter list ..\LDL\include\LDL/RngBuf.hpp(35) : error C2061: syntax error : identifier 'typename' ..\LDL\include\LDL/RngBuf.hpp(98) : error C2992: 'RingBuffer' : invalid or missing template parameter list ..\LDL\include\LDL/Events.hpp(30) : fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory  GdiRndr.cpp ..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list ..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename' ..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list ..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared ..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<' ..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<' ..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory  GdiTex.cpp ..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list ..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename' ..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list ..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared ..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<' ..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<' ..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory  MainWin.cpp ..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list ..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename' ..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list ..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared ..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<' ..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<' ..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory  Generating Code... LDL_Img.cpp ..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list ..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename' ..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list ..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared ..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<' ..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<' ..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory  BaseRndr.cpp ..\LDL\include\LDL/Color.hpp(30) : fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory  BaseWin.cpp ..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list ..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename' ..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list ..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared ..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<' ..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<' ..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory  Eventer.cpp ..\LDL\include\LDL/RngBuf.hpp(35) : error C2952: template declaration must specify parameter list ..\LDL\include\LDL/RngBuf.hpp(35) : error C2061: syntax error : identifier 'typename' ..\LDL\include\LDL/RngBuf.hpp(98) : error C2992: 'RingBuffer' : invalid or missing template parameter list ..\LDL\include\LDL/Events.hpp(30) : fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory  GdiRndr.cpp ..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list ..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename' ..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list ..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared ..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<' ..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<' ..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory  GdiTex.cpp ..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list ..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename' ..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list ..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared ..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<' ..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<' ..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory  MainWin.cpp ..\LDL\include\LDL/Vec2.hpp(32) : error C2952: template declaration must specify parameter list ..\LDL\include\LDL/Vec2.hpp(32) : error C2061: syntax error : identifier 'typename' ..\LDL\include\LDL/Vec2.hpp(50) : error C2992: 'Vec2' : invalid or missing template parameter list ..\LDL\include\LDL/Vec2.hpp(52) : warning C4091: no symbols were declared ..\LDL\include\LDL/Vec2.hpp(52) : error C2143: syntax error : missing ';' before '<' ..\LDL\include\LDL/Vec2.hpp(52) : error C2059: syntax error : '<' ..\LDL\include\LDL/BaseWin.hpp(31) : fatal error C1083: Cannot open include file: 'string': No such file or directory

Быстрым гуглением по кодам и описанию ошибок, приходит понимание. Что ещё в до стандартные времена С++ каждый вендор понимал С++ по своему. Ошибка не сложная нужно просто заменить в объявлении шаблона typename на class.

 syntax error : identifier 'typename'

Здесь уже сложнее, в поставку не входит STL и заголовки от С99. Тогда создадим их и передадим компилятору.

#ifndef LDL_Support_stdint_h #define LDL_Support_stdint_h  typedef unsigned char      uint8_t; typedef signed char        int8_t;  typedef unsigned short     uint16_t; typedef signed short       int16_t;  typedef unsigned int       uint32_t; typedef signed int         int32_t;  #endif
fatal error C1083: Cannot open include file: 'string': No such file or directory fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory

На эту ошибку у меня ушло больше времени. Тип bool отсутствует, тогда я его добавил самым простым и очевидным способом.

typedef enum { false, true } bool;
error C2501: 'bool' : missing decl-specifiers

Но сработал другой способ. Переопределение через define. Правда теперь bool вместо 1-го байта, стал 4-ех байтным.

#if (_MSC_VER <= 1100)     #define __forceinline #endif  #if (_MSC_VER <= 1020)     #include <Windows.h>     #define bool  BOOL     #define true  TRUE     #define false FALSE #endif

Естественно компилятор 1995 года не знает ни о каких этих ваших интринсиках. Поэтому добавляем пару дефайнов, отключающие использование современных компиляторных фич.

..\stb_image.h(726) : fatal error C1083: Cannot open include file: 'emmintrin.h': No such file or directory
#if (_MSC_VER <= 1200)     #define STBI_NO_THREAD_LOCALS     #define STBI_NO_SIMD #endif  #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h"

Теперь все файлы собраны, на компиляторе 1995 года. Программы запускаются и работают корректно.

 Z:\make>call "c:\msdev\bin\VCVARS32.BAT"  Usage: vcvars32 [target]     Where target is one of the following: x86, m68k, mppc. No target specified.  Selecting x86 as default target.  Setting environment for building x86 target LDL_Win.cpp BaseRndr.cpp BaseWin.cpp Eventer.cpp GdiRndr.cpp GdiTex.cpp MainWin.cpp Generating Code... Microsoft (R) 32-Bit Incremental Linker Version 3.00.5270 Copyright (C) Microsoft Corp 1992-1995. All rights reserved.  /out:LDL_Win.exe  gdi32.lib  winmm.lib  user32.lib  opengl32.lib  LDL_Win.obj  BaseRndr.obj  BaseWin.obj  Eventer.obj  GdiRndr.obj  GdiTex.obj  MainWin.obj  LDL_Img.cpp BaseRndr.cpp BaseWin.cpp Eventer.cpp GdiRndr.cpp GdiTex.cpp MainWin.cpp Generating Code... Microsoft (R) 32-Bit Incremental Linker Version 3.00.5270 Copyright (C) Microsoft Corp 1992-1995. All rights reserved.  /out:LDL_Img.exe  gdi32.lib  winmm.lib  user32.lib  opengl32.lib  LDL_Img.obj  BaseRndr.obj  BaseWin.obj  Eventer.obj  GdiRndr.obj  GdiTex.obj  MainWin.obj 

За кадром я протестировал версии Visual C++ 5.0 и 6.0 все собирается и больше никаких правок в код я не вносил.

Следующим шагом будут компиляторы от фирмы Borland. И ещё проверить Visual C++ 2.0, он поддерживает шаблоны и namespace. Тоже самое проделаю и со старыми Linux дистрибутивами, когда реализую вывод картинок на XLib.

В итоге, даже на таком древнем компиляторе можно использовать самописный STL и namespace. Что довольно хорошо. А самое главное, код совместим и с новыми компиляторами. Все несовместимости обернул в дефайны с проверкой версии.

Такими странными вещами я занимаюсь в свободное время:)

Буду рад предложениям, критике и советам. Уверен, есть куча компиляторов под Windows о которых я не знаю. Обязательно напишите их название, а я постараюсь собрать на них проект. К примеру узнал, что есть компилятор IBM VisualAge C++.


ссылка на оригинал статьи https://habr.com/ru/articles/876272/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *