-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Пользовательский интерфейс для создания многомодульных программ #87
Comments
Уточнение поведения утилиты
|
Уточнение по поводу srmakeА зачем у префиксов и ссылок нужно анализировать зависимости? Ведь они уже готовые скомпилированные элементы, их не надо перекомпилировать. Ссылка или префикс требуют для своего подключения каких-то дополнительных исходников? Если да, то почему тогда эти исходники не были скомпилированы в саму библиотеку или префикс? Можно пост-фактум скомпилировать и приписать RASL. Можно вместо одной библиотеки создать другую, которая будет ссылаться на первоначальную. Если ссылка или префикс должны работать вместе с исходниками, то, может лучше, сам исходник указать в директиве Префикс или ссылка требует другой ссылки? Это разрешается динамически при загрузке. Ссылка требует префикса? См. выше (пустой исходник с двумя комментариями Так что если возникнет ситуация подключать конгломерат из исходника и ссылки/префикса, лучше подключать через доступ к исходнику. Недостаток: требуется править исходные тексты, добавляя в них |
Что изменилось в srmake-core: * Во-первых, понимаются все новые опции командной строки. * Во-вторых, извлекаются из файлов ключи //PREFIX и //REFERENCE. * В-третьих, правильным образом формируется командная строка для srefc-core (который на данном этапе игнорирует новые опции). Ссылки на задачи #89 и #90 добавлены, поскольку в них предполагалось реализовать, соответственно, //PREFIX и //REFERENCE.
Уточнение. В дополнение к опциям Сейчас такое поведение поддерживается за счёт неуказания ключей А случай с неуказанием компилятора должен вполне корректно работать в режиме |
Ранее ключ -C использовался для задания опций командной строки компилятора C++, но, поскольку у него ещё были синонимы -F и --cppflags, я его оттуда убрал. В старом смысле ключ -C использовался в src/make.*, поменял на -F.
Очередные уточненияЧто имеем сейчасЧто работаетСейчас компилятор умеет правильно собирать модули I0 и I+. Поддерживаются три режима:
Разделение стандартной библиотеки на Режимы Различие (на данный момент) между Что не работаетЕсть частичная поддержка сборки библиотек (модулей типа N), но они пока собираются точно также, как модули типа I: используется только другой префикс командной строки (который сейчас установлен в пустую строку) В чём проблемаПроблема в подходе к созданию библиотек. Вернее, проблем несколько. Разная компоновка библиотек для модулей типа I и NДопустим, мы компилируем программу, использующую библиотеки Если точно также мы соберём библиотеку, то… А что тогда мы бы хотели получить? Библиотеку (С другой стороны, ничто не мешает подключать Получается, что для разных типов целевого файла (I и N) библиотеки должны подключаться по-разному. Разница в компоновке А что, если мы хотим скомпилировать эту библиотеку в модуль R? Почему бы и нет, ведь если мы создаём программу с префиксом, то нативного кода в ней точно нет. По-хорошему, этот модуль R также должен иметь ссылки на Подключение рантаймаЧтобы в режиме Это костыль. Более того, для I+ модуля и N+ модуля нужны разные рантаймы. Выше предлагалось использовать опцию Предлагаемое решениеПредлагается изменить алгоритм сканирования путей поиска файлов. Сейчас последовательно просматриваются все папки, для каждой папки (назовём её Предлагается изменить подход к рантайму. Рантайм для Преимуществом префикса Точно также с реализацией динамических библиотек из префикса |
Имеет смысл режим Также после реализации N-модулей из префикса |
Что уже реализовано?
Что криво?Перечисленное выше обеспечивает хорошую работу при сборке исполнимых файлов. Но вот с библиотеками криво. Допустим, мы собираем библиотеку ( В режиме Если библиотека будет загружаться из модуля, тоже собранного в режиме Если использующий её модуль собран в режиме Если до этой библиотеки были загружены другие библиотеки, некоторые из них имеют статически скомпонованную Теперь посмотрим, что получится, если библиотеку собрать в режиме В режиме Как предлагается это исправить?
|
Вместо |
Что ещё криво?Криво то, что опция Что делать?Ничего. Это не бага, а фича. Её исправление сильно всё усложнит и потребует много времени. |
|
Как реализовать Для Для Для режима |
Много переменныхКомпоновка определяется большим числом переменных: префикс (тонкий/толстый/нет), тип компоновки стандартных библиотек (авто/статический/динамический), наличие отладочного кода (есть/нет, см. #261). Компиляция также определяет целевой файл: исполнимый, DLL или R-модуль. Все эти Предлагается добавить к скриптам сборки три набора ключей (первый — по умолчанию):
Поскольку это ключи скриптов, они должны располагаться в начале командной строки. Нужно продумать разумное поведение для любой комбинации этих ключей (включая ключи компилятора Надо иметь ввиду, что R-модули не всегда используются как библиотеки, они могут быть готовыми программами для интерпретатора (#48), который их загружает и вызывает функцию |
Случай AСтроится исполнимый файл с тонким префиксом ( Случай БСтроится R-модуль без префикса, все библиотеки компонуются динамически. Случай ВСтроится исполнимый файл с тонким префиксом ( Случаи А и В отличаются лишь отладочными средствами. Случай ГСтроится R-модуль без префикса, библиотеки Случай ДСтроится исполнимый файл с тонким префиксом ( Случай ЕСтроится исполнимый файл с тонким префиксом ( Случаи Д и Е отличаются только отладочными средствами. Случай ЁСтроится исполнимый файл с толстым префиксом ( Случай ЖСтроится динамическая библиотека с толстым префиксом ( Файлы библиотек Таким образом, все файлы библиотек содержат ссылки. Случай ЗПри компиляции в режиме Поэтому все библиотеки для случаев Ж и З должны содержать ссылки не смотря на наличие толстого префикса. Случай ИСтроится исполнимый файл с толстым префиксом ( Случаи Ё и И отличаются только отладочной информацией. Случай ЙСтроится динамическая библиотека с толстым префиксом ( Файлы библиотек Отличия Ж и Й в режимах компиляции. В случае Ж компилятор может добавлять некий отладочный код вроде вызова профилировщика. Хотя я пока не понимаю, какой отладочный код там может быть добавлен. Возможно, Ж=Й. Случай КВсе библиотеки скомпилированы в RASL и Си++ (если использовалась При использовании Случай ЛБиблиотеки прилинковываются динамически — доступны только .rasl’ы с ссылками. Рантайм доступен только библиотечный. Средства диагностики в нём используются (например, не отключены макросами препроцессора, см. #261). При компиляции получается библиотека, которая динамически загружает стандартные библиотеки. Про Случай М!Восклицательный знак символизирует ошибку, т.е. эта комбинация не поддерживается. Если используется Если использовать Случай НБиблиотеки скомпилированы в RASL и Си++ (если использовалось Отличие от случая К — в отсутствии диагностики, остальное то же самое. Случай ОСтандартные библиотеки прилинковываются динамически. Доступен библиотечный рантайм, но без средств диагностики. При компиляции получается динамическая библиотека, которая динамически подгружает стандартные библиотеки. Случай О аналогичен случаю Л, только средства диагностики в нём отсутствуют. Случай ПБиблиотеки Нельзя к библиотеке прилинковывать статически библиотеку Случай РАналогичен случаю П, только средства диагностики отключены. Случай ССтандартные библиотеки связываются динамически. Доступны исходники рантайма для исполнимых файлов, включая диагностические средства. При компиляции получается исполнимый файл, содержащий только рантайм (с диагностическими средствами) и ссылки на стандартные библиотеки. Случай ТАналогичен случаю С, только диагностические средства отсутствуют. Случаи С и Т — единственные два способа создать исполнимый файл, который библиотеку А как собрать
|
Ранее .cpp-файлы рантайма для раскрутки брались из /srlib, сейчас берутся из /lib. Для сборки отладочных префиксов требуется указывать --squash и -debug, т.е. переменная SCRIPT_FLAGS может содержать пробелы. Скрипт make.bat ранее не поддерживал эту функцию.
Уже не используются • src/lib-rich-prefix-debug • src/lib-rich-prefix • src/lib-rich-prefix-lib • src/lib-slim-debug-prefix • src/lib-slim-prefix
В зависимости от имени файла скрипта реализуется логика srefc или srmake.
Они теперь копируются из одного шаблона srefc-srmake.*.
Команда shift для Windows сдвигает аргументы, включая %0, из-за чего проверка на имя скрипта не работала. Решение: %~n0 вынесено в переменную до сдвигов. Аналогично модифицирован скрипт для Bash для симметрии.
После формирования новой папки /lib взамен /srlib скрипты make.* из lib-dynamic стали формировать библиотеки, содержащие только ссылку на самих себя. Поэтому теперь при компиляции указывается точный путь до исходников в папке src/lib вместо одного имени. В src/make.bat почему-то использовалось только имя файла исходника без пути (%~n3). Возможно, это когда-то имело смысл, но сейчас утратило актуальность. Правки были вынесены в отдельный коммит ради большей ясности.
Во-первых, он адаптирован к новой папке lib вместо srlib. Во-вторых, в дистрибутив теперь добавляется папка docs.
В папке lib/scratch/exe лежат LibraryEx, Hash, GetOpt, в папке lib/scratch-rt/exe лежат Library и Platform. Переменные CSOURCES и RSOURCES более не нужны, поэтому удалены.
• Опция --ref5rsl добавляет в путь поиска переменную окружения REF5RSL. • Сгенерированные файлы .rasl и .cpp помещаются по умолчанию в текущую папку, альтернативную папку можно указать при помощи --temp-dir=… (эта опция ранее поддерживалась, но игнорировалась). • Работает опция --keep-rasls, ранее она игорировалась. По умолчанию .rasl-файлы удаляются после перекомпиляции. • Работает опция --overwrite-exist-rasls, ранее она игнорировалась. По умолчанию существующие .rasl-файлы с теми же именами перезаписываются. • ИСПРАВЛЕНО: формирование имени целевого файла. Ранее оно могло иметь вид sourcefile@1.exe в некоторых редких случаях. • Флаги --cpp-command-exe-suf=…, --cpp-command-lib-suf=…. На Windows они могут использоваться для передачи .def-файла для библиотек, на Linux для передачи дополнительных внешних библиотек (вроде -lm, -ldl). • В шаблоне конфигурации компилятора C++ задаются переменные CPPLINEL, CPPLINEESUF, CPPLINELSUF. • ИСПРАВЛЕНО: в случае успешной компиляции выдаётся сообщение «Compilation succeeded» вместо ошибочного «Compilation successed». • Для поддержки N-модулей изменился API рантайма. • Поддерживаются N-модули: их генерация и загрузка. • Для стандартных библиотек Hash, Library, GetOpt, LibraryEx, Platform генерируются .dll/.so для динамической загрузки, располагаются в папке /bin. • Инсталлятор на Windows устанавливает переменную среды RL_MODULE_PATH. • Небольшие уточнения в README.md. • Префикс slim(-debug).exe-prefix не содержит библиотеку Hash. • Расширен аварийный дамп. Помимо поля зрения выдаётся сводка из домена: списки загруженных модулей, функций в них и идентификаторов. • ИСПРАВЛЕНО: предупреждение компилятора GCC на рантайм. • ИСПРАВЛЕНО: функция Compare выполняется за один виртуальный шаг. • Вместо папки /srlib используется папка /lib. • Флаг компилятора --no-sources, позволяющий создать целевой файл содержащий только ссылки и/или флаги --incorporated. Без флага --no-sources компилятор выдаёт сообщение об ошибке о том, что исходники отсутствуют. • Изменена структура папки /lib в соответствии с задачей bmstu-iu9/refal-5-lambda#87 • Префикс rich(-debug).lib-prefix, содержащий LibraryEx, Hash и GetOpt. • ИСПРАВЛЕНО: компилятор падал при наличии файла filename.cpp при отсутствии filename.rasl. • Модуль может быть сам себе псевдонимом: допустима ситуация, когда модуль содержит и псевдоним --incorporated=… и ссылку с тем же именем. • Скрипты srefc(.bat) и srmake(.bat) поддерживают новые ключи (в соответствии с bmstu-iu9/refal-5-lambda#87): — ключи --slim, --rich, --scratch определяют префикс или его отсутствие, — ключи --static, --dynamic, --auto определяют компоновку с библиотеками LirbraryEx и GetOpt: статическая, динамическая и по умолчанию (статическая для исполнимых файлов, динамическая для библиотек), — ключи --debug, --no-debug включают и отключают компоновку с отладочными средствами, по умолчанию отладка отключена. Эти ключи должны быть первыми параметрами srefc и srmake, их может следовать неограниченное количество, последние имеют приоритет.
Задача оказалась существенно больше, чем я ожидал ранее. Ортогонализовывать режимы (префикс/отладка/связывание/тип целевого файла) оказалось довольно объёмно и интересно. |
Сборка всего содержимого папки /lib запускается из src/lib/make.*. Ранее префиксы и динамические экземпляры библиотек собирались отдельно из src/make.*. Почти рефакторинг, потому что ранее путь к исходникам библиотек внутри них прописывался как ../lib/〈библиотека〉, сейчас просто 〈библиотека〉. Различие мелкое, но оно влияло, в частности, на вычисление cookies.
Скрипт src/make.* позволяет собирать проекты с подгонкой опций, например, для RELEASE=1. Но здесь подгонка невозможна, исходные файлы в этой папке не содержат кода и содержат только директивы для srmake. Другой побочный эффект src/make.* — создание подпапки в /build. Но для сборки префиксов в релизе эта подпапка не нужна, не нужна она для отладки и в процессе разработки. Поэтому замена на srmake допустима.
Эта задача — подзадача #76 и ответ на #86.
В этой задаче описывается расширения пользовательского интерфейса и поведения программ
srefc-core
,srmake-core
,srefc
,srmake
, необходимые для создания многомодульных программ, предполагаемых в рамках задачи #76.Будем говорить, что компилируемое приложение содержит нативный код, если
.rasl
+.cpp
(библиотечные файлы, файлы рантайма),Любой из вышеперечисленных случаев вынуждает использовать компилятор C++ для создания двоичного модуля целевой платформы.
Пользовательский интерфейс и поведение
srefc-core
Начнём с простого.
Новые параметры командной строки
Компонент
srefc-core
получает следующие параметры командной строки:--prefix=…
(-p
) — указывает префикс, добавляемый в начало файла, необязательный параметр. Используется как при создании исполнимых файлов, так и при создании библиотек (при этом должен быть указан правильный префикс.--reference=…
(-r
) — добавляет ссылку на N- или R-модуль, автоматически загружаемый при запуске приложения.--exesuffix=…
,--libsuffix=…
— заменяют--targsuffix=…
, используемый сейчас (1.λ.11.2). Значения по умолчанию.EXE
и.DLL
, соответственно. Далее на значения, заданные этими ключами будем ссылаться как(EXESUF)
и(LIBSUF)
.--makeexe
(-x
),--makelib
(-l
),-R
— взаимоисключающие, предписывают собирать либо модуль типа I, либо модуль типа N или R, либо модуль типа R. По умолчанию используется опция--makeexe
.--no-dot-native
— отключает создание файла.native.(LIBSUF)
.--incorporated=libname
— указать, что библиотека с именемlibname
будет встроена в текущий собираемый файл.Детали поведения
Префикс ищется по тем же путям поиска, что и исходные файлы. Файл префикса должен иметь расширение
.exe-prefix
либо.lib-prefix
, однако в командной строке расширение явно не задаётся, а определяется на основе опций--makeexe
или--makelib
.Ссылки на библиотеки при компиляции не ищутся, а просто записываются в файл.
Если задан префикс и при этом приложение содержит нативный код, то
помимо исполнимого файла с именемкомпиляция будет прерываться с выдачей сообщения об ошибке.(TARGET)(EXESUF)
также будет по умолчанию создаваться файл(TARGET).native(LIBSUF)
. Если указан ключ--no-dot-native
, то при наличии нативного кода на входеОпция
--makelib
при явно указанном префиксе и/или при наличии нативного кода создаёт модуль типа N, в противном случае — модуль типа R. Если в единицах трансляции есть нативный код, то с опцией--makelib
в командную строку компилятора C++ добавляется ключ-DREFAL_5_LAMBDA_MAKELIB
. Таким образом можно иметь общий рантайм для I+- и N+-модулей.Опция
-R
предписывает создать из исходных файлов модуль типа R, при этом префикс игнорируется. При наличии нативного кода компиляция прерывается с выдачей сообщения об ошибке.Возникает вопрос: а какое расширение должно быть у файла, если указана опция
-R
и пользователь явно не задал имя целевого файла? По-хорошему, оно должно быть.rasl
, но тогда оно будет совпадать с именем выходного файла для первой единицы трансляции. Тогда получаем два варианта: или изменить имена выходных файлов (например, на.raslo
или.orasl
), или использовать расширение целевого файла.out.rasl
или.rldl
/.srdl
(Refal-5 Lambda Dynamic Link/Simple Refal Dynamic Link). Ответ на этот вопрос будет найден позже.В качестве префикса
можетдолжен использоваться уже готовый модуль типа I.следовательно,Таким образом, даже если префикс содержит только рантайм (без стандартных библиотек), он обязан иметь дополнение до 4096.srmake-core
должен уметь отличать «голые» exe-шники от модулей типа I с RASL-кодом и не добавлять дополнение до 4096 в последние. Или добавлять таким образом, чтобы рантайм мог его проигнорировать. Предпочтительнее первый вариант.Опция
--incorporated
является антонимом опции--reference
: если в запущенной программе присутствует модуль с записью «incorporated» (нужно будет добавить в формат RASL), то при наличии в других модулях записиREFERENCE
с тем же именем, последняя будет игнорироваться, поиск соответствующего модуля будет подавляться. «Инкорпорирование» библиотек полезно для случая, когда используются «толстые» префиксы, содержащие несколько библиотек внутри.Пользовательский интерфейс и поведение
srmake-core
Новые параметры командной строки
Компонент
srmake-core
получает опции--prefix
(-p
),--reference
(-r
),-R
,--makeexe
(-x
),--makelib
(-l
),-R
с тем же смыслом, что иsrefc-core
.Детали поведения
Тут уже интереснее. Утилита
srmake-core
, как мы помним, ищет единицы трансляции по путям поиска и формирует командную строку дляsrefc-core
. Если единица трансляции уже скомпилирована, то ищется файл с расширением.rasl.froms
и анализируется также, как и исходный текст (в поисках комментариев//FROM
). Предлагается модифицировать это поведение следующим образом.В список искомых файлов добавляются файлы, указанные в ключах
--prefix
и--reference
(при этом расширение префиксов определяется ключами--makeexe
и--makelib
(в случае ключа-R
префиксы игнорируются). Это раз.Префиксы и ссылки также могут содержать списки//FROM
, а значит и иметь зависимость от других файлов. Для префиксов это немножко странно, но, почему бы и нет.Помимо комментариев
//FROM
,srmake-core
начинает понимать комментарии//PREFIX
и//REFERENCE
с очевидным смыслом. При этом, если заданы различные префиксы в командной строке и в одном из файлов, либо разные префиксы в двух файлах, происходит ошибка компиляции. При этом одно и то же имя префикса может быть указано в разных местах одновременно, это ошибкой не является.Поскольку помимо ссылок
//FROM
поддерживаются и другие типы ссылок, расширение.rasl.froms
меняется на расширение.rminfo
.rasl.rminfo
(Refal Make info).Общий взгляд на компиляцию и сборку, изменения
srefc
иsrmake
Что дают новые возможности
srmake-core
(иsrefc-core
)Как можно видеть, новые возможности
srmake
позволяют стандартныеLibrary.sref
иLibraryEx.sref
либо скомпилировать в отдельный N-модуль, либо даже вкомпилировать (инкорпорировать) в префикс. В обоих случаях нужно будет создать файлы, соответственно,Library.rminfo
иLibraryEx.rminfo
, содержащие, соответственно, тег//REFERENCE
либо//PREFIX
. В итоге, код, использующий//FROM LibraryEx
, по-прежнему останется компилируемым.Но при этом нужно пользователю предоставить свободу выбора: компилировать программу в модуль типа I+, используя исходные тексты рантайма и библиотек, компилировать программу, используя «толстый» готовый префикс с рантаймом и всеми стандартными библиотеками (
Library
,LibraryEx
,Hash
), используя «лёгкий» префикс с одним только рантаймом (если стандартные библиотеки не нужны или должны подгружаться отдельно).Новые ключи
srefc
иsrmake
В текущей версии скрипты
srefc
иsrmake
дословно передают свои ключи соответствующей программе***-core
, но теперь они будут по особому обрабатывать свой первый аргумент.Итак, если командная строка начинается с одного из следующих слов, то оно обрабатывается скриптом, но при этом не передаётся нижележащей программе:
--rich
— добавить в пути поиска префикс с инкорпорированными стандартными библиотеками и файлы*.rminfo
для библиотек, ссылающиеся на префикс. Используется по умолчанию.--slim
— добавить в пути поиска префикс, состоящий только из одного рантайма и стандартные библиотеки, скомпилированные в один или несколько N-модулей.--scratch
— добавить в пути поиска единицы трансляции рантайма и стандартных библиотек (.rasl
или.rasl
+.cpp
) без собранных префиксов и N-модулей. Эта опция даёт возможность пользователю создавать свои модули типа I+ и N+, либо компилировать с оптимизацией прямой кодогенерации без лишних файлов.native.(LIBSUF)
.Критерий завершённости
Эта задача будет закрыта, когда будет реализована большая часть описанной функциональности. Программа-минимум: весь интерфейс, модули типа I0, модули типа R. Программа-максимум: весь интерфейс, модули типа I0, модули типа R, модули типа N — полная функциональность #76.
The text was updated successfully, but these errors were encountered: