Мы исправляли ошибки в VCL в Delphi XE6. Пока папка содержит:
| VCL Source Fixes
|----- Vcl.ComCtrls.pas
|----- Winapi.CommCtrl.pas
И мы добавляем папку в путь поиска нашей библиотеки:
Попутно мы узнали, что мы должны ограничить наши исправления только разделом implementation
. В противном случае хеш-подписи символов в разделе interface
изменятся. Это заставляет компоновщика понять, что символы внутри DCU не являются той версией, которую они ожидают.
У Барри Келли было хорошее объяснение этому поведению:
Важной концепцией является версия символа. При сохранении DCU Delphi вычисляет хэш на основе объявления интерфейса символа и связывает его с символом. Другие юниты, которые используют символ, также хранят версию символа. Таким образом, избегаются конфликты времени соединения, вызванные устаревшими символами, в отличие от большинства C-линкеров.
Результатом этого является то, что вы должны иметь возможность добавлять Classes.pas в ваш проект и изменять его раздел реализации почти в соответствии с вашим содержанием, и при этом иметь возможность статически связываться с остальными библиотеками RTL и VCL и сторонними библиотеками, даже те, которые предоставляются только в объектном формате.
Вещи, чтобы быть осторожным:
- Встроенные процедуры; тело встроенных подпрограмм является частью версии символа
- Дженерики; сторона реализации универсальных типов и методов является частью соответствующих версий символов
Поэтому мы постарались ограничить исправления ошибками в разделе реализации (например, ввести новые классы взломщика, а не переопределять метод в общедоступном классе).
А потом
Тогда я пошел, чтобы исправить в Vcl.Themes.pas
. Я начинаю с простого, копируя файл и помещая его в папку исправлений:
| VCL Source Fixes
|----- Vcl.ComCtrls.pas
|----- Winapi.CommCtrl.pas
|----- Vcl.Themes.pas
Несмотря на то, что я (пока) даже не модифицировал Vcl.Themes.pas
, компилятор его подавляет:
[dcc32 Fatal Error] Vcl.Themes.pas(2074): V20.Forms модуля F2051 был скомпилирован с другой версией Vcl.Themes.TMouseTrackControlStyleHook
Зачем
Важный вопрос:
Почему это происходит?
Что происходит, что компилятор не может понять, что точно такой же файл - точно такой же файл? Возможно ли, что источник VCL, поставляемый с XE6, неверен и не соответствует тому, что поставляется в DCU? Это как-то связано с порядком поиска в библиотеке? Это как-то связано с встраиванием, обобщениями, итераторами, платформами, отладкой dcus, 64-битным компилятором, ifdefs, дополнением кода, синергией, за пределами коробки?
Есть и другие, неявные вопросы, которые сопровождают попытки ответить на вопрос:
Почему это работает для двух других файлов, но не этот?
Почему происходит сбой, когда я даже не изменил файл?
Что вы пробовали?
- попытался переместить
VCL Source Fixes
выше и ниже в пути поиска - попытался включить использование отладки dcus
- попытался перейти на 64-битную платформу
- попытался удалить все файлы
dcu
в папке моего проекта (хотя неdcu
D:\Programs\Embarcadero\Studio\14.0\lib\win32\release\Vcl.Themes.dcu
который поставляется с Delphi XE6) - закрытие XE6 и повторный запуск
- собираюсь в Венди на обед
Конечно, я хочу это исправить. Но больше, чем желание исправить это, я хочу понять, почему это не удается. Компилятор не использует магию, вуду или Q-подобные способности. Это детерминированная машина, работающая в соответствии с фиксированным набором (недокументированных) правил.
Почему это происходит?