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

From EjudgeWiki
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, перечислены ниже:

Revision as of 09:24, 8 August 2008

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

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

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

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

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

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

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

Параметры языка программирования, необходимые для поддержки языка в системе 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 языков программирования языков, поддерживаемых в стандартной поставке, хранятся в файле /opt/ejudge/libexec/ejudge/lang/lang_ids.cfg. Если информация о новом языке программирования в этом файле отсутствует, его идентификатор назначается автоматически: берется первый еще не использованный в файле compile.cfg. Пользователь может скопировать файл lang_ids.cfg в каталог /home/ejudge/compile/scripts и вносить в него произвольные изменения. Модифицировать файл /opt/ejudge/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.

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