Модули, символьные файлы и ключи
В Обероне нет заголовочных файлов. Интерфейс модуля компилятор извлекает из
самого модуля и кладёт рядом — в символьный файл с расширением .smb.
Механизм маленький, но именно он держит всю раздельную компиляцию, и без
понимания ключей половина сообщений компилятора выглядит загадочно.
Что получается при компиляции
Из Math.Mod компилятор делает два файла:
Math.rsc— объектный код: команды, данные, строки, таблицы фиксапов, список импортов и точки входа;Math.smb— символьный файл: только экспортированные имена с их типами.
Смотреть .rsc можно командой ORTool.DecObj Math.rsc — она печатает
заголовок и дизассемблированный код.
Ключ
В заголовке каждого объектного и символьного файла лежит ключ — число, подсчитанное по содержимому интерфейса. В журнале он показывается последним:
compiling Math 447 0 32C32F12
Ключ меняется тогда и только тогда, когда меняется интерфейс: состав экспортированных имён, их типы, порядок. Изменение тела процедуры при том же заголовке ключ не трогает.
Каждый модуль запоминает ключи всех, кого импортирует. При загрузке система сверяет их с настоящими. Не совпало — модуль не загрузится, и вы увидите жалобу на несоответствие.
Это защита от самой неприятной ошибки раздельной компиляции: собрали модуль, поменяли интерфейс библиотеки, пересобрали только её — и получили программу, которая вызывает процедуру по старому смещению. В Обероне такое невозможно: она просто не запустится.
Ключ /s
Отсюда и смысл ключа /s в команде компиляции. По умолчанию компилятор
отказывается перезаписывать символьный файл, если интерфейс изменился, —
потому что это молча сломает всех, кто уже собран.
/s говорит «да, я знаю, перезаписывай». После этого всех зависимых надо
пересобрать. Порядок пересборки — от тех, кто ни от кого не зависит, к тем, кто
зависит от всех.
При пересборке неизменённого исходника интерфейс не меняется, ключ остаётся
прежним, и /s безвреден. Именно поэтому в лабораторных он стоит везде.
Порядок сборки
Порядок задаётся импортами. Для этой системы он получается такой (начало):
Kernel FileDir Files Modules Input Display Viewers
Fonts Texts Oberon ... ORS ORB ORG ORP ...
Его не надо помнить: он выводится из самих исходников топологической
сортировкой по IMPORT. Мы так и делаем, когда пересобираем систему целиком.
Что показывает пересборка
Если исходники и компилятор согласованы, пересборка неизменённого модуля даёт побайтово тот же объектный файл. Это сильное свойство, и его стоит проверять: оно означает, что компилятор детерминирован и что поставляемые двоичные файлы соответствуют поставляемым исходникам.
Мы пересобрали всю систему внутри неё самой. Тридцать семь объектных файлов из тридцати девяти собрались побайтово идентично. Два исключения оказались находками:
Math.rscна образе устарел. Поставляемый файл содержит 449 слов кода, пересборка даёт 447 — при одинаковом ключе32C32F12. Интерфейс тот же, а код порождён другой версией компилятора, чем лежит на том же диске.PIO.rscиPIO.smbотсутствовали вовсе и появляются только после пересборки.
Первое вы воспроизведёте своими руками в лабораторной №7: посмотрите длину
Math.rsc до и после.
Ещё три несогласованности
Заодно выяснилось, что три модуля с этого образа не компилируются компилятором с того же образа:
| модуль | сообщение | причина |
|---|---|---|
RISC |
pos 926 bad divisor |
в тексте IR DIV 80000000H, а эта константа как знаковое целое отрицательна; делитель должен быть положительным |
ORC |
import not available |
импортирует модуль V24, которого на образе нет ни исходником, ни символьным файлом |
Net |
девять раз incompatible parameters |
сигнатуры вызовов SCC разошлись с SCC.Mod этого же образа |
Это не поломка нашей машины и не ошибка сборки: диагностику выдаёт сам
компилятор Оберона, а расхождение в Math.rsc видно побайтовым сравнением
файлов.
Вывод, который стоит унести: распространяемый образ системы не обязан быть согласованным сам с собой, и проверяется это только попыткой пересборки.