Skip to content
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

Разработать подходы и пользовательский интерфейс для создания многомодульных программ #86

Closed
Mazdaywik opened this issue Mar 9, 2017 · 2 comments
Assignees

Comments

@Mazdaywik
Copy link
Member

Эта задача — подзадача для #76.

Обзор достигнутого

Самый простой механизм из предложенных в задаче #76, уже реализован (модули I+, #77) — он почти ничего не меняет в архитектуре и интерфейсе компилятора. Целевой исполнимый файл по прежнему создаётся из набора единиц трансляции, среди которых могут быть как исходные тексты, так и уже скомпилированные. Для создания по-прежнему вызывается компилятор C++. Отличие во внешнем поведении — сгенерированные файлы это либо один файл RASL-а, либо файл RASL-а + исходник на C++ с нативными функциями. Библиотека рантайма в этом случае представляется как файл .rasl нулевого размера + файл .cpp, содержащий, собственно, рантайм.

При реализации многомодульных программ программа (модуль типа I) будет состоять из:

  • (Опционально) префикса — исполнимого модуля с рантаймом, функцией main(), возможно, со скомпилированными библиотеками (Library, LibraryEx), возможно, с кодом RASL’а. Т.е. по факту префикс может представлять собой либо результат трансляции рантайма в исполнимый файл, либо уже полноценную скомпилированную программу на Простом Рефале (модуль типа I)

    Программы, предназначенные для запуска интерпретатором, префикса не имеют.

  • (Опционально) интерпретатора, запускающего программы без префикса. Интерпретатором может служить программа, динамически загружающая модуль и вызывающая в этом модуле функцию Go. Тут ничего интересного, кроме того, что и интерпретатор, и запускаемая им программа, могут содержать библиотеку общего пользования (Library, LibraryEx), причём даже разных версий. Тут нужно обеспечить корректное поведение.

  • Набора модулей, загружаемых при запуске. Они могут быть типа R или N. Загрузка модулей I, скорее всего, будет приводить к ошибке — они будут восприниматься как модули N, но в них не будет необходимой экспортированной функции.

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

Модуль, предназначенный для загрузки (R или N), состоит из тех же компонент, с той лишь разницей, что префиксом может служить либо голый скомпилированный рантайм, либо другой модуль типа N. Ну, и, понятно, роль интерпретатора выполняет загружающая программа. Кстати, модули типа N также можно разделить на модули типа N0 и N+ по аналогии с I0 и I+.

Проблемы

А нюанс следующий. Есть две очевидные ситуации.

  • Префикс не задан, среди исходных файлов присутствуют скомпилированные единицы трансляции, включающие в себя рантайм. Тогда srefc сам создаёт префикс (вызывая компилятор C++) и к нему приписывает RASL.

    Если исходные файлы содержат нативные вставки, либо если включена прямая кодогенерация, то получающиеся файлы .cpp будут скомпилированы вместе с префиксом.

    Собственно, этот подход реализован в задаче Исполнимый файл как SFX (модуль типа I+) #77.

  • Префикс явно задан, среди исходных единиц трансляции отсутствуют исходники C++ (рантайм и скомпилированные единицы трансляции с нативными вставками). Исходные файлы не содержат нативных вставок, также не используется оптимизация прямой кодогенерации.

    В этом случае srefc должен скомпилировать все исходные файлы в RASL, целевой файл сформировать из готового префикса и этого RASL’а.

А дальше начинается комбинаторика:

  • префикс может быть задан или не задан,
  • среди исходных единиц трансляции рантайм может присутствовать и отсутствовать,
  • среди исходных единиц трансляции могут присутствовать скомпилированные единицы трансляции с нативными функциями, а могут и отсутствовать,
  • исходные тексты могут как содержать нативные вставки, так и не содержать (отчасти эквивалентно предыдущему пункту),
  • оптимизация прямой кодогенерации может быть как включена, так и выключена (отчасти эквивалентно предыдущим двум пунктам).

Последние три пункта можно объединить в один, поскольку с точки зрения сборки их объединяет то, что компонуемые файлы могут включать в себя пару .rasl+.cpp. Итого получается 2×2×2=8 комбинаций, из которых две уже рассмотрены. Можно добавить ещё одно двоичное измерение: пользователь указал сборку библиотеки либо сборку исполнимого файла, но это принципиально нового добавлять не должно.

Задача

В рамках данной задачи необходимо разработать подход к сборке и компиляции, позволяющий минимизировать число некорректных комбинаций из перечисленных восьми, при этом сохраняя интуитивно простой интерфейс текущих утилит srefc и srmake. А именно

srmake MainFile.sref

должно давать ожидаемый результат (сборка программы) независимо от того, имеются ли в исходниках нативные функции, как задан префикс и т.д.

Эта задача будет считаться выполненной, когда будет создана новая задача, текст которой является подробной спецификацией, отвечающей на заданные вопросы.

Некоторые идеи

Компилятор srefc должен принимать в качестве параметра, очевидно, префикс, а также имена библиотек, на которые следует добавить ссылки (блок REFERENCE RASL’а).

Srmake тоже может принимать эти же параметры, но это не обязательно. В идеале она должна их вычислять (пользователь указал //FROM Library, единица трансляции подцепилась).

Префикс и внешние ссылки с точки зрения прикладного кода схожи тем, что содержат функции глобальной области видимости, причём они могут быть и нативными.

Если для префикса или внешней ссылки есть исходники, то при необходимости целевой модуль может собираться из их исходников в модуль типа I+ или N+ — это должна быть забота srmake.

Если для префикса исходников нет, но хочется собрать модуль target.exe / target.dll // target / target.so из исходных файлов с нативными функциями, то тут два варианта. Или запрещать такую сборку, или параллельно собирать файл с именем target.natives.dll // target.natives.so соответственно с реализациями нативных функций. Это спорный момент, его надо ещё обдумать.

@Mazdaywik
Copy link
Member Author

Создана задача #87, содержащая спецификацию, удовлетворяющую постановке задачи.

Рассмотрим каждую из комбинаций:

Префикс задан, рантайм среди единиц трансляции есть, нативный код есть.

Если используется srmake, то будет найден refalrts.rminfo, который ссылается на соответствующий префикс, если он совпадает с явно заданным — используется, не совпадает — ошибка. Нативный код попадает в filename.native.dll (или ….so, далее будут приводиться только имена с суффиксами dll и exe). Либо, в режиме --scratch, префикс не будет найден.

Если используется srefc, то не будет найден либо рантайм (в режимах --rich и --slim), либо префикс (в режиме --scratch).

При использовании core-утилит ответственность на конфигурации лежит на программисте. В худшем случае второй экземпляр рантайма будет находиться в filename.native.dll. Будет ли он там мешать, зависит от реализации этой самой filename.native.dll (хотя он там по-любому будет нужен).

Э-э-э. Фейл. Комбинация с filename.native.dll не работает. Нужно уточнять спецификацию — это будет сделано в первом комментарии к #87.

@Mazdaywik
Copy link
Member Author

Mazdaywik commented Mar 18, 2017

Задача #87 уточнена. Нездоровая комбинация запрещена.

Рассмотрим каждую из комбинаций:

1. Префикс задан, рантайм среди единиц трансляции есть, нативный код есть.

Ошибка трансляции во всех комбинациях

  • srmake + --rich или --slim — вызовет компилятор, который откажется собирать программу с нативным кодом и явно заданным префиксом. Проблем с рантаймом может и не быть — см. пункт 2.
  • srmake + --scratch — явно заданный префикс не найдётся.
  • srefc + --rich или --slim — не найдётся явно заданный рантайм.
  • srefc + --scratch — не найдётся явно заданный префикс.
  • srmake-core — вызовет srefc-core, который откажется собирать программу с префиксом и нативным кодом.
  • srefc-core — откажется собирать программу с префиксом и нативным кодом.

2. Префикс задан, рантайм среди единиц трансляции есть, нативного кода нет.

Программа может собраться.

  • srmake + --rich или --slim — refalrts.rminfo будет содержать ссылку на префикс. Если он совпадает с явно заданным, то всё srefc-core модуль рантайма не увидит и сможет корректно собрать программу. Иначе ошибка на уровне srmake-core.
  • srmake + --scratch — явно заданный префикс не найдётся.
  • srefc + --rich или --slim — не найдётся явно заданный рантайм.
  • srefc + --scratch — не найдётся явно заданный префикс.
  • srmake-core — тут уж как пользователь установит пути поиска. Или найдётся refalrts.rminfo, содержащий имя префикса — см. выше, или найдёт сам рантайм — тогда srefc-core откажется собирать программу с префиксом и нативным кодом (рантаймом).
  • srefc-core — откажется собирать программу с префиксом и нативным кодом (рантаймом).

2. Префикс задан, рантайма среди единиц трансляции нет, нативный код есть.

Ошибка трансляции во всех комбинациях

  • srmake + --rich или --slim — вызовет компилятор, который откажется собирать программу с нативным кодом и явно заданным префиксом.
  • srmake + --scratch — явно заданный префикс не найдётся.
  • srefc + --rich или --slim — откажется собирать программу с префиксом и нативным кодом.
  • srefc + --scratch — не найдётся явно заданный префикс.
  • srmake-core — вызовет srefc-core, который откажется собирать программу с префиксом и нативным кодом.
  • srefc-core — откажется собирать программу с префиксом и нативным кодом.

4. Префикс задан, рантайма среди единиц трансляции нет, нативного кода нет.

Штатная ситуация для srmake-core и srefc-core. Необычная ситуация для srmake и srefc.

  • srmake + --rich или --slim — если совпадает с дефолтовым для опции, то соберётся. Иначе ошибка на уровне srmake-core.
  • srmake + --scratch — явно заданный префикс не найдётся.
  • srefc + --rich или --slim —  если совпадает с дефолтовым для опции, то соберётся. Иначе ошибка на уровне srefc-core.
  • srefc + --scratch — не найдётся явно заданный префикс.
  • srmake-core — штатный сценарий использования.
  • srefc-core — штатный сценарий использования.

5. Префикс не задан, рантайм среди единиц трансляции есть, нативный код есть.

Штатное использование в режиме --scratch и для core-утилит

  • srmake + --rich или --slim — по ссылке на рантайм найдётся стандартный префикс, дальше компилятор откажется собирать программу с рантаймом и нативным кодом.
  • srmake + --scratch — штатное использование.
  • srefc + --rich или --slim — не найдётся явно заданный рантайм.
  • srefc + --scratch — штатное использование.
  • srmake-core — штатное использование.
  • srefc-core — штатное использование.

6. Префикс не задан, рантайм среди единиц трансляции есть, нативного кода нет.

Штатное использование в режиме --scratch и для core-утилит

  • srmake + --rich или --slim — по ссылке на рантайм найдётся стандартный префикс, дальше компиляция пойдёт естественным путём.
  • srmake + --scratch — штатное использование, рантайм найдётся по ссылкам.
  • srefc + --rich или --slim — явно заданный рантайм не найдётся, не соберётся без явно указанного префикса.
  • srefc + --scratch — штатное использование.
  • srmake-core — штатное использование.
  • srefc-core — штатное использование.

7. Префикс не задан, рантайма среди единиц трансляции нет, нативный код есть.

Штатное использование в режиме --scratch и для core-утилит

  • srmake + --rich или --slim — по ссылке на стандартные библиотеки найдётся стандартный префикс, дальше компилятор откажется собирать программу с рантаймом и нативным кодом. Если стандартные библиотеки не используются, то может собраться.
  • srmake + --scratch — штатное использование, рантайм найдётся по ссылкам (если найдётся)
  • srefc + --rich или --slim — не соберётся без явно указанного префикса.
  • srefc + --scratch — не соберётся без явно указанного рантайма.
  • srmake-core — штатное использование.
  • srefc-core — не соберётся без рантайма.

8. Префикс не задан, рантайма среди единиц трансляции нет, нативного кода нет.

Можно либо собрать модуль типа R, либо при помощи srmake, если рантайм или префикс доступны по ссылкам //FROM.

  • srmake + --rich или --slim — по ссылке на стандартные библиотеки найдётся стандартный префикс, к которому припишется RASL. Если стандартных библиотек нет, то собрать исполнимый файл не получится (можно будет собрать модуль типа R, используя ключи --makelib или --R).
  • srmake + --scratch — штатное использование, рантайм найдётся по ссылкам (если найдётся).
  • srefc + --rich или --slim — можно собрать только модуль типа R.
  • srefc + --scratch — можно собрать только модуль типа R.
  • srmake-core — если по ссылкам //FROM доступны префикс или рантайм, то можно создать любой модуль, иначе только модуль типа R.
  • srefc-core — можно собрать только модуль типа R.

Все перечисленные комбинации приемлемые и предсказуемые, странный битый .exe-шник собрать невозможно (по крайней мере, не очевидно как), странную битую .dll-ку или .so-шку создать можно, если собирается программа без префикса и рантайма (получится файл без основной точки входа).

Случаи, когда рантайм имеет имя, отличное от refalrts, тут не рассматривались — в таких ситуациях применимы только core-утилиты. Аналогично, когда разрабатывается специализированный префикс. Скрипты srefc и srmake такое иногда смогут собрать, но это нештатное их использование.

Задачу закрываю как выполненную.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant