Difference between revisions of "Добавление нового языкового процессора"

From EjudgeWiki
m (lang_ids.cfg)
 
(14 intermediate revisions by one other user not shown)
Line 1: Line 1:
Навигация: [[Main Page|Главная страница]]/[[Система ejudge]]/[[Расширение]]/[[Добавление нового языка программирования или компилятора]].
+
Навигация: [[Main Page|Главная страница]]/[[Система ejudge]]/[[Расширение]]/[[Добавление нового языкового процессора]].
  
 
Руководство по добавлению поддержки языков программирования, приведенное здесь, относится к системе ejudge версии не ниже 2.3.8.
 
Руководство по добавлению поддержки языков программирования, приведенное здесь, относится к системе ejudge версии не ниже 2.3.8.
  
Добавление поддержки нового языка программирования в систему ejudge выполняется в несколько шагов.
+
[[Языковой процессор]] (ЯП) — это либо компилятор, либо интерпретатор некоторого языка программирования.
# Определение параметров добавляемого языка
+
 
 +
Поскольку система ejudge поддерживает несколько вариантов одного и того же языка программирования (например, Free Pascal, Borland Kylix, и т. д.), правильнее говорить не о поддержке языков программирования, а о поддержке языковых процессоров.
 +
 
 +
Добавление поддержки нового ЯП в систему ejudge выполняется в несколько шагов.
 +
# Определение параметров добавляемого ЯП
 
# Написание настроечного скрипта (lang-version.in)
 
# Написание настроечного скрипта (lang-version.in)
 
# Написание скрипта компиляции (lang.in)
 
# Написание скрипта компиляции (lang.in)
# Переконфигурация поддерживаемых языков с помощью программы ejudge-configure-compilers
+
# Переконфигурация поддерживаемых ЯП с помощью программы ejudge-configure-compilers
 +
# Перезапуск системы ejudge
  
== Определение параметров языка программирования ==
+
== Определение параметров ЯП ==
  
Параметры языка программирования, необходимые для поддержки языка в системе ejudge, перечислены ниже:
+
Параметры ЯП, необходимые для его поддержки в системе ejudge, перечислены ниже:
  
 
{|
 
{|
 
| <tt>arch</tt>
 
| <tt>arch</tt>
| архитектура языка
+
| архитектура ЯП
 
|-
 
|-
 
| <tt>insecure</tt>
 
| <tt>insecure</tt>
Line 21: Line 26:
 
|-
 
|-
 
| <tt>short_name</tt>
 
| <tt>short_name</tt>
| краткое название языка (как правило, определяется автоматически)
+
| краткое название ЯП(как правило, определяется автоматически)
 
|-
 
|-
 
| <tt>long_name</tt>
 
| <tt>long_name</tt>
| полное название языка
+
| полное название ЯП
 
|-
 
|-
 
| <tt>src_sfx</tt>
 
| <tt>src_sfx</tt>
| стандартный суффикс файла с исходным текстом на данном языке программирования
+
| стандартный суффикс файла с исходным текстом для данного ЯП
 
|-
 
|-
 
| <tt>exe_sfx</tt>
 
| <tt>exe_sfx</tt>
| стандартный суффикс исполняемого файла на данном языке программирования
+
| стандартный суффикс исполняемого файла для данного ЯП
 
|-
 
|-
 
| <tt>version</tt>
 
| <tt>version</tt>
| версия компилятора или интерпретатора языка
+
| версия ЯП
 
|-
 
|-
 
| <tt>arg</tt>
 
| <tt>arg</tt>
| аргумент, указанный при конфигурировании языка программами ejudge-setup или ejudge-configure-compilers
+
| аргумент, указанный при конфигурировании ЯП программами ejudge-setup или ejudge-configure-compilers
 
|}
 
|}
  
Основной параметр языка программирования &mdash; это <i>архитектура</i> (<tt>arch</tt>). Под архитектурой понимается системное окружение, в котором запускается тестируемая программа. Система ejudge поддерживает следующие архитектуры:
+
Основной параметр ЯП &mdash; это <i>архитектура</i> (<tt>arch</tt>). Под архитектурой понимается системное окружение, в котором запускается тестируемая программа. Система ejudge поддерживает следующие архитектуры:
 
* [[arch:linux|linux]] &mdash; статически скомпонованная исполняемая программа
 
* [[arch:linux|linux]] &mdash; статически скомпонованная исполняемая программа
 
* [[arch:linux-shared|linux-shared]] &mdash; динамически скомпонованная исполняемая программа (в том числе и скрипты)
 
* [[arch:linux-shared|linux-shared]] &mdash; динамически скомпонованная исполняемая программа (в том числе и скрипты)
Line 46: Line 51:
 
* [[arch:dos|dos]] &mdash; приложения DOS
 
* [[arch:dos|dos]] &mdash; приложения DOS
  
Архитектура linux является архитектурой по умолчанию. Если язык имеет архитектуру linux, то параметр <tt>arch</tt> для этого языка должен либо отсутствовать, либо иметь пустое значение.
+
Архитектура linux является архитектурой по умолчанию. Если ЯП имеет архитектуру linux, то параметр <tt>arch</tt> для этого ЯП должен либо отсутствовать, либо иметь пустое значение.
  
Второй параметр языка &mdash; это флаг, корректно ли работает
+
Второй параметр ЯП &mdash; это флаг, корректно ли работает
тестируемая программа на данном языке при запуске в [[безопасный режим|безопасном режиме]]. Если язык имеет архитектуру linux, java или dos, то тестируемые программы на таком языке, как правило, корректно работают в безопасном режиме, при этом поддерживаются
+
тестируемая программа для данного ЯП при запуске в [[безопасный режим|безопасном режиме]]. Если ЯП имеет архитектуру linux, java или dos, то тестируемые программы для такого ЯП, как правило, корректно работают в безопасном режиме, при этом поддерживаются
все ограничения безопасности. Если язык имеет архитектуру msil, то безопасный режим для него не поддерживаются. Приложения на таком языке могут тестироваться, но при этом никаких ограничений безопасности на работу приложения накладываться не будет. Если язык имеет архитектуру linux-shared, то безопасный режим для такого языка поддерживается, однако тестируемая программа в безопасном режиме может работать некорректно или не работать вообще.
+
все ограничения безопасности. Если ЯП имеет архитектуру msil, то безопасный режим для него не поддерживаются. Программы для такого ЯП могут тестироваться, но при этом никаких ограничений безопасности на работу программы накладываться не будет. Если ЯП имеет архитектуру linux-shared, то безопасный режим для такого ЯП поддерживается, однако тестируемая программа в безопасном режиме может работать некорректно или не работать вообще.
  
 
В любом случае, если есть сомнения в работоспособности программы в безопасном режиме, требуется проверка на простых программах, как работающих со стандартными потоками, так и работающих с файлами.
 
В любом случае, если есть сомнения в работоспособности программы в безопасном режиме, требуется проверка на простых программах, как работающих со стандартными потоками, так и работающих с файлами.
  
Если добавляемый язык программирования не поддерживает безопасный режим, то параметр языка <tt>insecure</tt> должен быть равен 1.
+
Если добавляемый ЯП не поддерживает безопасный режим, то параметр ЯП <tt>insecure</tt> должен быть равен 1.
 
Если безопасный режим поддерживается, то параметр должен отсутствовать или иметь пустое значение.
 
Если безопасный режим поддерживается, то параметр должен отсутствовать или иметь пустое значение.
  
Из языков программирования, поддерживаемых системой ejudge в стандартной поставке в версии 2.3.8, небезопасными являются языки [[lang:gcj|gcj]] (GNU Java), [[lang:gfortran|gfortran]] (GNU Fortran), [[lang:mcs|mcs]] (Mono C#), [[lang:mzscheme|mzscheme]] (MzScheme), [[lang:php|php]] (PHP), [[lang:vbnc|vbnc]] (Mono Visual Basic), [[lang:yabasic|yabasic]] (YaBasic).
+
Из ЯП поддерживаемых системой ejudge в стандартной поставке в версии 2.3.8, небезопасными являются ЯП [[lang:gcj|gcj]] (GNU Java), [[lang:gfortran|gfortran]] (GNU Fortran), [[lang:mcs|mcs]] (Mono C#), [[lang:mzscheme|mzscheme]] (MzScheme), [[lang:php|php]] (PHP), [[lang:vbnc|vbnc]] (Mono Visual Basic), [[lang:yabasic|yabasic]] (YaBasic).
  
Параметр <tt>short_name</tt> &mdash; это краткое название языка программирования. Краткое название используется в таблице посылок пользователей и ряде других мест. Краткое название языка &mdash; это, по сути, идентификатор языка. Он должен представлять собой одно слово, не длинее 32 знаков, состоящее из заглавных и строчных латинских букв, цифр и знаков +, -, _. Как правило, краткое название языка программирования определяется автоматически из имени скрипта компиляции и настройки. Например, если скрипт компиляции (точнее, шаблон скрипта компиляции) имеет имя <tt>foo.in</tt>, то по умолчанию кратное название языка будет равно <tt>foo</tt>.
+
Параметр <tt>short_name</tt> &mdash; это краткое название ЯП. Краткое название используется в таблице посылок пользователей и ряде других мест. Краткое название ЯП &mdash; это, по сути, идентификатор ЯП. Он должен представлять собой одно слово, не длинее 32 знаков, состоящее из заглавных и строчных латинских букв, цифр и знаков +, -, _. Как правило, краткое название ЯП определяется автоматически из имени скрипта компиляции и настройки. Например, если скрипт компиляции (точнее, шаблон скрипта компиляции) имеет имя <tt>foo.in</tt>, то по умолчанию кратное название ЯП будет равно <tt>foo</tt>.
 
Обратите внимание, что в unix-системах имена файлов чувствительны к регистру букв. Значение параметра <tt>short_name</tt> также чувствительно к регистру букв.
 
Обратите внимание, что в unix-системах имена файлов чувствительны к регистру букв. Значение параметра <tt>short_name</tt> также чувствительно к регистру букв.
  
Параметр <tt>long_name</tt> &mdash; это развернутое (полное) название языка программирования. Например, краткое имя языка может быть <tt>foo</tt>, а полное &mdash; &quot;GNU Foo Interpreter&quot;. Обратите внимание, что в полное название языка программирования не входит версия компилятора или интерпретатора этого языка программирования.
+
Параметр <tt>long_name</tt> &mdash; это развернутое (полное) название ЯП. Например, краткое имя ЯП может быть <tt>foo</tt>, а полное &mdash; &quot;GNU Foo Interpreter&quot;. Обратите внимание, что в полное название ЯП не входит номер версии.
  
Параметр <tt>src_sfx</tt> &mdash; это стандартный суффикс исходных файлов на данном языке программирования. Например, если для языка GNU Foo исходные файлы называются <tt>file.foo</tt>, то суффиксом исходных файлов будет строка <tt>.foo</tt> (обратите внимание, что &quot;точка&quot; входит в суффикс).
+
Параметр <tt>src_sfx</tt> &mdash; это стандартный суффикс исходных файлов для данного ЯП. Например, если для ЯП GNU Foo исходные файлы называются <tt>file.foo</tt>, то суффиксом исходных файлов будет строка <tt>.foo</tt> (обратите внимание, что &quot;точка&quot; входит в суффикс).
  
Параметр <tt>exe_sfx</tt> определяет стандартный суффикс для исполняемых файлов на данном языке программирования. Как правило, суффикс исполняемых файлов зависит от архитектуры языка. Так, для архитектур linux и linux-shared стандартный суффикс исполняемых файлов не требуется, поэтому параметр <tt>exe_sfx</tt> может быть опущен или иметь пустое значение. Для архитектур dos и msil стандартный суффикс исполняемых файлов &mdash; <tt>.exe</tt>, а для архитектуры java &mdash; <tt>.jar</tt>.
+
Параметр <tt>exe_sfx</tt> определяет стандартный суффикс для исполняемых файлов для данного ЯП. Как правило, суффикс исполняемых файлов зависит от архитектуры ЯП. Так, для архитектур linux и linux-shared стандартный суффикс исполняемых файлов не требуется, поэтому параметр <tt>exe_sfx</tt> может быть опущен или иметь пустое значение. Для архитектур dos и msil стандартный суффикс исполняемых файлов &mdash; <tt>.exe</tt>, а для архитектуры java &mdash; <tt>.jar</tt>.
  
Параметры <tt>arch</tt>, <tt>insecure</tt>, <tt>short_name</tt>, <tt>long_name</tt>, <tt>src_sfx</tt>, <tt>exe_sfx</tt> описывают свойства собственно языка программирования, точнее соответствующего компилятора или интерпретатора, поэтому для данного языка программирования не меняются от инсталляции к инсталляции системы ejudge.
+
Параметры <tt>arch</tt>, <tt>insecure</tt>, <tt>short_name</tt>, <tt>long_name</tt>, <tt>src_sfx</tt>, <tt>exe_sfx</tt> описывают свойства собственно ЯП, поэтому для данного ЯП не меняются от инсталляции к инсталляции системы ejudge.
  
Параметры <tt>version</tt> и <tt>arg</tt> описывают свойства инсталляции данного языка в конкретной системе, поэтому их значения могут меняться от инсталляции к инсталляции.
+
Параметры <tt>version</tt> и <tt>arg</tt> описывают свойства инсталляции данного ЯП в конкретной системе, поэтому их значения могут меняться от инсталляции к инсталляции.
  
Параметр <tt>version</tt> определяет версию компилятора или интерпретатора. Если значение этого параметра пусто, то считается, что соответствующий компилятор или интерпретатор не был обнаружен в системе. Поэтому значение этого параметра не должно быть пустым. Версия компилятора (интерпретатора) определяется настроечным скриптом, как правило, с помощью запуска компилятора (интерпретатора) со специальными опциями и обработки полученного вывода.
+
Параметр <tt>version</tt> определяет версию ЯП. Если значение этого параметра пусто, то считается, что соответствующий ЯП не был обнаружен в системе. Поэтому значение этого параметра не должно быть пустым. Версия ЯП определяется настроечным скриптом, как правило, с помощью запуска ЯП со специальными опциями и обработки полученного вывода.
  
Параметр <tt>arg</tt> содержит аргумент конфигурации языка, переданный в скрипты настройки ejudge-setup или ejudge-configure-compilers. Например, если запустить программу ejudge-configure-compilers с опцией --with-foo=/usr/local/bin/foo, то параметр /usr/local/bin/foo будет передан скрипту конфигурации языка foo-version. Кроме того, этот параметр может быть установлен и в интерактивном режиме в программах ejudge-setup и ejudge-configure-compilers. Как правило, этот параметр задает путь к компилятору или интерпретатору соответствующего языка, и полезен в случаях, когда компилятор (интерпретатор) размещается в нестандартных местах.
+
Параметр <tt>arg</tt> содержит аргумент конфигурации ЯП, переданный в скрипты настройки ejudge-setup или ejudge-configure-compilers. Например, если запустить программу ejudge-configure-compilers с опцией --with-foo=/usr/local/bin/foo, то параметр /usr/local/bin/foo будет передан скрипту конфигурации ЯП foo-version. Кроме того, этот параметр может быть установлен и в интерактивном режиме в программах ejudge-setup и ejudge-configure-compilers. Как правило, этот параметр задает путь к ЯП в файловой системе, и полезен в случаях, когда ЯП размещается в нестандартных местах.
  
== Структура файлов для поддержки языка программирования ==
+
== Структура файлов для поддержки ЯП ==
  
 
Предположим, что система ejudge проинсталлирована в каталог /opt/ejudge, а каталог для данных установлен в /home/ejudge.
 
Предположим, что система ejudge проинсталлирована в каталог /opt/ejudge, а каталог для данных установлен в /home/ejudge.
Line 84: Line 89:
  
 
Файл /home/ejudge/compile/conf/compile.cfg &mdash; основной конфигурационный файл сервера компиляции [[compile]]. В файле
 
Файл /home/ejudge/compile/conf/compile.cfg &mdash; основной конфигурационный файл сервера компиляции [[compile]]. В файле
содержится информация, необходимая для компиляции для всех поддерживаемых в данной инсталляции языков программирования.
+
содержится информация, необходимая для компиляции для всех поддерживаемых в данной инсталляции ЯП.
Например, для языка foo секция описания языка может выглядить следующим образом:
+
Например, для ЯП foo секция описания ЯП может выглядить следующим образом:
 
  [language]
 
  [language]
 
  id = 99
 
  id = 99
Line 92: Line 97:
 
  src_sfx = ".foo"
 
  src_sfx = ".foo"
 
  cmd = "foo"
 
  cmd = "foo"
Здесь <tt>id</tt> &mdash; это числовой идентификатор языка, уникальный для всех языков в данной инсталляции. Остальная информация о языке берется из параметров языка, описанных в предыдущем разделе.
+
Здесь <tt>id</tt> &mdash; это числовой идентификатор ЯП, уникальный для всех ЯП в данной инсталляции. Остальная информация о ЯП берется из параметров ЯП, описанных в предыдущем разделе.
  
 
Файл /home/ejudge/compile/conf/compile.cfg автоматически записывается при каждом вызове программы ejudge-configure-compilers. Все изменения, внесенные в него вручную, теряются при каждом запуске ejudge-configure-compilers.
 
Файл /home/ejudge/compile/conf/compile.cfg автоматически записывается при каждом вызове программы ejudge-configure-compilers. Все изменения, внесенные в него вручную, теряются при каждом запуске ejudge-configure-compilers.
  
Версия компилятора и флаг, что соответствующий компилятор в системе обнаружен, не содержатся в этом конфигурационном файле, а считываются непосредственно из конфигурационного файла языка программировая при каждом запуске программы compile.
+
Версия ЯП и флаг, что соответствующий ЯП в системе обнаружен, не содержатся в этом конфигурационном файле, а считываются непосредственно из конфигурационного файла ЯП при каждом запуске программы compile.
  
 
=== lang_ids.cfg ===
 
=== lang_ids.cfg ===
  
Идентификаторы <tt>id</tt> языков программирования языков, поддерживаемых в стандартной поставке, хранятся в файле
+
Идентификаторы <tt>id</tt> ЯП, поддерживаемых в стандартной поставке, хранятся в файле
/opt/ejudge/libexec/ejudge/lang/lang_ids.cfg. Если информация о новом языке программирования в этом файле отсутствует, его идентификатор назначается автоматически: берется первый еще не использованный в файле compile.cfg. Пользователь может
+
${prefix}/libexec/ejudge/lang/lang_ids.cfg. Если информация о новом ЯП в этом файле отсутствует, его идентификатор назначается автоматически: берется первый еще не использованный в файле compile.cfg. Пользователь может
скопировать файл lang_ids.cfg в каталог /home/ejudge/compile/scripts и вносить в него произвольные изменения. Модифицировать файл /opt/ejudge/libexec/ejudge/lang/lang_ids.cfg не рекомендуется, так как он будет перезаписан при обновлении системы.
+
скопировать файл lang_ids.cfg в каталог ${prefix}/compile/scripts и вносить в него произвольные изменения. Модифицировать файл ${prefix}/libexec/ejudge/lang/lang_ids.cfg не рекомендуется, так как он будет перезаписан при обновлении системы.
  
 
=== Каталог lang.d ===
 
=== Каталог lang.d ===
  
Каталог /home/ejudge/compile/conf/lang.d содержит файлы конфигурационных настроек всех поддерживаемых системой ejudge языков программирования. Для языка foo конфигурационный файл называется <tt>foo.cfg</tt>. Его содержимое может быть примерно таким:
+
Каталог /home/ejudge/compile/conf/lang.d содержит файлы конфигурационных настроек всех поддерживаемых системой ejudge ЯП. Для ЯП foo конфигурационный файл называется <tt>foo.cfg</tt>. Его содержимое может быть примерно таким:
 
  version="3.14"
 
  version="3.14"
 
  arg="/usr/local/bin/foo"
 
  arg="/usr/local/bin/foo"
Line 116: Line 121:
 
Файл записывается в синтаксисе /bin/sh. Этот файл используется как программами системы ejudge, такими как compile, super-serve, так и непосредственно скриптами foo и foo-version. Он генерируется скриптом foo-version, запускаемым в специальном режиме.
 
Файл записывается в синтаксисе /bin/sh. Этот файл используется как программами системы ejudge, такими как compile, super-serve, так и непосредственно скриптами foo и foo-version. Он генерируется скриптом foo-version, запускаемым в специальном режиме.
  
Помимо параметров языка, описанных выше, файл может содержать определения произвольных переменных, необходимых для работы скриптов foo или foo-version. На примере выше это переменная <tt>FOOPATH</tt>.
+
Помимо параметров ЯП, описанных выше, файл может содержать определения произвольных переменных, необходимых для работы скриптов foo или foo-version. На примере выше это переменная <tt>FOOPATH</tt>.
  
 
=== Каталог in ===
 
=== Каталог in ===
  
В каталоге in находятся заготовки для скриптов конфигурации и компиляции языков программирования. В каталоге /opt/ejudge/libexec/ejudge/lang/in находятся заготовки скриптов для языков, поддерживаемых в стандартной поставке системы ejudge. В каталоге /home/ejudge/compile/scripts/in находятся заготовки скриптов пользователя. Последний каталог более приоритетен, то есть если заготовка скрипта обнаружена в каталоге /home/ejudge/compile/scripts/in, системный каталог проверяться не будет. Поэтому, если необходимо модифицировать поставляемый скрипт, его нужно предварительно скопировать в этот каталог, затем модифицировать. Модифицировать файлы непосредственно в каталоге /opt/ejudge/libexec/ejudge/lang/in не рекомендуется, так как эти файлы перезаписываются при обновлении системы ejudge.
+
В каталоге in находятся заготовки для скриптов конфигурации и компиляции ЯП. В каталоге /opt/ejudge/libexec/ejudge/lang/in находятся заготовки скриптов для ЯП, поддерживаемых в стандартной поставке системы ejudge. В каталоге /home/ejudge/compile/scripts/in находятся заготовки скриптов пользователя. Последний каталог более приоритетен, то есть если заготовка скрипта обнаружена в каталоге /home/ejudge/compile/scripts/in, системный каталог проверяться не будет. Поэтому, если необходимо модифицировать поставляемый скрипт, его нужно предварительно скопировать в этот каталог, затем модифицировать. Модифицировать файлы непосредственно в каталоге /opt/ejudge/libexec/ejudge/lang/in не рекомендуется, так как эти файлы перезаписываются при обновлении системы ejudge.
  
 
=== Каталог scripts ===
 
=== Каталог scripts ===
Line 128: Line 133:
 
=== Заготовки скриптов ===
 
=== Заготовки скриптов ===
  
Для языка foo должны быть написаны заготовки скриптов foo.in и foo-version.in. Заготовки скриптов должны быть помещены в каталог /home/ejudge/compile/scripts/in. Заготовки скриптов по смыслу соответствуют заготовкам файлов Makefile.in, config.h.in в системе GNU autotools. То есть в заготовках скриптов выполняется замена переменных вида <tt>@var@</tt> на их значения.
+
Для ЯП foo должны быть написаны заготовки скриптов foo.in и foo-version.in. Заготовки скриптов должны быть помещены в каталог /home/ejudge/compile/scripts/in. Заготовки скриптов по смыслу соответствуют заготовкам файлов Makefile.in, config.h.in в системе GNU autotools. То есть в заготовках скриптов выполняется замена переменных вида <tt>@var@</tt> на их значения.
  
 
Поддерживаемые подстановки перечислены в таблице
 
Поддерживаемые подстановки перечислены в таблице
Line 171: Line 176:
  
 
  foo-version [-v] -r [ARG]
 
  foo-version [-v] -r [ARG]
 +
 +
В режиме конфигурирования должна быть проверена поддержка ЯП в данной инсталляции. На стандартный поток вывода должно быть напечатано новое содержимое конфигурационного файла ЯП foo.cfg. Кроме того, если указана опция -v, на стандартный поток ошибок должна быть напечатана дополнительная информация о процессе конфигурирования. При успешном конфигурировании код завершения должен быть равен 0, а при неудаче &mdash; 1. В параметре <tt>ARG</tt> передается путь, который указал пользователь в опции <tt>--with-foo=ARG</tt> при конфигурировании в пакетном режиме, либо путь, введенный им при конфигурировании в диалоговом режиме.
 +
 +
Так, если ЯП foo поддерживается в данной инсталляции, сценарий запуска может быть следующим:
 +
 +
bash$ foo-version -v -r /usr/local/bin/foo
 +
version="3.14"
 +
arg="/usr/local/bin/foo"
 +
long_name="GNU Foo Interpreter"
 +
src_sfx=".foo"
 +
arch="linux-shared"
 +
FOOPATH="/usr/local/bin/foo"
 +
checking whether GNU Foo is available... yes, /usr/local/bin/foo, 3.14
 +
bash$
 +
 +
Последняя строка (checking...) выводится на стандартный поток ошибок.
 +
 +
Если ЯП foo не поддерживается в данной инсталляции, сценарий запуска может быть следующим:
 +
 +
bash$ foo-version -v -r
 +
version=
 +
arg=
 +
long_name="GNU Foo Interpreter"
 +
src_sfx=".foo"
 +
arch="linux-shared"
 +
FOOPATH="/bin/false"
 +
checking whether GNU Foo is available... no
 +
bash$
 +
 +
Последняя строка (checking...) выводится на стандартный поток ошибок.
  
 
==== -l &mdash; режим получения списка ====
 
==== -l &mdash; режим получения списка ====
Line 176: Line 211:
 
  foo-version -l
 
  foo-version -l
  
==== -p &mdash; печать командной строки компилятора ====
+
В режиме получения списков ЯП на стандартный поток вывода должна быть напечатана строка информации о ЯП.
 +
Строка информации печатается независимо от того, поддерживается ли данный ЯП в данной инсталляции.
 +
Код завершения всегда должен быть равен 0.
 +
 
 +
Так, для ЯП foo сценарий запуска может быть следующим:
 +
 
 +
bash$ foo-version -l
 +
GNU Foo Interpreter [http://gnufoo.org]
 +
bash$
 +
 
 +
Режим получения списка ЯП используется программой ejudge-configure-compilers при запуске ее с опцией --list.
 +
 
 +
==== -p &mdash; печать пути к ЯП ====
  
 
  foo-version -p
 
  foo-version -p
 +
 +
В режиме печати пути к ЯП на стандартный поток вывода должен быть напечатан путь к ЯП. Код завершения должен быть равен 0. Если ЯП не поддерживается в данной инсталляции, вывод должен быть пуст, а код завершения равен 1. В этом случае на стандартный поток ошибок может выводиться диагностическое сообщение.
 +
 +
Так, если ЯП foo поддерживается в данной инсталляции, сценарий запуска может быть следующим:
 +
 +
bash$ foo-version -p
 +
/usr/local/bin/foo
 +
bash$
 +
 +
Режим печати используется программой super-serve в некоторых специальных случаях.
  
 
==== -f &mdash; печать полного имени и версии ====
 
==== -f &mdash; печать полного имени и версии ====
  
 
  foo-version -f
 
  foo-version -f
 +
 +
В режиме печати полного названия ЯП на стандартный поток вывода должно быть напечатано полное имя ЯП и номер версии ЯП. В случае, если ЯП не поддерживается на данной системе (в данной инсталляции), стандартный поток вывода должен быть пуст, а код возврата равен 1. На стандартный поток ошибок при этом может выводиться диагностическое сообщение.
 +
 +
Так, если ЯП foo поддерживается в данной инсталляции, сценарий запуска может быть следующим:
 +
 +
bash$ foo-version -f
 +
GNU Foo Interpreter 3.14
 +
bash$
 +
 +
Если ЯП foo не поддерживается, то следующим:
 +
 +
bash$ foo-version -f
 +
This language is not supported.
 +
bash$
 +
 +
в этом случае сообщение выводится на стандартный поток ошибок.
 +
 +
Режим печати версии используется программой super-serve в процессе настройки ЯП при редактировании турнира.
  
 
==== печать версии ====
 
==== печать версии ====
  
 
  foo-version
 
  foo-version
 +
 +
В режиме печати версий, который задаётся запуском скрипта без параметров, на стандартный поток вывода должен быть напечатан номер версии ЯП. В случае, если ЯП не поддерживается на данной системе (в данной инсталляции), стандартный поток вывода должен быть пуст, а код возврата равен 1. На стандартный поток ошибок при этом может выводиться диагностическое сообщение.
 +
 +
Так, если ЯП foo поддерживается в данной инсталляции, сценарий запуска может быть следующим:
 +
 +
bash$ foo-version
 +
3.14
 +
bash$
 +
 +
Если ЯП foo не поддерживается, то следующим:
 +
 +
bash$ foo-version
 +
This language is not supported.
 +
bash$
 +
 +
в этом случае сообщение выводится на стандартный поток ошибок.
 +
 +
Режим печати версии используется программой super-serve в процессе настройки ЯП при редактировании турнира.
 +
 +
=== Реализация ===
 +
 +
Рассмотрим реализацию скрипта конфигурирования ЯП foo [[foo-version.in]]. За образец для этого (гипотетического) скрипта взят скрипт для конфигурирования ЯП Ruby.
  
 
== Скрипт компиляции ==
 
== Скрипт компиляции ==
 +
 +
Скрипт компиляции принимает в качестве параметров имя файла с исходным текстом программы для ЯП и имя файла результата.
 +
Задача скрипта компиляции &mdash; получить на выходе файл, готовый к запуску в окружении, задаваемом архитектурой языка.
 +
 +
Для компилируемых языков результатом работы скрипта компиляции является бинарный исполняемый файл. Для интерпретируемых языков результатом работы скрипта компиляции является скрипт, готовый к запуску. Как правило, для интерпретируемых языков для этого достаточно записать в начало файла конструкцию
 +
#! INTERP-PATH ARGS
 +
и установить бит <tt>x</tt> разрешения выполнения файла. Здесь INTERP-PATH &mdash; это полный путь к интерпретатору соответствующего языка.
 +
 +
Далее скрипт компиляции рассматривается на примере гипотетического интерпретируемого языка foo.
 +
 +
=== Интерфейс ===
 +
 +
Интерфейс скрипта компиляции очень простой
 +
 +
foo SRC-FILE DST-FILE
 +
 +
Здесь SRC-FILE &mdash; имя входного файла, DST-FILE &mdash; имя выходного файла. Система ejudge формирует имена входного и выходного файлов с использованием суффиксов исходного файла и файла результата, как указано в конфигурационном файле ЯП. Таким образом, никакой дополнительной обработки имен входного и выходного файла выполнять не требуется.
 +
 +
Дополнительно в переменной окружения EJUDGE_FLAGS могут задаваться флаги для ЯП. Администратор турнира имеет возможность устанавливать флаги при редактировании турнира. Поэтому скрипт компиляции должен поддерживать задание дополнительных опций с помощью еременной окружения EJUDGE_FLAGS.
 +
 +
=== Реализация ===
 +
 +
Пример реализации скрипта компиляции [[foo.in]]. За образец для этого (гипотетического) скрипта взят скрипт для компиляции ЯП Ruby.
 +
 +
== Переконфигурация поддерживаемых ЯП ==
 +
 +
После того, как скрипты foo-version.in и foo.in помещены в каталог /home/ejudge/compile/scripts/in достаточно запустить программу ejudge-configure-compilers. Если скрипты написаны правильно, версия ЯП должна быть определена корректно, после чего язык готов к использованию.
 +
 +
В турнир язык может быть добавлен при редактировании настроек турнира с помощью CGI-программы [[serve-control]].
 +
 +
== Перезапуск ejudge ==
 +
 +
После выполнения всех шагов не забудьте перезапустить ejudge, чтобы сервер компиляции compile считал новый конфигурационный файл.

Latest revision as of 15:32, 29 March 2014

Навигация: Главная страница/Система ejudge/Расширение/Добавление нового языкового процессора.

Руководство по добавлению поддержки языков программирования, приведенное здесь, относится к системе ejudge версии не ниже 2.3.8.

Языковой процессор (ЯП) — это либо компилятор, либо интерпретатор некоторого языка программирования.

Поскольку система ejudge поддерживает несколько вариантов одного и того же языка программирования (например, Free Pascal, Borland Kylix, и т. д.), правильнее говорить не о поддержке языков программирования, а о поддержке языковых процессоров.

Добавление поддержки нового ЯП в систему ejudge выполняется в несколько шагов.

  1. Определение параметров добавляемого ЯП
  2. Написание настроечного скрипта (lang-version.in)
  3. Написание скрипта компиляции (lang.in)
  4. Переконфигурация поддерживаемых ЯП с помощью программы ejudge-configure-compilers
  5. Перезапуск системы ejudge

Определение параметров ЯП

Параметры ЯП, необходимые для его поддержки в системе ejudge, перечислены ниже:

arch архитектура ЯП
insecure флаг поддержки безопасного режима
short_name краткое название ЯП(как правило, определяется автоматически)
long_name полное название ЯП
src_sfx стандартный суффикс файла с исходным текстом для данного ЯП
exe_sfx стандартный суффикс исполняемого файла для данного ЯП
version версия ЯП
arg аргумент, указанный при конфигурировании ЯП программами ejudge-setup или ejudge-configure-compilers

Основной параметр ЯП — это архитектура (arch). Под архитектурой понимается системное окружение, в котором запускается тестируемая программа. Система ejudge поддерживает следующие архитектуры:

  • linux — статически скомпонованная исполняемая программа
  • linux-shared — динамически скомпонованная исполняемая программа (в том числе и скрипты)
  • java — байт-код java
  • msil — байт-код .NET
  • dos — приложения DOS

Архитектура linux является архитектурой по умолчанию. Если ЯП имеет архитектуру linux, то параметр arch для этого ЯП должен либо отсутствовать, либо иметь пустое значение.

Второй параметр ЯП — это флаг, корректно ли работает тестируемая программа для данного ЯП при запуске в безопасном режиме. Если ЯП имеет архитектуру linux, java или dos, то тестируемые программы для такого ЯП, как правило, корректно работают в безопасном режиме, при этом поддерживаются все ограничения безопасности. Если ЯП имеет архитектуру msil, то безопасный режим для него не поддерживаются. Программы для такого ЯП могут тестироваться, но при этом никаких ограничений безопасности на работу программы накладываться не будет. Если ЯП имеет архитектуру linux-shared, то безопасный режим для такого ЯП поддерживается, однако тестируемая программа в безопасном режиме может работать некорректно или не работать вообще.

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

Если добавляемый ЯП не поддерживает безопасный режим, то параметр ЯП insecure должен быть равен 1. Если безопасный режим поддерживается, то параметр должен отсутствовать или иметь пустое значение.

Из ЯП поддерживаемых системой ejudge в стандартной поставке в версии 2.3.8, небезопасными являются ЯП gcj (GNU Java), gfortran (GNU Fortran), mcs (Mono C#), mzscheme (MzScheme), php (PHP), vbnc (Mono Visual Basic), yabasic (YaBasic).

Параметр short_name — это краткое название ЯП. Краткое название используется в таблице посылок пользователей и ряде других мест. Краткое название ЯП — это, по сути, идентификатор ЯП. Он должен представлять собой одно слово, не длинее 32 знаков, состоящее из заглавных и строчных латинских букв, цифр и знаков +, -, _. Как правило, краткое название ЯП определяется автоматически из имени скрипта компиляции и настройки. Например, если скрипт компиляции (точнее, шаблон скрипта компиляции) имеет имя foo.in, то по умолчанию кратное название ЯП будет равно foo. Обратите внимание, что в unix-системах имена файлов чувствительны к регистру букв. Значение параметра short_name также чувствительно к регистру букв.

Параметр long_name — это развернутое (полное) название ЯП. Например, краткое имя ЯП может быть foo, а полное — "GNU Foo Interpreter". Обратите внимание, что в полное название ЯП не входит номер версии.

Параметр src_sfx — это стандартный суффикс исходных файлов для данного ЯП. Например, если для ЯП GNU Foo исходные файлы называются file.foo, то суффиксом исходных файлов будет строка .foo (обратите внимание, что "точка" входит в суффикс).

Параметр exe_sfx определяет стандартный суффикс для исполняемых файлов для данного ЯП. Как правило, суффикс исполняемых файлов зависит от архитектуры ЯП. Так, для архитектур linux и linux-shared стандартный суффикс исполняемых файлов не требуется, поэтому параметр exe_sfx может быть опущен или иметь пустое значение. Для архитектур dos и msil стандартный суффикс исполняемых файлов — .exe, а для архитектуры java — .jar.

Параметры arch, insecure, short_name, long_name, src_sfx, exe_sfx описывают свойства собственно ЯП, поэтому для данного ЯП не меняются от инсталляции к инсталляции системы ejudge.

Параметры version и arg описывают свойства инсталляции данного ЯП в конкретной системе, поэтому их значения могут меняться от инсталляции к инсталляции.

Параметр version определяет версию ЯП. Если значение этого параметра пусто, то считается, что соответствующий ЯП не был обнаружен в системе. Поэтому значение этого параметра не должно быть пустым. Версия ЯП определяется настроечным скриптом, как правило, с помощью запуска ЯП со специальными опциями и обработки полученного вывода.

Параметр arg содержит аргумент конфигурации ЯП, переданный в скрипты настройки ejudge-setup или ejudge-configure-compilers. Например, если запустить программу ejudge-configure-compilers с опцией --with-foo=/usr/local/bin/foo, то параметр /usr/local/bin/foo будет передан скрипту конфигурации ЯП foo-version. Кроме того, этот параметр может быть установлен и в интерактивном режиме в программах ejudge-setup и ejudge-configure-compilers. Как правило, этот параметр задает путь к ЯП в файловой системе, и полезен в случаях, когда ЯП размещается в нестандартных местах.

Структура файлов для поддержки ЯП

Предположим, что система ejudge проинсталлирована в каталог /opt/ejudge, а каталог для данных установлен в /home/ejudge. Тогда в каталоге /home/ejudge/compile размещаются конфигурационные файлы и скрипты для сервера компиляции программ.

compile.cfg

Файл /home/ejudge/compile/conf/compile.cfg — основной конфигурационный файл сервера компиляции compile. В файле содержится информация, необходимая для компиляции для всех поддерживаемых в данной инсталляции ЯП. Например, для ЯП foo секция описания ЯП может выглядить следующим образом:

[language]
id = 99
short_name = "foo"
long_name = "GNU Foo Interpreter"
src_sfx = ".foo"
cmd = "foo"

Здесь id — это числовой идентификатор ЯП, уникальный для всех ЯП в данной инсталляции. Остальная информация о ЯП берется из параметров ЯП, описанных в предыдущем разделе.

Файл /home/ejudge/compile/conf/compile.cfg автоматически записывается при каждом вызове программы ejudge-configure-compilers. Все изменения, внесенные в него вручную, теряются при каждом запуске ejudge-configure-compilers.

Версия ЯП и флаг, что соответствующий ЯП в системе обнаружен, не содержатся в этом конфигурационном файле, а считываются непосредственно из конфигурационного файла ЯП при каждом запуске программы compile.

lang_ids.cfg

Идентификаторы id ЯП, поддерживаемых в стандартной поставке, хранятся в файле ${prefix}/libexec/ejudge/lang/lang_ids.cfg. Если информация о новом ЯП в этом файле отсутствует, его идентификатор назначается автоматически: берется первый еще не использованный в файле compile.cfg. Пользователь может скопировать файл lang_ids.cfg в каталог ${prefix}/compile/scripts и вносить в него произвольные изменения. Модифицировать файл ${prefix}/libexec/ejudge/lang/lang_ids.cfg не рекомендуется, так как он будет перезаписан при обновлении системы.

Каталог lang.d

Каталог /home/ejudge/compile/conf/lang.d содержит файлы конфигурационных настроек всех поддерживаемых системой ejudge ЯП. Для ЯП foo конфигурационный файл называется foo.cfg. Его содержимое может быть примерно таким:

version="3.14"
arg="/usr/local/bin/foo"
long_name="GNU Foo Interpreter"
src_sfx=".foo"
arch="linux-shared"
FOOPATH="/usr/local/bin/foo"

Файл записывается в синтаксисе /bin/sh. Этот файл используется как программами системы ejudge, такими как compile, super-serve, так и непосредственно скриптами foo и foo-version. Он генерируется скриптом foo-version, запускаемым в специальном режиме.

Помимо параметров ЯП, описанных выше, файл может содержать определения произвольных переменных, необходимых для работы скриптов foo или foo-version. На примере выше это переменная FOOPATH.

Каталог in

В каталоге in находятся заготовки для скриптов конфигурации и компиляции ЯП. В каталоге /opt/ejudge/libexec/ejudge/lang/in находятся заготовки скриптов для ЯП, поддерживаемых в стандартной поставке системы ejudge. В каталоге /home/ejudge/compile/scripts/in находятся заготовки скриптов пользователя. Последний каталог более приоритетен, то есть если заготовка скрипта обнаружена в каталоге /home/ejudge/compile/scripts/in, системный каталог проверяться не будет. Поэтому, если необходимо модифицировать поставляемый скрипт, его нужно предварительно скопировать в этот каталог, затем модифицировать. Модифицировать файлы непосредственно в каталоге /opt/ejudge/libexec/ejudge/lang/in не рекомендуется, так как эти файлы перезаписываются при обновлении системы ejudge.

Каталог scripts

В каталоге /home/ejudge/compile/scripts находятся обработанные заготовки скриптов, готовые к использованию всеми программами системы ejudge. Заготовки скриптов обрабатываются и копируются из каталогов /opt/ejudge/libexec/ejudge/lang/in и /home/ejudge/compile/scripts/in в этот каталог программой ejudge-configure-compilers.

Заготовки скриптов

Для ЯП foo должны быть написаны заготовки скриптов foo.in и foo-version.in. Заготовки скриптов должны быть помещены в каталог /home/ejudge/compile/scripts/in. Заготовки скриптов по смыслу соответствуют заготовкам файлов Makefile.in, config.h.in в системе GNU autotools. То есть в заготовках скриптов выполняется замена переменных вида @var@ на их значения.

Поддерживаемые подстановки перечислены в таблице

подстановка соотв. опция configure значение для рассм. примера
@lang_config_dir@ --enable-lang-config-dir /home/ejudge/compile/conf/lang.d
@prefix@ --prefix /opt/ejudge
@exec_prefix@ --exec-prefix /opt/ejudge
@libexecdir@ --libexecdir /opt/ejudge/libexec
@local_dir@ --enable-local-dir /var/lib/ejudge
@contests_home_dir@ --enable-contests-home-dir /home/ejudge

Настроечный скрипт

Интерфейс

Настроечный скрипт должен поддерживать несколько режимов запуска. Режимы задаются с помощью опций командной строки. Все режимы работы рассматриваются на примере настроечного скрипта foo-version

-r — режим конфигурирования

foo-version [-v] -r [ARG]

В режиме конфигурирования должна быть проверена поддержка ЯП в данной инсталляции. На стандартный поток вывода должно быть напечатано новое содержимое конфигурационного файла ЯП foo.cfg. Кроме того, если указана опция -v, на стандартный поток ошибок должна быть напечатана дополнительная информация о процессе конфигурирования. При успешном конфигурировании код завершения должен быть равен 0, а при неудаче — 1. В параметре ARG передается путь, который указал пользователь в опции --with-foo=ARG при конфигурировании в пакетном режиме, либо путь, введенный им при конфигурировании в диалоговом режиме.

Так, если ЯП foo поддерживается в данной инсталляции, сценарий запуска может быть следующим:

bash$ foo-version -v -r /usr/local/bin/foo
version="3.14"
arg="/usr/local/bin/foo"
long_name="GNU Foo Interpreter"
src_sfx=".foo"
arch="linux-shared"
FOOPATH="/usr/local/bin/foo"
checking whether GNU Foo is available... yes, /usr/local/bin/foo, 3.14
bash$

Последняя строка (checking...) выводится на стандартный поток ошибок.

Если ЯП foo не поддерживается в данной инсталляции, сценарий запуска может быть следующим:

bash$ foo-version -v -r
version=
arg=
long_name="GNU Foo Interpreter"
src_sfx=".foo"
arch="linux-shared"
FOOPATH="/bin/false"
checking whether GNU Foo is available... no
bash$

Последняя строка (checking...) выводится на стандартный поток ошибок.

-l — режим получения списка

foo-version -l

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

Так, для ЯП foo сценарий запуска может быть следующим:

bash$ foo-version -l
GNU Foo Interpreter [1]
bash$

Режим получения списка ЯП используется программой ejudge-configure-compilers при запуске ее с опцией --list.

-p — печать пути к ЯП

foo-version -p

В режиме печати пути к ЯП на стандартный поток вывода должен быть напечатан путь к ЯП. Код завершения должен быть равен 0. Если ЯП не поддерживается в данной инсталляции, вывод должен быть пуст, а код завершения равен 1. В этом случае на стандартный поток ошибок может выводиться диагностическое сообщение.

Так, если ЯП foo поддерживается в данной инсталляции, сценарий запуска может быть следующим:

bash$ foo-version -p
/usr/local/bin/foo
bash$

Режим печати используется программой super-serve в некоторых специальных случаях.

-f — печать полного имени и версии

foo-version -f

В режиме печати полного названия ЯП на стандартный поток вывода должно быть напечатано полное имя ЯП и номер версии ЯП. В случае, если ЯП не поддерживается на данной системе (в данной инсталляции), стандартный поток вывода должен быть пуст, а код возврата равен 1. На стандартный поток ошибок при этом может выводиться диагностическое сообщение.

Так, если ЯП foo поддерживается в данной инсталляции, сценарий запуска может быть следующим:

bash$ foo-version -f
GNU Foo Interpreter 3.14
bash$

Если ЯП foo не поддерживается, то следующим:

bash$ foo-version -f
This language is not supported.
bash$

в этом случае сообщение выводится на стандартный поток ошибок.

Режим печати версии используется программой super-serve в процессе настройки ЯП при редактировании турнира.

печать версии

foo-version

В режиме печати версий, который задаётся запуском скрипта без параметров, на стандартный поток вывода должен быть напечатан номер версии ЯП. В случае, если ЯП не поддерживается на данной системе (в данной инсталляции), стандартный поток вывода должен быть пуст, а код возврата равен 1. На стандартный поток ошибок при этом может выводиться диагностическое сообщение.

Так, если ЯП foo поддерживается в данной инсталляции, сценарий запуска может быть следующим:

bash$ foo-version
3.14
bash$

Если ЯП foo не поддерживается, то следующим:

bash$ foo-version
This language is not supported.
bash$

в этом случае сообщение выводится на стандартный поток ошибок.

Режим печати версии используется программой super-serve в процессе настройки ЯП при редактировании турнира.

Реализация

Рассмотрим реализацию скрипта конфигурирования ЯП foo foo-version.in. За образец для этого (гипотетического) скрипта взят скрипт для конфигурирования ЯП Ruby.

Скрипт компиляции

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

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

#! INTERP-PATH ARGS

и установить бит x разрешения выполнения файла. Здесь INTERP-PATH — это полный путь к интерпретатору соответствующего языка.

Далее скрипт компиляции рассматривается на примере гипотетического интерпретируемого языка foo.

Интерфейс

Интерфейс скрипта компиляции очень простой

foo SRC-FILE DST-FILE

Здесь SRC-FILE — имя входного файла, DST-FILE — имя выходного файла. Система ejudge формирует имена входного и выходного файлов с использованием суффиксов исходного файла и файла результата, как указано в конфигурационном файле ЯП. Таким образом, никакой дополнительной обработки имен входного и выходного файла выполнять не требуется.

Дополнительно в переменной окружения EJUDGE_FLAGS могут задаваться флаги для ЯП. Администратор турнира имеет возможность устанавливать флаги при редактировании турнира. Поэтому скрипт компиляции должен поддерживать задание дополнительных опций с помощью еременной окружения EJUDGE_FLAGS.

Реализация

Пример реализации скрипта компиляции foo.in. За образец для этого (гипотетического) скрипта взят скрипт для компиляции ЯП Ruby.

Переконфигурация поддерживаемых ЯП

После того, как скрипты foo-version.in и foo.in помещены в каталог /home/ejudge/compile/scripts/in достаточно запустить программу ejudge-configure-compilers. Если скрипты написаны правильно, версия ЯП должна быть определена корректно, после чего язык готов к использованию.

В турнир язык может быть добавлен при редактировании настроек турнира с помощью CGI-программы serve-control.

Перезапуск ejudge

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