Spec-Zone.ru › Perl 5.30

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
    • Некоторая проблема (забыл какая :-))
    • Библиотека… не найдена
    • Ошибка segfault в make
    • Ошибка теста op/sprintf
  • Специфические (ошибки) особенности порта OS/2
    • setpriority, getpriority
    • system()
    • extproc в первой строке
    • Дополнительные модули:
    • Встроенные методы:
    • Встроенные переменные:
    • Недостатки
    • Изменения
    • Идентификация DLL
    • Централизованное управление ресурсами
  • Разновидности Perl
    • perl.exe
    • perl_.exe
    • perl__.exe
    • perl___.exe
    • Почему такие странные имена?
    • Почему динамическая компоновка?
    • Почему сборка chimera?
  • СРЕДА
    • 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 и IBM's Visual Age C++ 3.5.

Копия 뷰ер для 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.

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

    Хотя использование стандартного 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 (см. "Другие ОС"). RSX не будет работать только с VCPI, как EMX, она требует DMPI.

Имея RSX и последнюю версию sh.exe, вы получаете полностью функциональную среду *nix-ish под 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, и документацию cmdref по extproc:

view perl perlrun
man perlrun
view cmdref extproc
help extproc

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

Также существуют бесконечные возможности использования исполняемых расширений 4os2, ассоциаций WPS и так далее... Однако, если вы используете оболочку *nixish (такую как 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()/pipe-open()/`` это скрипт со строкой «магии» #! или extproc , которая задает оболочку;

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

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

  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 программу из процесса PM Perl, 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, поэтому выполните grep в подкаталоге ./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, двоичный дистрибутив OS/2 perl разделен на 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.30.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, выполните

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) справкой.

Убедитесь, что каталог над каталогом со справочными страницами находится в нашей 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-сборки: 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' - неразрешенный внешний объект

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

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

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

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

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

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

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

Segfault в 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, когда текущая сессия не является таковой, он запустит новый процесс в отдельной сессии необходимого типа. Вызовите 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 и к расширенным атрибутам.

Два дополнительных расширения от Andreas Kaiser, 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)

означает, что есть буква диска и is_rooted.

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 равно false, не отправляет сообщения, если известен реальный цикл обработки сообщений. Возвращает количество полученных сообщений.

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

OS2::Process_Messages(force [, cnt])

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

Возвращает изменение количества окон. Если задан 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, если текущий исполняемый файл — EMX исполняемый файл в формате AOUT, так что 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-привязок. Поскольку DLL-привязки выполняются в контексте всех приложений в системе, это означает полную непредсказуемость флагов плавающей точки в системах, использующих такие DLL-привязки. Например, GAMESRVR.DLL от DIVE изменяет флаги плавающей точки при каждом записи в терминал 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, имеют идентификационные строки, указывающие имя расширения, его версию и версию 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, скомпилированным с помощью формата Unix a.out, экспортировать символы для данных (или, по крайней мере, некоторых типов данных). Это вынуждает компиляцию perl.dll в стиле omf.

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

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

  • open FH, "|-"

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

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

Окружение

Здесь перечислены переменные среды, которые являются либо специфичными для 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 DLL.

Поскольку 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(), и в OS/2 нет работающей функции exec(). exec() эмулируется EMX асинхронным вызовом, в то время как вызывающий процесс ожидает завершения дочернего процесса (чтобы симулировать, что pid не изменилось). Это означает, что sh.exe создается дополнительная копия, активная через fork()/exec(), что может привести к некоторому использованию ресурсов системы (даже если мы не учитываем дополнительную работу, необходимую для fork()).

Обратите внимание, что эта проблема менее актуальна сейчас, когда мы не запускаем 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 лучше на 5%.

Сочетание собственного malloc() Perl и строгого разрешения имен DLL создает особую проблему с функциями библиотек, которые ожидают, что их возвращаемое значение будет освобождено системой 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.30.3/perlos2

Spec-Zone.ru

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