Spec-Zone.ru › Perl 5.28

perlos2

СОДЕРЖАНИЕ

  • ИМЯ
  • СИНОПСИС
  • ОПИСАНИЕ
    • Целевая платформа
    • Другие операционные системы
    • Предварительные условия
    • Запуск программ Perl под OS/2 (и DOS и...)
    • Запуск программ OS/2 (и DOS) под Perl
  • Часто задаваемые вопросы
    • «Это не работает»
    • Не могу запустить внешние программы
    • Не могу встроить Perl в свою программу или использовать perl.dll из своей программы.
    • `` и pipe-open не работают под DOS.
    • Не могу запустить find.exe "шаблон" файл
  • УСТАНОВКА
    • Автоматическая установка двоичных файлов
    • Ручная установка двоичных файлов
    • Предупреждение
  • Доступ к документации
    • Файл OS/2 .INF
    • Простой текст
    • Руководства
    • HTML
    • Файлы GNU info
    • Файлы PDF
    • Документация LaTeX
  • СБОРКА
    • Краткое содержание
    • Предварительные условия
    • Получение исходного кода Perl
    • Применение патчей
    • Ручная правка
    • Создание
    • Тестирование
    • Установка собранного Perl
    • Сборка в стиле a.out
  • Сборка двоичного дистрибутива
  • Сборка пользовательских .EXE файлов
    • Создание исполняемых файлов с набором статически загружаемых расширений
    • Создание исполняемых файлов с пользовательскими путями поиска
  • Вопросы и ответы по сборке
    • Некоторые / стали \ в pdksh.
    • 'errno' — неразрешенная внешняя ссылка
    • Проблемы с tr или sed
    • Некая проблема (забыл какую ;-)
    • Библиотека ... не найдена
    • Ошибка сегментации в make
    • Ошибка теста op/sprintf
  • Особенности (недостатки) порта под OS/2
    • setpriority, getpriority
    • system()
    • extproc в первой строке
    • Дополнительные модули:
    • Предварительно построенные методы:
    • Предварительно построенные переменные:
    • Недостатки
    • Изменения
    • Идентификация DLL
    • Централизованное управление ресурсами
  • Варианты Perl
    • perl.exe
    • perl_.exe
    • perl__.exe
    • perl___.exe
    • Почему такие странные имена?
    • Почему динамическая компоновка?
    • Почему сборка химеры?
  • ОКРУЖЕНИЕ
    • PERLLIB_PREFIX
    • PERL_BADLANG
    • PERL_BADFREE
    • PERL_SH_DIR
    • USE_PERL_FLOCK
    • TMP или TEMP
  • Эволюция
    • Файловые дескрипторы текстового режима
    • Приоритеты
    • Изменение имён DLL: до версии 5.6.2
    • Изменение имён DLL: начиная с версии 5.6.2
    • Генерация перенаправляющих DLL
    • Потоки
    • Вызовы внешних программ
    • Выделение памяти
    • Потоки
  • ОШИБКИ
  • АВТОР
  • СМОТРИ ТАКЖЕ

ИМЯ

perlos2 - Perl под OS/2, DOS, Win0.3*, Win0.95 и WinNT.

СИНОПСИС

Данный документ можно прочитать в следующих форматах:

man perlos2
view perl perlos2
explorer perlos2.html
info perlos2

чтобы перечислить некоторые (не все могут быть доступны одновременно), или его можно прочитать как есть: как README.os2 или pod/perlos2.pod.

Чтобы прочитать версию документации в формате .INF (крайне рекомендуется) вне OS/2, вам потребуется программа-просмотрщик от IBM (возможно, доступна на ftp-сайтах IBM (?) (ссылка?)) или поставляется с PC DOS 7.0 и Visual Age C++ 3.5 от IBM.

Копия просмотрщика для Win* содержится в пакете "Just add OS/2 Warp".

ftp://ftp.software.ibm.com/ps/products/os2/tools/jaow/jaow.zip

в ?:\JUST_ADD\view.exe. Это даёт доступ к документации EMX в формате .INF (текстовая форма доступна в /emx/doc в дистрибутиве EMX). Также существует другой просмотрщик под названием xview.

Обратите внимание, что если у вас установлены lynx.exe или netscape.exe, вы можете переходить по ссылкам WWW в этом документе в формате .INF. Если у вас правильно установлена документация EMX, вы можете переходить по ссылкам на библиотеки (вам нужно убедиться, что view emxbook работает, установив переменную среды EMXBOOK, как описано в документации EMX).

ОПИСАНИЕ

Целевая платформа

Цель состоит в том, чтобы сделать OS/2 одной из наиболее поддерживаемых платформ для использования, создания и разработки Perl и приложений Perl, а также сделать Perl лучшим языком для использования под OS/2. Вторичная цель — попытаться заставить это работать и под DOS и Win* (но не слишком усердно).

Текущее состояние довольно близко к этой цели. Известные ограничения:

  • Некоторые программы *nix активно используют fork(); в большинстве полезных версий Perl для OS/2 (они собираются одновременно) это поддерживается; но некоторые версии этого не поддерживают (например, когда Perl вызывается из REXX). Использование fork() после использования динамически загружаемых расширений не будет работать с очень старыми версиями EMX.

  • Вам нужен отдельный исполняемый файл Perl perl__.exe (см. "perl__.exe"), если вы хотите использовать код PM в своём приложении (как Perl/Tk или OpenGL Perl модули) без наличия текстового окна.

    Хотя использование стандартного perl.exe из текстового окна возможно, я сталкивался с случаями, когда это приводило к ухудшению стабильности системы. Использование perl__.exe предотвращает такое ухудшение.

  • Нет простого способа доступа к объектам WPS. Единственный известный способ — через OS2::REXX и SOM расширения (см. OS2::REXX, SOM). Однако у нас нет доступа к удобным методам Object-REXX. (Возможно ли это вообще? Мне не известен API Object-REXX.) Расширение SOM (в настоящее время в альфа-тексте) может в конечном итоге устранить этот недостаток; однако из-за того, что DII не поддерживается модулем SOM, использование SOM не так удобно, как хотелось бы.

Пожалуйста, поддерживайте этот список актуальным, сообщив мне о других пунктах.

Другие операционные системы

Так как порт OS/2 для Perl использует замечательную среду EMX, он может работать (и создавать расширения, и, возможно, сам компилироваться) в любой среде, способной запускать EMX. Текущий список включает DOS, DOS-внутри-OS/2, Win0.3*, Win0.95 и WinNT. Из многих вариантов Perl работает только один, см. "perl_.exe".

Обратите внимание, что не все функции Perl доступны в этих средах. Это зависит от функций, которые расширитель (скорее всего, RSX) решил реализовать.

См. "Предварительные требования".

Предварительные требования

EMX

Необходим запуск EMX (может быть заменён RSX). Обратите внимание, что можно заставить perl_.exe работать под DOS без какой-либо внешней поддержки, связав emx.exe/rsx.exe с ним, см. emxbind. Обратите внимание, что в DOS для достижения наилучших результатов следует использовать среду RSX, которая имеет гораздо больше работающих функций (например, fork, popen и так далее). Фактически, RSX необходим, если отсутствует VCPI. Обратите внимание, что RSX требует DPMI. Многие реализации DPMI известны своей высокой ошибочностью, будьте осторожны!

Поддерживается только последняя версия среды, в настоящее время 0.9d fix 03. Perl может работать под более ранними версиями EMX, но это не тестировалось.

Различные компоненты EMX можно получить, например, из

ftp://crydee.sai.msu.ru/pub/comp/os/os2/leo/gnu/emx+gcc/
http://hobbes.nmsu.edu/h-browse.php?dir=/pub/os2/dev/emx/v0.9d/

Компонент среды выполнения должен иметь имя emxrt.zip.

ПРИМЕЧАНИЕ. При использовании emx.exe/rsx.exe достаточно разместить их в вашей переменной PATH. Нет необходимости указывать их явно (хотя это

emx perl_.exe -de 0

также сработает).

RSX

Для запуска Perl на платформах DPMI необходима среда RSX. Это необходимо в DOS-внутри-OS/2, Win0.3*, Win0.95 и WinNT (см. "Other OSes"). RSX не будет работать только с VCPI, как EMX, он требует DMPI.

Имея RSX и последнюю версию sh.exe, вы получите полностью функциональную среду типа *nix под DOS, например, fork, `` и работу с каналами-open. Фактически, MakeMaker работает (для статической сборки), поэтому можно создать среду разработки Perl под DOS.

RSX можно получить, например, из

http://cd.textfiles.com/hobbesos29804/disk1/EMX09C/
ftp://crydee.sai.msu.ru/pub/comp/os/os2/leo/gnu/emx+gcc/contrib/

Свяжитесь с автором по адресу rainer@mathematik.uni-bielefeld.de.

Последняя версия sh.exe с поддержкой DOS доступна в

http://www.ilyaz.org/software/os2/

как sh_dos.zip или под похожими именами, начинающимися с sh, pdksh и т. д.

HPFS

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

Обратите внимание, что если вы не планируете устанавливать сам Perl, возможно обмануть EMX, чтобы он усекал имена файлов. Это не поддерживается, ознакомьтесь с документацией EMX, чтобы узнать, как это сделать.

pdksh

Для запуска внешних программ со сложными командными строками (например, с каналами и/или экранированием аргументов) Perl использует внешнюю оболочку. В порте EMX эта оболочка должна называться sh.exe и располагаться либо в предопределённых местах (обычно F:/bin), либо в конфигурируемом месте (см. "PERL_SH_DIR").

Для наилучших результатов используйте EMX pdksh. Стандартная двоичная версия (5.2.14 или более поздняя) работает под DOS (с "RSX"), см.

http://www.ilyaz.org/software/os2/

Запуск программ Perl под OS/2 (и DOS и...)

Запустите свою программу Perl foo.pl с аргументами arg1 arg2 arg3 так же, как и на любой другой платформе, используя

perl foo.pl arg1 arg2 arg3

Если вы хотите указать параметры Perl -my_opts самому Perl (в отличие от вашей программы), используйте

perl -my_opts foo.pl arg1 arg2 arg3

В качестве альтернативы, если вы используете оболочку типа OS/2, такую как CMD или 4os2, поместите следующее в начало вашего скрипта Perl:

extproc perl -S -my_opts

переименуйте свою программу в foo.cmd и запустите её, набрав

foo arg1 arg2 arg3

Обратите внимание, что из-за ограничений OS/2 полный путь к скрипту Perl недоступен при использовании extproc, поэтому вы вынуждены использовать переключатель -S Perl, и ваш скрипт должен находиться в PATH. В качестве преимущества, если вы знаете полный путь к вашему скрипту, вы можете запустить его с помощью

perl ../../blah/foo.cmd arg1 arg2 arg3

(обратите внимание, что аргумент -my_opts обрабатывается строкой extproc в вашем скрипте, см. "extproc в первой строке").

Чтобы понять, что делает приведенное выше "волшебство", прочитайте документацию Perl о переключателе -S — см. perlrun, и справку по extproc:

view perl perlrun
man perlrun
view cmdref extproc
help extproc

или любой другой предпочитаемый вами метод.

Также существуют бесконечные возможности использования выполняемых расширений 4os2, ассоциаций WPS и т. д.... Однако, если вы используете оболочку типа *nix (например, sh.exe, предоставленную в дистрибутиве), вы должны следовать синтаксису, указанному в "Командные переключатели" в perlrun.

Обратите внимание, что переключатель -S поддерживает скрипты с дополнительными расширениями .cmd, .btm, .bat, .pl также.

Запуск программ OS/2 (и DOS) под Perl

Для этого предназначены функции system() (см. "system" в perlfunc), `` (см. "Операторы ввода/вывода" в perlop) и открытие канала (см. "open" в perlfunc). (Избегайте exec() (см. "exec" в perlfunc), если вы не знаете, что делаете).

Однако обратите внимание, что для использования некоторых из этих операторов необходима установленная оболочка с синтаксисом sh (см. "Pdksh", "Часто задаваемые вопросы"), и Perl должен иметь возможность её найти (см. "PERL_SH_DIR").

Случаи использования оболочки:

  1. Функция system() с одним аргументом (см. "system" в perlfunc), exec() (см. "exec" в perlfunc) с перенаправлением или символами метаязыка оболочки;

  2. Открытие канала (см. "open" в perlfunc) с командой, содержащей перенаправление или символы метаязыка оболочки;

  3. Обратные кавычки `` (см. "Операторы ввода/вывода" в perlop) с командой, содержащей перенаправление или символы метаязыка оболочки;

  4. Если исполняемый файл, вызываемый system()/exec()/open pipe/`` , является скриптом со строкой "магии" #! или extproc , которая задаёт оболочку;

  5. Если исполняемый файл, вызываемый system()/exec()/open pipe/`` , является скриптом без строки "магии", и $ENV{EXECSHELL} установлена на оболочку;

  6. Если исполняемый файл, вызываемый system()/exec()/open pipe/`` , не найден (не устарело ли это замечание?);

  7. Для подстановки шаблонов (см. "glob" в perlfunc, "Операторы ввода/вывода" в perlop) (устарело? Perl теперь использует встроенную подстановку шаблонов...).

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

Perl запускает скрипты, начинающиеся с маркеров extproc или #! непосредственно без вмешательства оболочки. Perl использует тот же алгоритм поиска исполняемого файла, что и pdksh: если путь в строке #! не работает и содержит /, то часть каталога исполняемого файла игнорируется, и исполняемый файл ищется в текущем каталоге и в PATH. Для поиска аргументов этих скриптов Perl использует другой алгоритм, чем pdksh: распознаётся до 3 аргументов, и отбрасываются хвостовые пробелы.

Если скрипт не содержит такой маркер, для избегания вызова sh.exe Perl использует тот же алгоритм, что и pdksh: если $ENV{EXECSHELL} установлена, скрипт передаётся в качестве первого аргумента этой команде, если не установлена, используется $ENV{COMSPEC} /c (или жёстко заданное предположение, если $ENV{COMSPEC} не установлена).

При запуске скриптов непосредственно Perl использует точно такой же алгоритм, как и для поиска скрипта, заданного опцией командной строки -S: он будет искать в текущем каталоге, затем в компонентах $ENV{PATH} с использованием следующего порядка добавляемых расширений: без расширения, .cmd, .btm, .bat, .pl.

Обратите внимание, что Perl начнёт поиск скриптов только если OS/2 не сможет запустить указанное приложение, поэтому system 'blah' не будет искать скрипт, если существует исполняемый файл blah.exe в любом месте в PATH. Другими словами, PATH фактически ищется дважды: сначала операционной системой как исполняемый файл, затем Perl как скрипт.

Также обратите внимание, что исполняемые файлы под OS/2 могут иметь любое расширение, но .exe будет автоматически добавлен, если в имени нет точки. Способ решения прост: так как blah. и blah обозначают один и тот же файл (по крайней мере, в файловых системах FAT и HPFS), чтобы запустить исполняемый файл, находящийся в файле n:/bin/blah (без расширения), передайте аргумент n:/bin/blah. (с добавленной точкой) в system().

Perl будет запускать программы PM из процесса VIO (=текстового) Perl в отдельной сессии PM; обратное неверно: когда вы запускаете программу, не являющуюся PM, из процесса Perl PM, Perl не запустит её в отдельной сессии. Если требуется отдельная сессия, либо убедитесь, что будет использована оболочка, как в system 'cmd /c myprog', либо запустите её с помощью необязательных аргументов функции system(), описанных в модуле OS2::Process. Это рассматривается как функция.

Часто задаваемые вопросы

'"Это не работает"'

Дистрибутивы Perl поставляются со скриптом testperl.cmd, который пытается обнаружить распространённые проблемы с неправильно настроенными установками. Есть большая вероятность, что он выяснит, на каком этапе установки вы допустили ошибку. ;-)

Не удаётся запустить внешние программы

  • Вы запустили свои программы с переключателем -w? См. "Запуск программ OS/2 (и DOS) под Perl".

  • Вы пытаетесь выполнить внутренние команды оболочки, такие как `copy a b` (внутренняя для cmd.exe) или `glob a*b` (внутренняя для ksh)? Вам необходимо явно указать вашу оболочку, как `cmd /c copy a b`, так как Perl не может определить, какие команды являются внутренними для вашей оболочки.

Не удаётся встроить Perl в моё приложение или использовать perl.dll из моего приложения.

Является ли ваша программа EMX-скомпилированной с -Zmt -Zcrtdll?

Ну, в наши дни DLL Perl должна быть пригодна и для программы с другой компиляцией… Если вы можете запускать Perl-код из REXX-скриптов (см. OS2::REXX), то существуют и другие аспекты взаимодействия, которые игнорируются текущим костыльным кодом для поддержки программ с разной компиляцией.

Если всё остальное не сработает, вам нужно создать автономную DLL для perl. Свяжитесь со мной, я это делал однажды. Сокеты не будут работать, как и многое другое.

Использовали ли вы ExtUtils::Embed?

Некоторое время назад поступали сообщения о том, что это не работает. В настоящее время это проверяется в наборе тестов Perl, поэтому выполните поиск в подкаталоге ./t дерева построения (а также в файлах *.t в подкаталоге ./lib), чтобы узнать, как это сделать «правильно».

`` и pipe-open не работают в DOS.

Это может быть вариантом проблемы «я не могу запустить внешние программы» или более глубокой проблемой. В принципе: вам необходим RSX (см. «Предварительные требования») для работы этих команд, и вам может потребоваться порт sh.exe, который понимает аргументы команд. Один из таких портов указан в «Предварительные требования» в разделе RSX. Не забудьте также установить переменную "PERL_SH_DIR".

Для RSX требуется DPMI.

Не удается запустить find.exe "pattern" file

Вся идея «стандартного C-API для запуска приложений» заключается в том, что формы foo и "foo" аргументов программы полностью взаимозаменяемы. find нарушает эту парадигму;

find "pattern" file
find pattern file

не эквивалентны; find нельзя запустить напрямую с помощью вышеуказанного API. Нужно каким-то образом заключить двойные кавычки в другую конструкцию цитирования, обязательно используя дополнительную не-подобную-Unix оболочку между ними.

Используйте одну из

system 'cmd', '/c', 'find "pattern" file';
`cmd /c 'find "pattern" file'`

Это запустит find.exe через cmd.exe через sh.exe через perl.exe, но это цена, которую нужно заплатить, если вы хотите использовать несоответствующую программу.

УСТАНОВКА

Автоматическая установка двоичных файлов

Самый удобный способ установки двоичного распределения perl — через установщик perl install.exe. Просто следуйте инструкциям, и 99% проблем с установкой исчезнут.

Однако имейте в виду, что unzip.exe должен быть в вашей переменной PATH, и среда EMX запущена. Последнее означает, что если вы только что установили EMX и внесли все необходимые изменения в Config.sys, вам может потребоваться перезагрузка между этапами. Проверьте запуск EMX, выполнив

emxrev

Двоичный установщик также создаёт папку на рабочем столе с некоторыми полезными объектами. Если вам нужно изменить некоторые аспекты работы двоичного установщика, вы можете изменить файл Perl.pkg. Это может быть полезно, например, если вам нужно запускать установщик много раз и вы не хотите вносить много интерактивных изменений в графический интерфейс.

Элементы, не обрабатываемые автоматической установкой двоичных файлов:

PERL_BADLANG

может потребоваться, если вы измените свою кодировку после установки perl, а новое значение не поддерживается EMX. См. "PERL_BADLANG".

PERL_BADFREE

см. "PERL_BADFREE".

Config.pm

Этот файл находится где-то глубоко в каталоге, куда вы установили свою библиотеку perl, найдите его, выполнив

perl -MConfig -le "print $INC{'Config.pm'}"

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

ПРИМЕЧАНИЕ. Из-за опечатки двоичный установщик версии 5.00305 установит переменную PERL_SHPATH в Config.sys. Пожалуйста, удалите эту переменную и вместо неё вставьте "PERL_SH_DIR".

Ручная установка двоичных файлов

Начиная с версии 5.00305, двоичное распределение perl для OS/2 разделено на 11 компонентов. К сожалению, для обеспечения конфигурируемой установки двоичных файлов пути файлов в zip-архивах не абсолютные, а относительные к какому-то каталогу.

Обратите внимание, что извлечение сохранёнными путями всё ещё необходимо (по умолчанию с unzip, укажите -d для pkunzip). Однако вам нужно знать, куда извлекать файлы. Вам также необходимо вручную изменить записи в Config.sys, чтобы отразить, куда вы поместили файлы. Обратите внимание, что если у вас есть примитивный распаковщик (например, pkunzip), при распаковке может появиться много предупреждений/ошибок. Обновитесь до (w)unzip.

Ниже приведен пример того, что нужно сделать, чтобы воспроизвести конфигурацию на моём компьютере. В VIEW.EXE вы можете нажать Ctrl-Insert сейчас и скопировать/вставить из полученного файла — созданного в каталоге, из которого вы запустили VIEW.EXE.

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

Исполняемые файлы Perl VIO и PM (динамически связанные)
unzip perl_exc.zip *.exe *.ico -d f:/emx.add/bin
unzip perl_exc.zip *.dll -d f:/emx.add/dll

(каталоги с *.exe в PATH и *.dll в LIBPATH);

Исполняемый файл Perl_ VIO (статически связанный)
unzip perl_aou.zip -d f:/emx.add/bin

(каталог в PATH);

Исполняемые файлы для утилит Perl
unzip perl_utl.zip -d f:/emx.add/bin

(каталог в PATH);

Основная библиотека Perl
unzip perl_mlb.zip -d f:/perllib/lib

Если этот каталог точно такой же, как префикс, который был скомпилирован в perl.exe, вам ничего не нужно менять. Однако, чтобы perl нашёл библиотеку, если вы используете другой путь, вам нужно set PERLLIB_PREFIX в Config.sys, см. "PERLLIB_PREFIX".

Дополнительные модули Perl
unzip perl_ste.zip -d f:/perllib/lib/site_perl/5.28.3/

То же замечание, что и выше. Кроме того, если этот каталог не является одним из каталогов в @INC (и @INC зависит от PERLLIB_PREFIX), вам нужно поместить этот каталог и подкаталог ./os2 в переменную PERLLIB или PERL5LIB. Не используйте PERL5LIB, если вы её уже не установили. См. "СРЕДА" в perl.

[Проверьте, остаётся ли этот каталог извлечения применимым с новой структурой расположения каталогов!]

Инструменты для компиляции модулей Perl
unzip perl_blb.zip -d f:/perllib/lib

То же замечание, что и для perl_ste.zip.

Справочные страницы для Perl и утилит
unzip perl_man.zip -d f:/perllib/man

Этот каталог лучше поместить в MANPATH. Вам нужна работающая утилита man для доступа к этим файлам.

Справочные страницы для модулей Perl
unzip perl_mam.zip -d f:/perllib/man

Этот каталог лучше поместить в MANPATH. Вам нужна работающая утилита man для доступа к этим файлам.

Исходный код документации Perl
unzip perl_pod.zip -d f:/perllib/lib

Используется программой perldoc (см. perldoc) и может использоваться для генерации HTML-документации, доступной для веб-браузеров, и документации в бесчисленных других форматах: info, LaTeX, Acrobat, FrameMaker и так далее. [Используйте программы, такие как pod2latex и т. д.]

Справочник Perl в формате .INF
unzip perl_inf.zip -d d:/os2/book

Этот каталог лучше поместить в BOOKSHELF.

Pdksh
unzip perl_sh.zip -d f:/bin

Используется perl для запуска внешних команд, которые явно требуют оболочки, таких как команды с использованием перенаправления и метасимволов оболочки. Также используется вместо явного /bin/sh.

Установите PERL_SH_DIR (см. "PERL_SH_DIR"), если вы перемещаете sh.exe из указанного выше места.

Примечание. Возможно использование другой совместимой с sh оболочки (не протестировано).

После установки необходимых компонентов и соответствующего обновления Config.sys вам нужно вручную отредактировать Config.pm. Этот файл находится где-то глубоко в каталоге, куда вы установили свою библиотеку perl, найдите его, выполнив

perl -MConfig -le "print $INC{'Config.pm'}"

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

Предупреждение

Автоматическая и ручная установка perl оставляют предварительно скомпилированные пути внутри исполняемых файлов perl. Хотя эти пути можно перезаписать (см. "PERLLIB_PREFIX", "PERL_SH_DIR"), некоторые люди могут предпочесть двоичное редактирование путей внутри исполняемых файлов/DLL.

Доступ к документации

В зависимости от того, как вы построили/установили perl, у вас может быть (в противном случае идентичная) документация Perl в следующих форматах:

Файл OS/2 .INF

Вероятно, самый удобный формат. В OS/2 отображается как

view perl
view perl perlfunc
view perl less
view perl ExtUtils::MakeMaker

(в настоящее время последние два могут попасть в неправильное место, но это может быть исправлено вскоре). В Win* см. "ОБЗОР".

Если вы хотите самостоятельно создать документацию и имеете OS/2 toolkit, выполните

pod2ipf > perl.ipf

в каталоге /perllib/lib/pod, затем

ipfc /inf perl.ipf

(Ожидайте много ошибок во время обоих этапов.) Теперь перенесите его в свой каталог BOOKSHELF.

Текст

Если у вас есть исходный текст документации perl, установлены утилиты perl и установлена GNU groff, вы можете использовать

perldoc perlfunc
perldoc less
perldoc ExtUtils::MakeMaker

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

В качестве альтернативы попробуйте запустить pod2text на файлах .pod.

Справочные страницы

Если у вас установлена утилита man на вашей системе и установлены справочные страницы perl, используйте что-то вроде этого:

man perlfunc
man 3 less
man ExtUtils.MakeMaker

для доступа к документации различных компонентов Perl. Начните с

man perl

Обратите внимание, что точка (.) используется в качестве разделителя пакетов для документации пакетов, и, как обычно, иногда вам нужно указать раздел — 3 выше — чтобы избежать перекрытия со справочной страницей less(1) manpage.

Убедитесь, что каталог выше каталога со справочными страницами находится в нашем MANPATH, например так

set MANPATH=c:/man;f:/perllib/man

для справочных страниц perl в f:/perllib/man/man1/ и т. д.

HTML

Если у вас есть доступный веб-браузер, установлена документация Perl в исходной форме и утилиты Perl, вы можете сгенерировать HTML-документацию. Перейдите в каталог с файлами .pod и выполните следующие действия

cd f:/perllib/lib/pod
pod2html

После этого вы можете открыть в браузере файл perl.html в этом каталоге и приступить к чтению документации, как показано ниже:

explore file:///f:/perllib/lib/pod/perl.html

В качестве альтернативы вы можете получить эти документы, уже сгенерированные, с помощью CPAN.

Файлы GNU info

Пользователям Emacs это очень пригодится, особенно с загруженным режимом CPerl. Вам необходимо получить последние pod2texi с CPAN, или, в качестве альтернативы, уже сгенерированные страницы info.

Файлы PDF

для Acrobat доступны на CPAN (возможно, для немного более старой версии Perl).

Документация LaTeX

может быть сгенерирована с помощью pod2latex.

Сборка

Здесь мы обсудим, как собрать Perl под OS/2.

Краткое описание процесса

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

gnupatch -p0 < os2\diff.configure
sh Configure -des -D prefix=f:/perllib
make
make test
make install
make aout_test
make aout_install

Это поместит исполняемые файлы в f:/perllib/bin. Переместите их вручную в PATH, вручную переместите созданные perl*.dll в LIBPATH (здесь для Perl DLL * — не имеющий особого смысла шестнадцатеричный контрольный код) и выполните

make installcmd INSTALLCMDDIR=d:/ir/on/path

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

Далее следует подробное руководство по этим шагам.

Предварительные условия

Вам нужна последняя среда разработки EMX, полный набор инструментов GNU (gawk переименован в awk, и GNU find.exe расположен выше в пути, чем OS/2 find.exe, также с sort.exe, чтобы проверить, используйте

find --version
sort --version

). Вам нужна последняя версия pdksh, установленная как sh.exe.

Проверьте, установлены ли библиотеки и заголовки BSD, а также — по желанию — заголовки и библиотеки Berkeley DB и crypt.

Возможные места для получения файлов:

ftp://ftp.uni-heidelberg.de/pub/os2/unix/
http://hobbes.nmsu.edu/h-browse.php?dir=/pub/os2
http://cd.textfiles.com/hobbesos29804/disk1/DEV32/
http://cd.textfiles.com/hobbesos29804/disk1/EMX09C/

Сообщается, что следующие архивы содержат достаточно утилит для сборки Perl: gnufutil.zip, gnusutil.zip, gnututil.zip, gnused.zip, gnupatch.zip, gnuawk.zip, gnumake.zip, gnugrep.zip, bsddev.zip и ksh527rt.zip (или более поздняя версия). Обратите внимание, что все эти утилиты, как известно, доступны в LEO:

ftp://crydee.sai.msu.ru/pub/comp/os/os2/leo/gnu/

Также обратите внимание, что db.lib и db.a из дистрибутива EMX не подходят для многопоточной компиляции (даже однопоточная версия Perl использует многопоточную C RTL для совместимости с XFree86-OS/2). Получите исправленную версию из

http://www.ilyaz.org/software/os2/db_mt.zip

Если у вас установлена точно такая же версия Perl, убедитесь, что в данный момент не запущены какие-либо копии или экземпляры perl. Более поздние этапы сборки могут завершиться неудачей, так как в памяти может быть загружена более старая версия perl.dll. Запуск make test становится бессмысленным, так как тесты проверяют предыдущую версию сборки perl (эта ситуация обнаруживается и сообщается тестом os2/os2_base.t). Не забудьте сбросить PERL_EMXLOAD_SEC в среде.

Также убедитесь, что каталог /tmp находится на текущем диске и каталог . в вашей LIBPATH. Можно попытаться исправить последнее условие, выполнив

set BEGINLIBPATH .\.

если вы используете что-то вроде CMD.EXE или последние версии 4os2.exe. (Установка BEGINLIBPATH только на . игнорируется ядром OS/2.)

Убедитесь, что ваш gcc подходит для -Zomf линковки: выполните скрипт omflibs в каталоге /emx/lib.

Проверьте, установлен ли link386. Он входит в стандартную поставку OS/2, но может быть не установлен из-за настройки. Если ввод

link386

показывает, что он отсутствует, выполните Выборочную установку и выберите Link object modules в Дополнительные системные утилиты/Ещё. Если вы попадете в приглашения link386, нажмите Ctrl-C для выхода.

Получение исходного кода Perl

Вам нужно получить последний исходный код Perl (включая релизы разработчиков). С определённой вероятностью он находится в

http://www.cpan.org/src/
http://www.cpan.org/src/unsupported

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

Быстрый цикл релизов разработчиков время от времени может нарушить процесс сборки под OS/2, поиск в

http://www.cpan.org/ports/os2/

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

Извлеките его так:

tar vzxf perl5.00409.tar.gz

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

Перейдите в каталог извлечения.

Применение исправлений

Вам нужно применить исправления из ./os2/diff.* следующим образом:

gnupatch -p0 < os2\diff.configure

Вам также может потребоваться применить исправления, входящие в состав бинарного дистрибутива Perl. Также имеет смысл обратиться к списку рассылки perl5-porters по последним исправлениям, относящимся к OS/2 (см. http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/). Такие исправления обычно содержат строки /os2/ и patch, поэтому имеет смысл искать эти строки.

Редактирование вручную

Вы можете посмотреть файл ./hints/os2.sh и исправить любые ошибки, которые вы там найдёте. Я не ожидаю, что это потребуется в любом случае.

Сборка

sh Configure -des -D prefix=f:/perllib

prefix означает: куда установить получившуюся библиотеку perl. Указав правильный префикс, вы можете избежать необходимости указывать PERLLIB_PREFIX, см. "PERLLIB_PREFIX".

Игнорируйте сообщение об отсутствии ln, и об опции -c для tr. Вероятно, последняя уже исправлена, если вы её видите и можете отследить, откуда исходит это ложное предупреждение, сообщите мне об этом.

Теперь

make

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

Тестирование

Теперь выполните

make test

Все тесты должны быть пройдены (некоторые из них могут быть пропущены). Если у вас установлена та же версия Perl, крайне важно, чтобы . находилась в начале вашего LIBPATH (или в BEGINLIBPATH), в противном случае ваши тесты, скорее всего, будут проверять не ту версию Perl.

Некоторые тесты могут генерировать дополнительные сообщения, подобные

Множество bad free

в тестах базы данных, связанных с Berkeley DB. Это должно быть уже исправлено. Если проблема сохраняется, вы можете отключить эти предупреждения, см. "PERL_BADFREE".

Процесс завершён по сигналу SIGTERM/SIGINT

Это стандартное сообщение, выдаваемое приложениями OS/2. Приложения *nix завершаются без сообщений. Это считается особенностью. Можно легко отключить это с помощью соответствующих обработчиков сигналов.

Однако система тестирования выводит эти сообщения на экран в неожиданные моменты. Два таких сообщения *должны* присутствовать во время тестирования.

Для получения более подробных отчётов о тестах вызовите

perl t/harness

Отчёт с io/pipe.t, завершившимся ошибкой, может выглядеть так:

Failed Test  Status Wstat Total Fail  Failed  List of failed
------------------------------------------------------------
io/pipe.t                    12    1   8.33%  9
7 tests skipped, plus 56 subtests skipped.
Failed 1/195 test scripts, 99.49% okay. 1/6542 subtests failed,
   99.98% okay.

Причины самых важных пропущенных тестов:

op/fs.t
18

Проверяет atime и mtime в stat() — к сожалению, HPFS предоставляет только 2-секундную точность временных меток (для совместимости с FAT?).

25

Проверяет truncate() на файле, только что открытом для записи — я не знаю, почему это должно или не должно работать.

op/stat.t

Проверяет stat(). Тесты:

4

Проверяет atime и mtime в stat() — к сожалению, HPFS предоставляет только 2-секундную точность временных меток (для совместимости с FAT?).

Установка собранного Perl

Если вы ещё не перенесли perl*.dll в LIBPATH, сделайте это сейчас.

Выполните

make install

Это поместит сгенерированные файлы в нужные места. Вручную поместите perl.exe, perl__.exe и perl___.exe в местоположение в вашем PATH, perl.dll — в местоположение в вашем LIBPATH.

Выполните

make installcmd INSTALLCMDDIR=d:/ir/on/path

чтобы преобразовать утилиты perl в файлы .cmd и поместить их в PATH. Вам нужно вручную поместить утилиты с расширением .EXE в путь. Они установлены в $prefix/bin, здесь $prefix — то, что вы указали в Configure, см. "Сборка".

Если вы используете man, либо перенесите установленные каталоги */man/ в ваш MANPATH, либо измените MANPATH для соответствия расположению. (Можно было бы избежать этого, предоставив корректную опцию manpath для ./Configure или отредактировав ./config.sh между этапами конфигурирования и сборки.)

Сборка в стиле a.out

Продолжайте как выше, но создайте perl_.exe (см. "perl_.exe") с помощью

make perl_

тестируйте и устанавливайте с помощью

make aout_test
make aout_install

Вручную поместите perl_.exe в местоположение в вашем PATH.

Примечание. Процесс сборки для perl_ не знает обо всех зависимостях, поэтому вы должны убедиться, что все обновлено, например, выполнив

make perl_dll

сначала.

Сборка бинарного дистрибутива

[Этот раздел содержит только краткий обзор...]

Процесс сборки должен отличаться в зависимости от того, уже присутствует ли и используется ли устанавливаемая версия Perl в вашей системе или это новая версия, которая ещё не используется. Описание ниже предполагает, что версия новая, поэтому установка её DLL и файлов .pm не нарушит работу вашей системы, даже если некоторые промежуточные шаги ещё не полностью работают.

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

  1. Полностью постройте и протестируйте дистрибутив Perl. Убедитесь, что никакие тесты не терпят неудачу с целями test и aout_test; исправьте ошибки в Perl и наборе тестов Perl, обнаруженные этими тестами. Убедитесь, что цель all_test make выполняется максимально чисто. Проверьте, что os2/perlrexx.cmd работает нормально.

  2. Полностью установите Perl, включая цель installcmd. Скопируйте сгенерированные DLL-файлы в LIBPATH; скопируйте пронумерованные исполняемые файлы Perl (как в perl5.8.2.exe) в PATH; скопируйте perl_.exe в PATH как perl_5.8.2.exe. Подумайте, нужны ли вам DLL-файлы обратной совместимости. В большинстве случаев вам пока не нужно их устанавливать; но иногда это может упростить последующие шаги.

  3. Убедитесь, что CPAN.pm может загружать файлы из CPAN. Если нет, возможно, вам нужно вручную установить Net::FTP.

  4. Установите пакет Bundle::OS2_default

    perl5.8.2 -MCPAN -e "install Bundle::OS2_default" < nul |& tee 00cpan_i_1

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

    perl5.8.2 -MCPAN -e "install Bundle::OS2_default" < nul |& tee 00cpan_i_2
    perl5.8.2 -MCPAN -e "install Bundle::OS2_default" < nul |& tee 00cpan_i_3

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

    Исправьте как можно больше обнаруженных ошибок. Документируйте все ошибки, которые не были исправлены, и все сбои с неизвестными причинами. Проверьте созданные журналы 00cpan_i_1, чтобы найти подозрительно пропущенные тесты и другие подозрительные события.

    Помните, что установка некоторых модулей также может завершиться ошибкой: например, DLL-файлы для обновления могут уже быть загружены CPAN.pm. Проверьте журналы install (в примере выше 00cpan_i_1 и т.д.) на наличие ошибок и установите компоненты вручную, как в

    cd $CPANHOME/.cpan/build/Digest-MD5-2.31
    make install

    Некоторые дистрибутивы могут не пройти некоторые тесты, но вы можете захотеть установить их все равно (как выше, или с помощью команды force install оболочки CPAN.pm).

    Поскольку эта процедура может занимать довольно много времени, имеет смысл «заморозить» вашу конфигурацию CPAN, отключив периодические обновления локальной копии индекса CPAN: установите index_expire на какое-то большое значение (я использую 365), затем сохраните настройки

    CPAN> o conf index_expire 365
    CPAN> o conf commit

    Верните значение по умолчанию 1 по завершении.

  5. По завершении выполнения, перезапустите цель installcmd. Теперь вы можете скопировать perl5.8.2.exe в perl.exe, и установить другие исполняемые файлы OMF-build: perl__.exe и т.д. Они готовы к использованию.

  6. Перейдите в директорию ./pod дерева сборки, загрузите логотип Perl CamelGrayBig.BMP и выполните

    ( perl2ipf > perl.ipf ) |& tee 00ipf
    ipfc /INF perl.ipf |& tee 00inf

    Это создает онлайн-книгу документации Perl perl.INF. Установите её в путь BOOKSHELF.

  7. Сейчас самое время создать статически связанный исполняемый файл perl_.exe, включающий недавно установленные через Bundle::OS2_default модули. Тестирование через CPAN.pm будет очень медленным, так как для каждого XS-расширения создается новый исполняемый файл.

    Вот возможный обходной путь: создайте файл Makefile.PL в корне в $CPANHOME/.cpan/build/ с содержимым (сравните с "Создание исполняемых файлов с набором статически загружаемых расширений")

    use ExtUtils::MakeMaker;
    WriteMakefile NAME => 'dummy';

    выполните это как

    perl_5.8.2.exe Makefile.PL <nul |& tee 00aout_c1
    make -k all test <nul |& 00aout_t1

    Опять же, этот процесс не должен быть совершенно гладким. Некоторые Makefile.PL в поддиректориях могут быть ошибочными и не будут работать как «дочерние» скрипты. Взаимозависимость модулей может вас удивить; однако, так как не-XS модули уже установлены, предшественники большинства модулей, скорее всего, присутствуют.

    Если вы обнаружите какие-либо проблемы, переместите каталоги проблемных модулей в другое место; если эти модули являются не-XS модулями, вы можете просто их пропустить — они уже установлены; оставшиеся, XS-модули, необходимо установить вручную по одному.

    После каждого такого удаления необходимо перезапустить процесс Makefile.PL/make; обычно этот процесс быстро сходится. (Но убедитесь, что все необходимые внешние библиотеки C преобразованы из формата .lib в формат .a: выполните одну из

    emxaout foo.lib
    emximp -o foo.a foo.lib

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

    Когда вы уверены, что только несколько подкаталогов приводят к ошибкам, вы можете добавить опцию -j4 к make для ускорения пропуска подкаталогов с уже завершенной сборкой.

    Когда вы удовлетворены результатами тестов, установите библиотеки C для сборки расширений:

    make install |& tee 00aout_i

    Теперь вы можете переименовать файл ./perl.exe, сгенерированный на последнем этапе, в perl_5.8.2.exe; поместите его в PATH; если существует взаимозависимость между некоторыми XS-модулями, вам может потребоваться повторить цикл test/install с этим новым исполняемым файлом и некоторыми исключенными модулями — до тех пор, пока процедура не сойдётся.

    Теперь у вас есть все необходимые библиотеки .a для этих модулей Perl в местах, где их может найти Perl-строитель. Используйте Perl-строитель: перейдите в пустую директорию, создайте еще один «фиктивный» файл Makefile.PL и выполните

    perl_5.8.2.exe Makefile.PL |& tee 00c
    make perl                  |& tee 00p

    Это должно создать исполняемый файл ./perl.exe со всеми статически загруженными расширениями, встроенными в него. Сравните сгенерированные файлы perlmain.c, чтобы убедиться, что при итерациях число загруженных расширений только увеличивается. Переименуйте ./perl.exe в perl_5.8.2.exe в PATH.

    Когда процедура сойдётся, вы получите функциональную версию perl_5.8.2.exe; скопируйте её в perl_.exe. Вы завершили генерацию локальной установки Perl.

  8. Убедитесь, что установленные модули действительно установлены в местоположение нового Perl, а не унаследованы из записей @INC, указанных для наследования от более старых версий Perl: установите PERLLIB_582_PREFIX для перенаправления новой версии Perl в новое местоположение и скопируйте установленные файлы в это новое местоположение. Повторите тесты, чтобы убедиться, что версии модулей, унаследованные от более ранних версий Perl, не нужны.

    На самом деле, вывод логов pod2ipf(1) на шаге 6 дает очень подробную информацию о том, какие модули загружаются откуда; поэтому вы можете использовать его как дополнительный инструмент проверки.

    Проверьте, что некоторые временные файлы не попали в дерево установки Perl. Выполните что-то вроде этого

    pfind . -f "!(/\.(pm|pl|ix|al|h|a|lib|txt|pod|imp|bs|dll|ld|bs|inc|xbm|yml|cgi|uu|e2x|skip|packlist|eg|cfg|html|pub|enc|all|ini|po|pot)$/i or /^\w+$/") | less

    в дереве установки (как в верхнем, так и в sitelib).

    Сжать все DLL-файлы с помощью lxlite. Небольшие .exe-файлы можно сжать с помощью /c:max (ошибка возникает только тогда, когда есть исправление в последних 6 байтах страницы (?); поскольку небольшие исполняемые файлы намного меньше страницы, ошибка не повлияет). Не сжимайте perl_.exe — это не будет работать под DOS.

  9. Теперь вы можете сгенерировать двоичный дистрибутив. Для этого выполните тест дистрибутива CPAN OS2::SoftInstaller. Сначала настройте файл test.pl в соответствии с макетом текущей версии Perl. Не забудьте соответствующим образом упаковать необходимые внешние DLL-файлы. Включите описание ошибок и сбоев набора тестов, которые вы не смогли исправить. Включите версии Perl с небольшим стеком из каталога сборки Perl.

    Включите perl5.def, чтобы пользователи могли повторно связать DLL Perl, сохраняя двоичную совместимость, или могли создать DLL-файлы совместимости. Включите файлы diff (diff -pu old new) исправлений, которые вы внесли, чтобы пользователи могли перестроить вашу версию. Включите perl5.map, чтобы можно было использовать удаленное отладку.

  10. Поделитесь тем, что вы сделали с другими людьми. Отдохните. Наслаждайтесь плодами своего труда.

  11. Приготовьтесь к благодарностям, сообщениям об ошибках, ненавистным письмам и спаму, которые придут в результате предыдущего шага. Нет добрых дел, которые остаются невознагражденными!

Создание пользовательских файлов .EXE

Исполняемые файлы Perl можно легко перестроить в любое время. Более того, можно использовать интерфейс встраивания (см. perlembed), чтобы создавать очень настраиваемые исполняемые файлы.

Создание исполняемых файлов с набором статически загружаемых расширений

Немного проще сделать это, уменьшив список статически загружаемых расширений. Мы рассматриваем только этот случай.

  1. Перейдите в пустую директорию и создайте файл-заглушку <Makefile.PL>:

    use ExtUtils::MakeMaker;
    WriteMakefile NAME => 'dummy';
  2. Запустите его с требуемой версией Perl (perl.exe или perl_.exe), которую вы хотите перестроить.

    perl_ Makefile.PL
  3. Попросите его создать новый исполняемый файл Perl:

    make perl

    (возможно, вам нужно будет вручную добавить PERLTYPE=-DPERL_CORE к этой команде в некоторых версиях Perl; признаком является то, что команда-глобальный поиск не работает из оболочек OS/2 с недавно скомпилированным исполняемым файлом; проверьте с помощью

    .\perl.exe -wle "print for @ARGV" *

    ).

  4. На предыдущем шаге был создан perlmain.c, который содержит список вызовов newXS() в конце. Удаление ненужных вызовов и повторное выполнение

    make perl

    создаст настраиваемый исполняемый файл.

Создание исполняемых файлов с пользовательскими путями поиска

Стандартный исполняемый файл perl достаточно гибкий, чтобы поддерживать большинство применений. Однако, возможно, потребуется что-то еще более гибкое; например, может потребоваться найти DLL Perl относительно расположения файла EXE; или может потребоваться игнорировать среду при установке пути поиска библиотек Perl и т.д.

Если вы чувствуете себя комфортно с интерфейсом встраивания (см. perlembed), такие вещи легко сделать, повторив шаги, описанные в L/<Создание исполняемых файлов с пользовательским набором статически загружаемых расширений> и выполнив более подробные правки в main() в perlmain.c. Люди с небольшим желанием понимать Perl могут просто переименовать main() и внести необходимые изменения в пользовательскую функцию main(), которая вызывает переименованную функцию в соответствующее время.

Однако существует третий способ: DLL Perl экспортирует функцию main() и несколько обратных вызовов для настройки пути поиска. Ниже приведен полный пример «загрузчика Perl», который

  1. Ищет DLL Perl в директории $exedir/../dll;

  2. Добавляет вышеуказанную директорию в начало BEGINLIBPATH;

  3. Возвращает ошибку, если DLL Perl, найденная с помощью BEGINLIBPATH, отличается от загруженной на шаге 1; например, другой процесс мог загрузить её из LIBPATH или из другого значения BEGINLIBPATH. В этих случаях необходимо изменить настройки системы, чтобы этот другой процесс либо не запускался, либо загружал DLL из BEGINLIBPATH с LIBPATHSTRICT=T (доступно в ядрах после сентября 2000 года).

  4. Загружает библиотеку Perl из $exedir/../dll/lib/.

  5. Использует оболочку Bourne из $exedir/../dll/sh/ksh.exe.

Для наилучших результатов скомпилируйте нижеприведенный файл C с теми же опциями, что и Perl DLL. Однако, многие функции будут работать даже если исполняемый файл не является приложением EMX, например, если он скомпилирован с

gcc -Wall -DDOSISH -DOS2=1 -O2 -s -Zomf -Zsys perl-starter.c \
  -DPERL_DLL_BASENAME=\"perl312F\" -Zstack 8192 -Zlinker /PM:VIO

Вот пример файла C:

#define INCL_DOS
#define INCL_NOPM
/* These are needed for compile if os2.h includes os2tk.h, not
 * os2emx.h */
#define INCL_DOSPROCESS
#include <os2.h>

#include "EXTERN.h"
#define PERL_IN_MINIPERLMAIN_C
#include "perl.h"

static char *me;
HMODULE handle;

static void
die_with(char *msg1, char *msg2, char *msg3, char *msg4)
{
   ULONG c;
   char *s = " error: ";

   DosWrite(2, me, strlen(me), &c);
   DosWrite(2, s, strlen(s), &c);
   DosWrite(2, msg1, strlen(msg1), &c);
   DosWrite(2, msg2, strlen(msg2), &c);
   DosWrite(2, msg3, strlen(msg3), &c);
   DosWrite(2, msg4, strlen(msg4), &c);
   DosWrite(2, "\r\n", 2, &c);
   exit(255);
}

typedef ULONG (*fill_extLibpath_t)(int type,
                                   char *pre,
                                   char *post,
                                   int replace,
                                   char *msg);
typedef int (*main_t)(int type, char *argv[], char *env[]);
typedef int (*handler_t)(void* data, int which);

#ifndef PERL_DLL_BASENAME
#  define PERL_DLL_BASENAME "perl"
#endif

static HMODULE
load_perl_dll(char *basename)
{
    char buf[300], fail[260];
    STRLEN l, dirl;
    fill_extLibpath_t f;
    ULONG rc_fullname;
    HMODULE handle, handle1;

    if (_execname(buf, sizeof(buf) - 13) != 0)
        die_with("Can't find full path: ", strerror(errno), "", "");
    /* XXXX Fill 'me' with new value */
    l = strlen(buf);
    while (l && buf[l-1] != '/' && buf[l-1] != '\\')
        l--;
    dirl = l - 1;
    strcpy(buf + l, basename);
    l += strlen(basename);
    strcpy(buf + l, ".dll");
    if ( (rc_fullname = DosLoadModule(fail, sizeof fail, buf, &handle))
                                                                   != 0
         && DosLoadModule(fail, sizeof fail, basename, &handle) != 0 )
        die_with("Can't load DLL ", buf, "", "");
    if (rc_fullname)
        return handle;    /* was loaded with short name; all is fine */
    if (DosQueryProcAddr(handle, 0, "fill_extLibpath", (PFN*)&f))
        die_with(buf,
                 ": DLL exports no symbol ",
                 "fill_extLibpath",
                 "");
    buf[dirl] = 0;
    if (f(0 /*BEGINLIBPATH*/, buf /* prepend */, NULL /* append */,
          0 /* keep old value */, me))
        die_with(me, ": prepending BEGINLIBPATH", "", "");
    if (DosLoadModule(fail, sizeof fail, basename, &handle1) != 0)
        die_with(me,
                 ": finding perl DLL again via BEGINLIBPATH",
                 "",
                 "");
    buf[dirl] = '\\';
    if (handle1 != handle) {
        if (DosQueryModuleName(handle1, sizeof(fail), fail))
            strcpy(fail, "???");
        die_with(buf,
                 ":\n\tperl DLL via BEGINLIBPATH is different: \n\t",
                 fail,
                 "\n\tYou may need to manipulate global BEGINLIBPATH"
                    " and LIBPATHSTRICT"
                    "\n\tso that the other copy is loaded via"
                    BEGINLIBPATH.");
    }
    return handle;
}

int
main(int argc, char **argv, char **env)
{
    main_t f;
    handler_t h;

    me = argv[0];
    /**/
    handle = load_perl_dll(PERL_DLL_BASENAME);

    if (DosQueryProcAddr(handle,
                         0,
                         "Perl_OS2_handler_install",
                         (PFN*)&h))
        die_with(PERL_DLL_BASENAME,
                 ": DLL exports no symbol ",
                 "Perl_OS2_handler_install",
                 "");
    if ( !h((void *)"~installprefix", Perlos2_handler_perllib_from)
         || !h((void *)"~dll", Perlos2_handler_perllib_to)
         || !h((void *)"~dll/sh/ksh.exe", Perlos2_handler_perl_sh) )
        die_with(PERL_DLL_BASENAME,
                 ": Can't install @INC manglers",
                 "",
                 "");
    if (DosQueryProcAddr(handle, 0, "dll_perlmain", (PFN*)&f))
        die_with(PERL_DLL_BASENAME,
                 ": DLL exports no symbol ",
                 "dll_perlmain",
                 "");
    return f(argc, argv, env);
}

Вопросы и ответы по сборке

Некоторые / стали \ в pdksh.

У вас очень старая версия pdksh. См. "Предварительные требования".

'errno' - неразрешенная внешняя ссылка

У вас нет безопасной для многопоточности библиотеки db.lib. См. "Предварительные требования".

Проблемы с tr или sed

сообщаются при использовании очень старых версий tr и sed.

Некоторая проблема (забыл какая ;-)

У вас старая версия perl.dll в вашем каталоге LIBPATH, из-за которой произошла ошибка сборки расширений.

Библиотека ... не найдена

Вы не выполнили omflibs. См. "Предварительные требования".

Ошибка сегментации в make

Вы используете старую версию GNU make. См. "Предварительные требования".

Ошибка теста op/sprintf

Это может быть следствием ошибки в emx sprintf, которая была исправлена в 0.9d фикс 03.

Особенности (недостатки) порта для OS/2

setpriority, getpriority

Обратите внимание, что эти функции совместимы с *nix, но не с более старыми портами 94-95 годов. Приоритеты абсолютны, изменяются от 32 до -95, более низкий приоритет означает более высокую скорость. 0 — это приоритет по умолчанию.

ПРЕДУПРЕЖДЕНИЕ. Вызов getpriority для несуществующего процесса может заблокировать систему до исправления Warp3 fixpak22. Начиная с Warp3, Perl будет использовать обходной путь: он прерывает getpriority(), если процесс отсутствует. Это невозможно в старых версиях 2.*, и в любом случае существует проблема гонки.

system()

Многоаргументная форма system() позволяет использовать дополнительный числовой аргумент. Значение этого аргумента описано в OS2::Process.

При поиске программы для запуска Perl сначала просит ОС искать исполняемые файлы в PATH (OS/2 добавляет расширение .exe, если расширение отсутствует). Если не найдено, ищется скрипт с возможными расширениями в таком порядке: без расширения, .cmd, .btm, .bat, .pl. Если найден, Perl проверяет начало файла на наличие магических строк "#!" и "extproc ". Если найдены, Perl использует остальную часть первой строки как начало командной строки для запуска этого скрипта. Единственная обработка первой строки — извлечение аргументов (в настоящее время до 3) и игнорирование части пути в имени «интерпретатора», если его невозможно найти, используя полный путь.

Например, system 'foo', 'bar', 'baz' может привести Perl к поиску C:/emx/bin/foo.cmd, где первая строка будет

extproc /bin/bash    -x   -c

Если /bin/bash.exe не найден, тогда Perl ищет исполняемый файл bash.exe в PATH. Если он найден в C:/emx.add/bin/bash.exe, то вышеприведенный вызов system() преобразуется в

system qw(C:/emx.add/bin/bash.exe -x -c C:/emx/bin/foo.cmd bar baz)

Выполняется дополнительный перевод: вместо /bin/sh Perl использует жёстко заданную или настраиваемую оболочку (см. "PERL_SH_DIR").

Вышеописанный поиск «интерпретатора» рекурсивен: если исполняемый файл bash не найден, но bash.btm найден, Perl будет исследовать его первую строку и т. д. Единственное жёстко заданное ограничение на глубину рекурсии неявное: существует ограничение в 4 на количество дополнительных аргументов, вставленных перед фактическими аргументами, переданными в system(). В частности, если в «магических» первых строках не указаны дополнительные аргументы, то ограничение по глубине равно 4.

Если Perl определяет, что найденный исполняемый файл является типа PM, когда текущая сессия не PM, он запустит новый процесс в отдельной сессии необходимого типа. Для отключения этой «магии» вызовите OS2::Process.

ПРЕДУПРЕЖДЕНИЕ. Из-за описанной логики вам необходимо явно указать расширение .com, если это необходимо. Более того, если запрашивается исполняемый файл perl5.6.1, Perl не будет искать perl5.6.1.exe. [Это может измениться в будущем.]

extproc в первой строке

Если первые символы Perl-скрипта — "extproc ", эта строка обрабатывается как #!-строка, поэтому все переключатели в этой строке обрабатываются (дважды, если сценарий был запущен через cmd.exe). См. "DESCRIPTION" в perlrun.

Дополнительные модули:

OS2::Process, OS2::DLL, OS2::REXX, OS2::PrfDB, OS2::ExtAttr. Эти модули обеспечивают доступ к дополнительным числовым аргументам для system и к информации о работающем процессе, к DLL, содержащим функции с синтаксисом REXX, и к среде выполнения REXX, к базам данных OS/2 в формате .INI и к расширенным атрибутам.

Два дополнительных расширения Андрея Кайзера, OS2::UPM, и OS2::FTP, включены в каталог ILYAZ, дублирующийся на CPAN. Также доступны другие расширения, относящиеся к OS/2.

Встроенные методы:

File::Copy::syscopy

используется File::Copy::copy, см. File::Copy.

DynaLoader::mod2fname

используется DynaLoader для преобразования имен DLL.

Cwd::current_drive()

Самодокументирующаяся функция.

Cwd::sys_chdir(name)

оставляет диск без изменений.

Cwd::change_drive(name)

изменяет "текущий" диск.

Cwd::sys_is_absolute(name)

имеет букву диска и является корневым.

Cwd::sys_is_rooted(name)

имеет ведущий [/\\] (возможно, после буквы диска :).

Cwd::sys_is_relative(name)

изменяется в зависимости от текущей директории.

Cwd::sys_cwd(name)

Интерфейс к cwd из EMX. Используется Cwd::cwd.

Cwd::sys_abspath(name, dir)

Действительно очень неприятная функция для реализации. Возвращает абсолютное имя файла, которое имело бы name , если бы текущая директория была dir. Dir по умолчанию - текущая директория.

Cwd::extLibpath([type])

Получить текущее значение расширенного пути поиска библиотек. Если type присутствует и положительно, работает с END_LIBPATH, если отрицательно, работает с LIBPATHSTRICT, в противном случае с BEGIN_LIBPATH.

Cwd::extLibpath_set( path [, type ] )

Установить текущее значение расширенного пути поиска библиотек. Если type присутствует и положительно, работает с <END_LIBPATH>, если отрицательно, работает с LIBPATHSTRICT, в противном случае с BEGIN_LIBPATH.

OS2::Error(do_harderror,do_exception)

Возвращает undef если еще не вызывалась, в противном случае бит 1 установлен, если на предыдущем вызове do_harderror был включен, бит 2 установлен, если на предыдущем вызове do_exception был включен.

Эта функция включает/выключает всплывающие окна ошибок, связанные с аппаратными ошибками (диск не готов и т.п.), и программными ошибками.

Я не знаю способа узнать состояние всплывающих окон *до* первого вызова этой функции.

OS2::Errors2Drive(drive)

Возвращает undef если еще не вызывалась, в противном случае возвращает false, если ошибки не были запрошены для записи на жесткий диск, или букву диска, если это было запрошено.

Эта функция может перенаправить всплывающие окна ошибок, связанные с аппаратными ошибками (диск не готов и т.п.), и программными ошибками, в файл POPUPLOG.OS2 в корневой директории указанного диска. Переопределяет OS2::Error(), указанный отдельными программами. Аргумент undef отключит перенаправление.

Действует глобально, сохраняется после завершения работы приложения.

Я не знаю способа узнать состояние перенаправления всплывающих окон на диск *до* первого вызова этой функции.

OS2::SysInfo()

Возвращает хеш с системной информацией. Ключи хеша:

MAX_PATH_LENGTH, MAX_TEXT_SESSIONS, MAX_PM_SESSIONS,
MAX_VDM_SESSIONS, BOOT_DRIVE, DYN_PRI_VARIATION,
MAX_WAIT, MIN_SLICE, MAX_SLICE, PAGE_SIZE,
VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION,
MS_COUNT, TIME_LOW, TIME_HIGH, TOTPHYSMEM, TOTRESMEM,
TOTAVAILMEM, MAXPRMEM, MAXSHMEM, TIMER_INTERVAL,
MAX_COMP_LENGTH, FOREGROUND_FS_SESSION,
FOREGROUND_PROCESS
OS2::BootDrive()

Возвращает букву без двоеточия.

OS2::MorphPM(serve), OS2::UnMorphPM(serve)

Преобразует текущее приложение в приложение PM и обратно. Аргумент true означает, что будет обслуживаться настоящий цикл обработки сообщений. OS2::MorphPM() возвращает дескриптор очереди сообщений PM как целое число.

См. "Централизованное управление ресурсами" для получения дополнительных сведений.

OS2::Serve_Messages(force)

Вымышленный запрос на получение необработанных сообщений PM. Если force ложно, не будет отправлять сообщения, если настоящий цикл обработки сообщений известен. Возвращает количество полученных сообщений.

Завершается с сообщением "QUITing..." при получении сообщения WM_QUIT.

OS2::Process_Messages(force [, cnt])

Получение сообщений PM до создания/уничтожения окна. Если force ложно, не будет отправлять сообщения, если настоящий цикл обработки сообщений известен.

Возвращает изменение количества окон. Если cnt задан, он увеличивается на количество полученных сообщений.

Завершается с сообщением "QUITing..." при получении сообщения WM_QUIT.

OS2::_control87(new,mask)

то же, что и _control87(3) в EMX. Принимает целые числа в качестве аргументов, возвращает предыдущее слово управления сопроцессором как целое число. Только биты в new, которые присутствуют в mask, изменяются в слове управления.

OS2::get_control87()

получает слово управления сопроцессором как целое число.

OS2::set_control87_em(new=MCW_EM,mask=MCW_EM)

Вариант OS2::_control87() с значениями по умолчанию, подходящий для обработки маски исключений: если нет mask, используется только часть маски исключений new. Если нет new, отключаются все исключения с плавающей точкой.

См. "Недостатки" для получения дополнительной информации.

OS2::DLLname([how [, \&xsub]])

Предоставляет информацию о Perl DLL или DLL, содержащей C-функцию, связанную с &xsub. Значение how : по умолчанию (2): полное имя; 0: дескриптор; 1: имя модуля.

(Обратите внимание, что некоторые из них могут быть перемещены в разные библиотеки - со временем).

Переменные по умолчанию:

$OS2::emx_rev

числовое значение совпадает с _emx_rev в EMX, строковое значение совпадает с _emx_vprt (аналогично 0.9c).

$OS2::emx_env

аналогично _emx_env в EMX, число, аналогичное 0x8001.

$OS2::os_ver

число OS_MAJOR + 0.001 * OS_MINOR.

$OS2::is_aout

true, если Perl-библиотека скомпилирована в формате AOUT.

$OS2::can_fork

true, если текущий исполняемый файл - исполняемый файл AOUT EMX, поэтому Perl может выполнить fork. Не используйте это, используйте переносимую проверку $Config::Config{dfork}.

$OS2::nsyserror

Эта переменная (по умолчанию 1) управляет тем, будет ли содержимое $^E начинаться с идентификатора типа SYS0003. Если установлено в 0, то строковое значение $^E - это то, что доступно из файла сообщений OS/2. (Некоторые сообщения в этом файле имеют префикс типа SYS0003, некоторые нет.)

Недостатки

  • Поскольку flock(3) присутствует в EMX, но не работает, он эмулируется Perl. Чтобы отключить эмуляцию, установите переменную среды USE_PERL_FLOCK=0.

  • Вот список вещей, которые могут быть "сломаны" в EMX (из документации EMX):

    • Функции recvmsg(3), sendmsg(3) и socketpair(3) не реализованы.

    • sock_init(3) не требуется и не реализована.

    • flock(3) еще не реализован (пустая функция). (В Perl есть обходной путь.)

    • kill(3): Специальное обращение с PID=0, PID=1 и PID=-1 не реализовано.

    • waitpid(3):

      WUNTRACED
              Not implemented.
      waitpid() is not implemented for negative values of PID.

    Обратите внимание, что kill -9 не работает с текущей версией EMX.

  • См. "Текстовые дескрипторы файлов".

  • Unix-сокеты в OS/2 находятся в псевдофайловой системе /sockets/.... Чтобы избежать отказа от создания сокета с именем другой формы, "/socket/" добавляется к имени сокета (если оно не начинается с этого уже).

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

  • По-видимому, IBM использовала компилятор (в какой-то период времени около '95?), который изменяет маску FP влево и вправо. Это не *такое* плохое решение для программ IBM, но тот же компилятор использовался для DLL, используемых в приложениях общего назначения. При использовании этих DLL состояние флагов с плавающей точкой в приложении непредсказуемо.

    Что гораздо хуже, некоторые DLL изменяют флаги с плавающей точкой при вызове _DLLInitTerm() (например, TCP32IP). Это означает, что даже если вы не вызываете ни одну функцию в DLL, сам факт загрузки этой DLL сбросит ваши флаги. Что еще хуже, тот же компилятор использовался для компиляции некоторых DLL-модулей HOOK. Учитывая, что DLL HOOK выполняются в контексте *всех* приложений в системе, это означает полную непредсказуемость флагов с плавающей точкой на системах, использующих такие DLL HOOK. Например, GAMESRVR.DLL от DIVE origin изменяет флаги с плавающей точкой при каждом записи в TTY приложений VIO (окно в текстовом режиме).

    Другие (не полностью отлаженные) ситуации, когда меняются флаги FP, включают некоторые драйверы видео (?), и некоторые операции, связанные с созданием окон. У людей, которые работают с OpenGL, может быть больше опыта в этом.

    Perl обычно используется в ситуации, когда все исключения с плавающей точкой игнорируются, как и по умолчанию в EMX. Если они не игнорируются, некоторые доброкачественные программы Perl получат SIGFPE и погибнут ужасной смертью.

    Для обхода этой проблемы Perl использует два хакерских приема. Они помогают только против *одного* типа повреждений: флагов FP, изменившихся при загрузке DLL.

    Один из хаков - отключение исключений с плавающей точкой при запуске Perl (как и по умолчанию в EMX). Это помогает только с DLL, связанными во время компиляции, которые изменяют флаги до того, как main() успел вызваться.

    Другой хак - восстановление флагов FP после вызова dlopen(). Это помогает против аналогичного повреждения, нанесенного DLL _DLLInitTerm() во время выполнения. В настоящее время нет способа отключить эти хаки.

Изменения

Perl изменяет некоторые стандартные вызовы C-библиотек следующим образом:

popen

my_popen использует sh.exe, если требуется оболочка, см. "PERL_SH_DIR".

tmpnam

создается с помощью переменной среды TMP или TEMP через tempnam.

tmpfile

Если текущая директория недоступна для записи, файл создаётся с модифицированным tmpnam, поэтому может возникнуть гонка ресурсов.

ctermid

имитация.

stat

os2_stat обрабатывает /dev/tty и /dev/con как специальные случаи.

mkdir, rmdir

эти функции EMX не работают, если путь содержит конечный /. Perl содержит обходной путь для этого.

flock

Поскольку flock(3) присутствует в EMX, но не функционален, он эмулируется perl. Чтобы отключить эмуляцию, установите переменную среды USE_PERL_FLOCK=0.

Идентификация DLL

Все DLL, построенные с текущими версиями Perl, содержат строки ID, определяющие имя расширения, его версию и требуемую версию Perl для этой DLL. Запустите bldlevel DLL-name для получения этой информации.

Централизованное управление ресурсами

Поскольку для вызова определённых API OS/2 необходимо иметь правильно инициализированный подсистему Win, расширения, специфичные для OS/2, могут потребовать получения HAB и HMQ. Если расширение будет делать это самостоятельно, другое расширение может не пройти инициализацию.

Perl обеспечивает централизованное управление этими ресурсами:

HAB

Для получения HAB расширение должно вызвать hab = perl_hab_GET() в C. После этого вызова Perl_hab может быть доступен как Perl_hab. Нет необходимости освобождать HAB после его использования.

Если по каким-либо причинам perl.h не может быть включён, используйте

extern int Perl_hab_GET(void);

вместо этого.

HMQ

Есть два случая:

  • расширению требуется HMQ только потому, что некоторые API в противном случае не будут работать. Используйте serve = 0 ниже.

  • расширению требуется HMQ так как оно хочет участвовать в цикле событий PM. Используйте serve = 1 ниже.

Для получения HMQ расширение должно вызвать hmq = perl_hmq_GET(serve) в C. После этого вызова hmq может быть доступен как Perl_hmq.

Чтобы сигнализировать Perl о том, что HMQ больше не нужен, вызовите perl_hmq_UNSET(serve). Процесс Perl автоматически превратится/превратится обратно в процесс PM, если HMQ необходим/не необходим. Perl автоматически включит/выключит сообщения WM_QUIT во время завершения работы, если очередь сообщений обслуживается/не обслуживается.

ПРИМЕЧАНИЕ. Если во время завершения работы есть очередь сообщений, которая не отключила WM_QUIT и не обработала полученное сообщение WM_QUIT, завершение автоматически отменяется. Не вызывайте perl_hmq_GET(1), если не собираетесь обрабатывать сообщения упорядоченным образом.

Обработка ошибок, сообщённых API OS/2

Существует две основные конвенции (полезно назвать их Dos* и Win* - хотя эта часть сигнатуры функции не всегда определяется именем API) для сообщения об ошибках API OS/2. Большинство API Dos* сообщают код ошибки в качестве результата вызова (так, 0 означает успех, и существует много типов ошибок). Большинство API Win* сообщают успех/неуспех через результат, являющийся TRUE/FALSE; чтобы определить причину неудачи, следует вызвать API WinGetLastError().

Некоторые точки входа Win* также перегружают «осмысленное» возвращаемое значение индикатором ошибки; возвращаемое значение 0 указывает на ошибку. Однако некоторые другие точки входа Win* перегружают вещи ещё больше, и возвращаемое значение 0 может означать успешный вызов, возвращающий действительное значение 0, а также условие ошибки; в случае возвращаемого значения 0 следует вызвать API WinGetLastError(), чтобы отличить успешный вызов от неудачного.

По соглашению, все вызовы API OS/2 должны указывать на ошибки, сбрасывая $^E. Все доступные в Perl функции, которые вызывают API OS/2, можно разделить на два класса: некоторые вызывают die(), когда возникает ошибка API, другие сообщают об ошибке через ложное возвращаемое значение (конечно, это не касается функций, доступных в Perl, которые ожидают ошибки вызова API OS/2, имея обходные пути).

Очевидно, в случае последнего типа сигнатуры API OS/2 для пользователей будет удобнее, если ошибка сигнализируется с помощью die(): нет необходимости проверять $^E, чтобы узнать, что-то пошло не так. Однако, если по какой-либо причине это решение нежелательно, код должен сбросить $^E в 0 перед выполнением этого вызова API OS/2, чтобы вызывающий эту доступную в Perl функцию имел возможность отличить значение возврата 0 от успеха от ошибки. (Можно вернуть undef в качестве альтернативного способа сообщения об ошибке.)

Макросы для упрощения этого типа распространения ошибок

CheckOSError(expr)

Возвращает true при ошибке, устанавливает $^E. Ожидается, что expr() будет вызовом API стиля Dos*.

CheckWinError(expr)

Возвращает true при ошибке, устанавливает $^E. Ожидается, что expr() будет вызовом API стиля Win*.

SaveWinError(expr)

Возвращает expr, устанавливает $^E из WinGetLastError(), если expr ложно.

SaveCroakWinError(expr,die,name1,name2)

Возвращает expr, устанавливает $^E из WinGetLastError(), если expr ложно, и вызывается die(), если die и $^E истинны. Сообщение для die() - это конкатенированные строки name1 и name2, разделенные ": " из содержимого $^E.

WinError_2_Perl_rc

Устанавливает Perl_rc в возвращаемое значение WinGetLastError().

FillWinError

Устанавливает Perl_rc в возвращаемое значение WinGetLastError(), и устанавливает $^E в соответствующее значение.

FillOSError(rc)

Устанавливает Perl_rc в rc, и устанавливает $^E в соответствующее значение.

Загрузка DLL и порядковых номеров в DLL

Некоторые DLL присутствуют только в некоторых версиях OS/2 или в некоторых конфигурациях OS/2. Некоторые экспортируемые точки входа присутствуют только в DLL, поставляемых с некоторыми версиями OS/2. Если эти DLL и точки входа были связаны напрямую для исполняемого файла Perl/DLL или из расширений Perl, этот двоичный файл будет работать только с указанными версиями/настройками. Даже если эти точки входа не требовались, загрузка исполняемого файла (или DLL) завершится неудачей.

Например, многие новые полезные API отсутствуют в OS/2 v2; многие API, связанные с PM, требуют DLL, которые недоступны при установке с флоппи-диска.

Чтобы сделать эти вызовы неудачными только при их выполнении, следует вызывать эти API через API динамической загрузки. В Perl есть подсистема для упрощения такого типа вызовов. Предоставлен большой набор точек входа для такой загрузки (см. entries_ordinals - и также PMWIN_entries - в os2ish.h). К этим порядковым номерам можно получить доступ через API:

CallORD(), DeclFuncByORD(), DeclVoidFuncByORD(),
DeclOSFuncByORD(), DeclWinFuncByORD(), AssignFuncPByORD(),
DeclWinFuncByORD_CACHE(), DeclWinFuncByORD_CACHE_survive(),
DeclWinFuncByORD_CACHE_resetError_survive(),
DeclWinFunc_CACHE(), DeclWinFunc_CACHE_resetError(),
DeclWinFunc_CACHE_survive(), DeclWinFunc_CACHE_resetError_survive()

Подробности об использовании этих функций см. в заголовочных файлах и C-коде в прилагаемых модулях OS/2.

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

Варианты Perl

Из-за особенностей OS/2 невозможно поместить все яйца в одну корзину (хотя среда EMX старается преодолеть эти ограничения, поэтому ситуация может как-то улучшиться). Распространение предоставляет 4 исполняемых файла для Perl:

perl.exe

Основной рабочий инструмент. Это исполняемый файл-химера: он компилируется как исполняемый файл типа a.out, но связан с динамической библиотекой типа omf perl.dll и динамической библиотекой CRT. Этот исполняемый файл является приложением VIO.

Он может загружать динамические расширения Perl и выполнять fork().

Примечание. Имейте в виду, что fork() необходим для открытия канала к себе.

perl_.exe

Это статически скомпилированный исполняемый файл типа a.out. Он не может загружать динамические расширения Perl. Исполняемый файл, поставляемый в двоичных распределениях, имеет множество предварительно скомпилированных расширений, поэтому вышеупомянутое ограничение важно только если вы используете расширения собственной разработки. Этот исполняемый файл является приложением VIO.

Это единственный исполняемый файл, который не требует OS/2. Друзья, запертые в мире M$ оценят тот факт, что этот исполняемый файл работает под DOS, Win0.3*, Win0.95 и WinNT с соответствующим расширителем. См. "Другие ОС".

perl__.exe

Этот исполняемый файл такой же, как perl___.exe, но это приложение PM.

Примечание. Обычно (если не перенаправлено явно во время запуска) STDIN, STDERR и STDOUT приложения PM перенаправляются в nul. Однако их можно увидеть, если запустить perl__.exe из программы PM, которая эмулирует окно консоли, например, режим оболочки Emacs или EPM. Таким образом, можно использовать отладчик Perl (см. perldebug) для отладки приложения PM (но будьте осторожны с блокировками цикла обработки сообщений - это не сработает, если у вас есть очередь сообщений для обработки, если вы не включите обработку в функцию getc() отладчика).

Другой способ увидеть вывод программы PM - запустить её как

pm_prog args 2>&1 | cat -

с оболочкой отличной от cmd.exe, чтобы не создавать связь между сеансом VIO и сеансом pm_porg. (Такая связь закрывает окно VIO.) Например, это работает с sh.exe - или с Perl!

open P, 'pm_prog args 2>&1 |' or die;
print while <P>;

Вариант perl__.exe требуется, если вы хотите запустить свою программу без окна VIO, но не detach (запустите help detach для получения дополнительной информации). Очень полезно для расширений, использующих PM, например, Perl/Tk или OpenGL.

Обратите также внимание, что различия между исполняемыми файлами PM и VIO заключаются только в поведении по умолчанию. Можно запустить любой исполняемый файл в любом типе сессии, используя ключи /fs, /pm или /win команды start (CMD.EXE или аналогичной оболочки). В качестве альтернативы можно использовать числовой первый аргумент функции system Perl (см. OS2::Process).

perl___.exe

Это исполняемый файл в формате omf, динамически связанный с perl.dll и CRT DLL. Мне неизвестны преимущества этого исполняемого файла по сравнению с perl.exe, но он не может использовать функцию fork(). Ну, одно преимущество заключается в том, что процесс сборки не такой запутанный, как с perl.exe.

Это приложение VIO.

Почему такие странные имена?

Поскольку Perl обрабатывает строку #! (см. "DESCRIPTION" в perlrun, "Команды переключения" в perlrun, "Скрипт Perl не найден в вводе" в perldiag), он должен знать, когда программа является Perl. Существует некоторая соглашение об именовании, которое позволяет Perl различать правильные строки и неправильные. Вышеперечисленные имена — почти единственные разрешенные соглашением об именовании, которые не содержат цифр (у которых совершенно другое семантическое значение).

Почему динамическая компоновка?

Ну, наличие нескольких исполняемых файлов, динамически связанных с одной большой библиотекой, имеет свои преимущества, но это не оправдывает дополнительных усилий по его компиляции. Причина заключается в сложной для разработчиков, но очень быстрой и удобной для пользователей «жесткой» динамической компоновке, используемой в OS/2.

Есть две отличительные особенности модели динамической компоновки OS/2: во-первых, все ссылки на внешние функции разрешаются на этапе компиляции; во-вторых, нет исправления ссылок DLL во время выполнения после их загрузки в память. Первое свойство является огромным преимуществом по сравнению с другими моделями: оно предотвращает конфликты, когда несколько DLL, используемых приложением, экспортируют записи с одинаковым именем. В таких случаях «другие» модели динамической компоновки просто выбирают между этими двумя точками входа, используя какой-то случайный критерий — с предсказуемыми катастрофическими результатами. Но именно второе свойство требует создания perl.dll.

Таблицы адресов DLL исправляются только один раз при их загрузке. Адреса точек входа в DLL гарантированно одинаковы для всех программ, использующих одну и ту же DLL. Это устраняет исправление во время выполнения — после загрузки DLL ее код становится только для чтения.

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

Однако динамически загружаемый Perl-расширение вынужден использовать некоторые символы из исполняемого файла perl, например, для того, чтобы знать, как найти аргументы для функций: аргументы находятся в внутренней стеке вычислений perl. Решение заключается в том, чтобы поместить основной код интерпретатора в DLL, а файл .EXE просто загружает эту DLL в память и предоставляет аргументы командной строки. Расширение DLL не может ссылаться на символы в файле .EXE, но у него нет проблем со ссылками на символы в файле .DLL.

Это значительно увеличивает время загрузки приложения (а также сложность компиляции). Поскольку интерпретатор находится в DLL, C RTL фактически вынужден находиться в DLL также (иначе расширения не смогут использовать CRT). Существуют некоторые преимущества, если вы используете разные версии perl, такие как одновременный запуск perl.exe и perl__.exe: они используют общую память perl.dll.

ПРИМЕЧАНИЕ. Существует один дополнительный эффект, который делает DLL более затратными: DLL загружаются в общую область памяти, которая является ограниченным ресурсом, учитывая барьер в 512 МБ «стандартной» виртуальной памяти OS/2. Код файлов .EXE также используется всеми процессами, которые используют конкретный .EXE, но они «делятся в частном адресном пространстве процесса»; это возможно, потому что адрес, по которому загружаются различные секции файла .EXE, определяется на этапе компиляции, поэтому все процессы загружают эти секции по тем же адресам, и исправление внутренних ссылок внутри .EXE не требуется.

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

Почему сборка химеры?

Текущая среда EMX не позволяет DLL, скомпилированным в формате Unixish a.out, экспортировать символы для данных (или, по крайней мере, некоторых типов данных). Это вынуждает использовать стиль компиляции omf для perl.dll.

Текущая среда EMX не позволяет файлам .EXE, скомпилированным в формате omf , использовать fork(). fork() необходим для ровно трех операций Perl:

  • явный fork() в скрипте,

  • open FH, "|-"

  • open FH, "-|", другими словами, открытие каналов для себя.

Хотя эти операции не являются вопросом жизни и смерти, они необходимы для многих полезных скриптов. Это вынуждает использовать стиль компиляции a.out для perl.exe.

СРЕДА

Здесь перечислены переменные среды, которые являются либо специфичными для OS/2, DOS и Win*, либо более важными в OS/2, чем в других ОС.

PERLLIB_PREFIX

Специфично для порта EMX. Должно иметь вид

path1;path2

или

path1 path2

Если начало некоторого предопределённого пути совпадает с path1, оно заменяется на path2.

Следует использовать, если библиотека perl перемещена из стандартного расположения в предпочтение PERL(5)LIB, так как это не оставит неправильных записей в @INC. Например, если скомпилированная версия perl ищет @INC в f:/perllib/lib, а вы хотите установить библиотеку в h:/opt/gnu, сделайте

set PERLLIB_PREFIX=f:/perllib/lib;h:/opt/gnu

Это заставит Perl с предварительно определённым @INC

f:/perllib/lib/5.00553/os2
f:/perllib/lib/5.00553
f:/perllib/lib/site_perl/5.00553/os2
f:/perllib/lib/site_perl/5.00553
.

использовать следующий @INC:

h:/opt/gnu/5.00553/os2
h:/opt/gnu/5.00553
h:/opt/gnu/site_perl/5.00553/os2
h:/opt/gnu/site_perl/5.00553
.

PERL_BADLANG

Если 0, perl игнорирует setlocale(), возвращающее ошибку. Может быть полезно с некоторыми странными локаль.

PERL_BADFREE

Если 0, perl не будет предупреждать о ненужном free(). С более старыми версиями perl это может быть полезно в сочетании с модулем DB_File, который был глючным при динамической компоновке и построении OMF.

Не следует устанавливать с более новыми версиями Perl, так как это может скрыть некоторые реальные проблемы.

PERL_SH_DIR

Специфично для порта EMX. Указывает директорию части местоположения sh.exe.

USE_PERL_FLOCK

Специфично для порта EMX. Поскольку flock(3) присутствует в EMX, но не функционален, он эмулируется perl. Чтобы отключить эмуляцию, установите переменную среды USE_PERL_FLOCK=0.

TMP или TEMP

Специфично для порта EMX. Используется в качестве места хранения временных файлов.

Эволюция

Здесь перечислены основные изменения, которые могут вас удивить.

Файловые дескрипторы в текстовом режиме

Начиная с версии 5.8, Perl использует встроенный уровень перевода для файлов в текстовом режиме. Это заменяет эффективную проверенную версию EMX некоторым кодом, который лучше всего можно охарактеризовать как «быстрый хак».

В дополнение к возможным ошибкам и невозможности отслеживать изменения в политике перевода с помощью переключателей включения/выключения перевода TERMIO, это вносит серьезное несовместимое изменение: раньше sysread() для файловых дескрипторов в текстовом режиме проходил через слой перевода, теперь нет.

Приоритеты

setpriority и getpriority несовместимы с более ранними портами Андрея Кайзера. См. "setpriority, getpriority".

Изменение имён DLL: до 5.6.2

С выпуском 5.003_01 динамически загружаемые библиотеки должны быть пересобраны при компиляции другой версии Perl. В частности, DLL (включая perl.dll) теперь создаются с именами, содержащими контрольную сумму, что позволяет обойти схему кэширования DLL в OS/2.

Возможно, можно написать простое решение, которое

  • найдёт старые DLL, просматривая старый @INC;

  • изменит имена в соответствии со схемой нового perl и скопирует DLL в эти имена;

  • изменит внутренние таблицы LX DLL, чтобы отразить изменение имени (вероятно, не требуется для DLL расширений Perl, так как внутренние кодированные имена не используются для «специфических» DLL, они используются только для «глобальных» DLL).

  • изменит внутренние таблицы IMPORT и изменит имя «старой» perl????.dll на «новую» perl????.dll.

Изменение имён DLL: 5.6.2 и далее

На самом деле изменение имён расширений DLL было сделано из-за непонимания модели динамической загрузки OS/2. OS/2 (эффективно) поддерживает две разные таблицы загруженных DLL:

Глобальные DLL

те, которые загружаются по имени из LIBPATH; включая те, которые связаны во время компоновки;

специфические DLL

загружаются по полному имени.

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

Есть/была небольшая тонкость, которая делает эту схему хрупкой: что делать с DLL, загруженными из

BEGINLIBPATH и ENDLIBPATH

(которые зависят от процесса)

. из LIBPATH

что эффективно зависит от процесса (хотя LIBPATH одинаково для всех процессов).

Если LIBPATHSTRICT не установлено в T (и ядро после 2000/09/01), такие DLL считаются глобальными. При загрузке глобальной DLL сначала ищется в таблице уже загруженных глобальных DLL. Из-за этого тот факт, что один исполняемый файл загрузил DLL из BEGINLIBPATH и ENDLIBPATH, или . из LIBPATH может повлиять на какую DLL загрузится, когда другой исполняемый файл запросит DLL с тем же именем. Это причина изменения имени DLL perl по версиям.

END_OF_DOCUMENT_MARKER

Поскольку DLL-расширения Perl всегда загружаются с полным путем, нет необходимости изменять их имена специфичным для версии способом: их каталог уже отражает соответствующую версию Perl, а @INC учитывает бинарную совместимость со старыми версиями. Начиная с 5.6.2 схема изменения имен закреплена такой же, как для Perl 5.005_53 (такой же, как в популярном двоичном выпуске). Таким образом, новые версии Perl смогут распознать имена старых DLL-расширений, если @INC позволяет найти их каталоги.

Однако это все равно не гарантирует, что эти DLL могут быть загружены. Причина заключается в изменении имени DLL Perl. И поскольку расширения DLL связываются с DLL Perl, расширения DLL для старых версий загружали бы старую DLL Perl и, скорее всего, бы зависли (так как данные в этой DLL не инициализированы должным образом).

Существует частичное решение (которое можно сделать полным с помощью более новых ядер OS/2): создать DLL-перенаправитель с тем же именем, что и DLL старой версии Perl, которая перенаправляет точки входа в DLL новой версии Perl. Сделайте эту DLL доступной (например) в BEGINLIBPATH нового исполняемого файла Perl. Когда новый исполняемый файл обращается к старым DLL-расширениям Perl, они запросят старую DLL Perl по имени, получат вместо нее перенаправитель, поэтому фактически свяжутся с текущей (новой) DLL Perl.

Это может нарушиться двумя способами:

  • Запущен старый исполняемый файл Perl, когда новый исполняемый файл загрузил расширение, скомпилированное для старого исполняемого файла (упс!). В этом случае старый исполняемый файл получит DLL-перенаправитель вместо старой DLL Perl, поэтому будет связан с новой DLL Perl. Хотя это не является непосредственно фатальным, он будет вести себя так же, как и новый исполняемый файл. Это разрушает всю цель явного запуска старого исполняемого файла.

  • Новый исполняемый файл загружает расширение, скомпилированное для старого исполняемого файла, когда запущен старый исполняемый файл Perl. В этом случае расширение не получит перенаправитель — с фатальными последствиями.

С поддержкой LIBPATHSTRICT это можно обойти — если один из DLL не запущен из . из LIBPATH (я не знаю, влияет ли LIBPATHSTRICT на этот случай).

ПРИМЕЧАНИЕ. Если более новые ядра позволяют . в BEGINLIBPATH (старые не позволяют), эта проблема не может быть полностью устранена. (Оказывается, что по состоянию на начало 2002 года . не разрешено, но .\. — да, и это имеет тот же эффект).

ПРИМЕЧАНИЕ. LIBPATHSTRICT, BEGINLIBPATH и ENDLIBPATH не являются переменными среды, хотя cmd.exe эмулирует их в SET ... строках. Из Perl они могут быть доступны по ссылкам Cwd::extLibpath и Cwd::extLibpath_set.

Генерация DLL-перенаправителя

Предположим, что старая DLL называется perlE0AC.dll (как одна для 5.005_53), а новая версия — 5.6.1. Создайте файл perl5shim.def-leader со следующим содержимым:

LIBRARY 'perlE0AC' INITINSTANCE TERMINSTANCE
DESCRIPTION '@#perl5-porters@perl.org:5.006001#@ Perl module for 5.00553 -> Perl 5.6.1 forwarder'
CODE LOADONCALL
DATA LOADONCALL NONSHARED MULTIPLE
EXPORTS

изменив версии/имена по мере необходимости. Запустите

perl -wnle "next if 0../EXPORTS/; print qq(  \"$1\")
                                         if /\"(\w+)\"/" perl5.def >lst

в каталоге построения Perl (чтобы сделать DLL меньше, замените perl5.def на файл определения для более старой версии Perl, если он есть).

cat perl5shim.def-leader lst >perl5shim.def
gcc -Zomf -Zdll -o perlE0AC.dll perl5shim.def -s -llibperl

(проигнорируйте несколько warning L4085).

Потоки

Начиная с выпуска 5.003_01 perl связан с многопоточной DLL C RTL. Если сам perl не скомпилирован с поддержкой многопоточности, то и malloc() perl не будет многопоточным. Однако расширения могут использовать несколько потоков на свой страх и риск.

Это было необходимо для компиляции Perl/Tk для XFree86-OS/2 "из коробки" и связи с DLL других полезных библиотек, которые обычно компилируются с -Zmt -Zcrtdll.

Вызовы внешних программ

По популярному требованию вызов внешних программ perl был изменен по сравнению с портом Андрэаса Кайзера. Если perl нужно вызвать внешнюю программу через оболочку, будет вызван f:/bin/sh.exe, или любая другая замена, см. "PERL_SH_DIR".

Таким образом, вам также потребуется копия sh.exe (я использую одну из pdksh). Путь F:/bin выше автоматически устанавливается во время сборки до правильного значения на машине сборки, но может быть переопределён во время выполнения.

Причины: в результате соглашения по perl5-porters было решено, что perl должен использовать одну неизменяемую оболочку на платформу. Очевидные варианты для OS/2 — cmd.exe и sh.exe. Если бы perl сам создавал оболочку, это было бы невозможно с cmd.exe в качестве оболочки, поэтому я выбрал sh.exe. Это обеспечивает почти 100% совместимость со скриптами из *nix. В качестве дополнительного преимущества это работает и в DOS, если вы используете DOS-совместимую версию pdksh (см. "Требования").

Недостатки: в настоящее время sh.exe pdksh вызывает внешние программы через fork()/exec(), а exec() в OS/2 не работает. Exec() эмулируется EMX с помощью асинхронного вызова, в то время как вызывающая программа ожидает завершения дочернего процесса (чтобы создать иллюзию, что pid не изменилось). Это означает, что создается 1 дополнительная копия sh.exe, активная через fork()/exec(), что может привести к использованию дополнительных ресурсов системы (даже если мы не учитываем дополнительную работу, необходимую для fork()ing).

Обратите внимание, что эта проблема сейчас менее актуальна, поскольку мы не запускаем sh.exe, если это не требуется (обнаружены метасимволы).

Вы всегда можете явно запустить cmd.exe с помощью

system 'cmd', '/c', 'mycmd', 'arg1', 'arg2', ...

Если вам нужно использовать cmd.exe и вы не хотите вручную редактировать тысячи ваших скриптов, долгосрочное решение, предложенное в p5-p, заключается в наличии директивы

use OS2::Cmd;

которая переопределит system(), exec(), ``, и open(,'...|'). В текущей версии perl вы можете переопределить только system(), readpipe() — явную версию ``, и, возможно, exec(). Код заменит вызов system() с одним аргументом на CORE::system('cmd.exe', '/c', shift).

Если у вас есть рабочий код для OS2::Cmd, пришлите его мне, я включу его в дистрибутив. Мне не нужен такой модуль, поэтому я не могу его протестировать.

Подробности текущей ситуации с вызовом внешних программ см. в разделе "Запуск программ OS/2 (и DOS) в Perl". Заметим несколько особенностей:

  • Внешние скрипты могут вызываться по своему имени без расширения. Perl будет пробовать те же расширения, что и при обработке параметра командной строки -S.

  • Внешние скрипты, начинающиеся с #! или extproc будут выполняться непосредственно, без вызова оболочки, вызывая программу, указанную в остальной части первой строки.

Выделение памяти

Perl использует свой собственный malloc() в OS/2 — интерпретаторы обычно ограничены malloc для скорости, но perl нет, так как его malloc очень быстрый. Тесты производительности, настроенные для использования памяти Perl, показывают, что malloc Perl в 5 раз быстрее, чем EMX.

Сочетание malloc() Perl и жёсткого разрешения имён DLL создаёт особую проблему с функциями библиотек, которые ожидают, что их возвращаемое значение будет освобождено system's free(). Чтобы облегчить расширения, которым нужно вызывать такие функции, функции выделения памяти системы все ещё доступны с префиксом emx_ добавленным. (В настоящее время это только для DLL perl, оно должно вскоре распространиться и на perl_.exe.)

Потоки

Можно скомпилировать perl с поддержкой потоков, указав параметр -D usethreads в Configure. В настоящее время поддержка потоков в OS/2 находится на очень предварительной стадии.

Основные проблемы:

COND_WAIT

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

os2.c

использует несколько статических переменных в OS/2-специфических функциях. (Нужно перенести в структуру каждого потока или сериализовать?)

Обратите внимание, что эти проблемы не должны отговаривать от экспериментов, поскольку у них низкая вероятность повлиять на небольшие программы.

ОШИБКИ

Это описание не обновляется часто (с 5.6.1?), см. ./os2/Changes для получения дополнительной информации.

АВТОР

Илья Захаревич, cpan@ilyaz.org

См. также

perl(1).

© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.28.3/perlos2

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API