итак. что мы имеем от предварительных результатов (которые уже в Lament Configuration).
во-первых, немного переработаный StdLibrarian, в довесок к которому появился StdLibrarianEx, который занимается открытием и созданием файлов, консультируясь у StdLibrarian. компилятор больше не лазит напрямую на диск, чтобы открыть или создать что-то в Sym/Code, а вежливо просит это сделать StdLibrarianEx. DevCompiler всё ещё сканирует каталоги, но тоже за исходниками на диск не лазит, а просит StdLibrarianEx.
зачем отделил? потому что DevCompiler хочет получить Views.View, а я не хочу Views импортировать в StdLibrarian. поэтому второй модуль.
во-вторых. переделал для примера LamentdevLog. это мой личный независимый логер, который пишет строго в консоль/терминал, параллельный другим логам. его специфика в том, что он импортирует только самый минимум, даже нужные системные апи берёт из себя же. ну, чтобы его можно было почти в любом модуле использовать, если понадобится, без боязни circular dependencies. итого: в нём стало на один импорт меньше.
мелочь, скажете вы. но
какой это импорт! это Dialog, который использовался для `Dialog.Call`, чтобы динамически вызвать нужный инициализатор в зависимости от ОС. и теперь импорт логера выглядит так: `SYSTEM, Strings, Base := LamentdevLogCon;`. а LogCon вот так: `SYSTEM, libc := LamentdevLogLinApi;`. а в LinApi ровно два импорта из libc: `write` и `flush`.
и у нас магически повысилась герметичность — без хуков, регистрации и смс! потому что LogCon реализует, по сути, интерфейс, который использует главный Log. но больше не надо чесать репу и руками проверять на то, под какой мы ОС, и дёргать `Dialog.Call()`.
теперь Lamentdev выглядит так:
Код:
Lamentdev/
Lamentdev/Code/
Lamentdev/Code/Win/
Lamentdev/Code/Win/LogCon.ocf
Lamentdev/Code/Win/Log.ocf
Lamentdev/Code/Lin/
Lamentdev/Code/Lin/LogCon.ocf
Lamentdev/Code/Lin/Log.ocf
Lamentdev/Sym/
Lamentdev/Sym/Win/
Lamentdev/Sym/Win/LogWinApi.osf
Lamentdev/Sym/Win/LogCon.osf
Lamentdev/Sym/Win/Log.osf
Lamentdev/Sym/Lin/
Lamentdev/Sym/Lin/LogLinApi.osf
Lamentdev/Sym/Lin/LogCon.osf
Lamentdev/Sym/Lin/Log.osf
Lamentdev/Mod/
Lamentdev/Mod/Win/
Lamentdev/Mod/Win/LogWinApi.odc
Lamentdev/Mod/Win/LogCon.odc
Lamentdev/Mod/Lin/
Lamentdev/Mod/Lin/LogLinApi.odc
Lamentdev/Mod/Lin/LogCon.odc
Lamentdev/Mod/Log.odc
"Code/Win/LogCon.ocf" и "Code/Lin/LogCon.ocf" — разные: один импортирует WinAPI, другой — libc. но главному логеру на это совершенно наплевать, там нет вообще ни одной проверки на ос, и ни одного отложеного вызова через `Dialog.Call()`, или другой подобный механизм. и в инит-модулях ничего добавлять не надо. оно Просто Работает. как видите, там есть главный модуль "Log", который просто импортирует "LogCon". а какую LogCon брать — среда сама знает.
также, `DevCompiler.CompileSubs Lamentdev` отлично понимает, какие модули надо компилировать. для кросс-компиляции есть вызов `DevCompiler.SetCrossArch Win`, например: его надо сделать один раз, и после этого собирать. ну, как-то так:
Код:
./blackboxInterp <<DATA
DevCompiler.SetCrossArch Lin
DevCompiler.CompileSubs Lin System Std Cons Text Form Dev Comm Obx Diff Lamentdev
Kernel.Quit(0)
DATA
реализации для разных ОС не путаются, объектные файлы не путаются, из одного и того же каталога запускается как линуксовая версия, так и виндовая (через wine). можно собирать и Lin и Win версии, как лин-бинарями, так и вин-бинарями через вайн. обычными, не dev. опять таки — из одного каталога. Просто Работает.
пакер тоже подкорректирован, и пакует dev-бинари для соответствующей CrossArch. они даже после этого работают. руками в пакере архитектуру указывать не надо, по-прежнему пишем какой-нибудь "System/Code/Fonts.ocf". всё остальное делает волшебная команда "DevCompiler.SetCrossArch".
если вдруг завтра появится какой-нибудь "Arm" или "Win64" — то я добавлю соответствующий подкаталог в "Lamentdev/Mod/", и всё. и тот же арм-билд я смогу гонять через qemu, например, в режиме прокидывания системных апи, из того же самого каталога, что и другие билды. и собрать его смогу, не поломав при этом всё остальное, и не требуя, чтобы оно обязательно собиралось dev-бинарём.
теперь, если нежно обучить среду ходить за ресурсами через StdLibrarianEx — то магически появится возможность иметь как общий ресурс, так и локальные для системы. и даже перекрывать общий ресурс только для некоторых ос (потому что StdLibrarianEx сначала пытается загрузить из "dir/<arch>/", а если не выходит — тогда просто из "dir/").
в итоге получилось, что я делаю то, что и так надо: заменяю прямые походы на диск обращениями к StdLibrarian постепенно. и вся остальная механика Просто Волшебно Работает. по-моему, это называется «чистка кода и упрощение», а не усложнение. ;-)
p.s.: остальную систему я ещё на эту механику не перевёл, сделал только Lamentdev для обкатки пока. но всё остальное тоже переедет обратно в Host, и будет так же разложено по arch-подкаталогам.
опять таки напомню, что никаких планов объединять те же Kernel и прочее обратно в монолит нет: все уже введённые хуки для отделения платформо-зависимых частей останутся там же, где и были. и организация системы тоже не сильно поменяется: просто "Lin/" и "Win/" из корня переедут в "Host/Mod/Lin/" и "Host/Mod/Win/" (ну, и импорты поправлю где надо). то есть, работа по красивому разделению системы не пропадает даром, она нужна и полезна. просто изменяется расположение файлов на диске, и местами упрощается код за счёт убирания некоторых проверок на архитектуру и связывания во время исполнения (ведь кое-где оно нужно не потому что так идеологически верно, а потому что иначе сейчас в mainline не сделать).