Spec-Zone.ru › Perl 5.38

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
    • Почему такие странные имена?
    • Почему динамическая загрузка?
    • Почему сборка химеры?
  • ОКРУЖЕНИЕ
    • 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 (?) (ссылка anyone?)) или поставляется с PC DOS 7.0 и IBM Visual Age C++ 3.5.

Копия просмотрщика Win* содержится в пакете «Просто добавьте OS/2 Warp»

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

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

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

ОПИСАНИЕ

Цель

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

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

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

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

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

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

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

Другие ОС

Поскольку порт Perl для OS/2 использует замечательную среду 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(1). Обратите внимание, что под 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 под DOS, например, fork, `` и операцию с каналами-open работают. Фактически, MakeMaker работает (для статической сборки), поэтому вы можете иметь среду разработки Perl под DOS.

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

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

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

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

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

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

HPFS

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

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

pdksh

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

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

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

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

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

perl foo.pl arg1 arg2 arg3

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

perl -my_opts foo.pl arg1 arg2 arg3

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

extproc perl -S -my_opts

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

foo arg1 arg2 arg3

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

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

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

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

view perl perlrun
man perlrun
view cmdref extproc
help extproc

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Perl будет запускать программы PM из процесса VIO (=текстового) Perl в отдельной сессии PM; обратное неверно: при запуске не-PM программы из процесса 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, поэтому найдите подкаталог ./t дерева сборки (а также файлы *.t в подкаталоге ./lib), чтобы узнать, как это сделать «правильно».

`` и операция с каналами-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 в вашем пути и запущенная среда EMX. Последнее означает, что если вы только установили EMX и внесли все необходимые изменения в Config.sys, вам может потребоваться перезагрузка. Проверьте работоспособность EMX, запустив

emxrev

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

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

PERL_BADLANG

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

PERL_BADFREE

см. «PERL_BADFREE».

Config.pm

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

То же замечание, что и выше. Кроме того, если этот каталог не является одним из каталогов в @INC (а @INC зависит от PERLLIB_PREFIX), вам нужно поместить этот каталог и подкаталог ./os2 в переменную PERLLIB или PERL5LIB. Не используйте PERL5LIB, если она не установлена. См. «ENVIRONMENT» в 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 документации, пригодной для просмотра в браузерах WWW, а также документации в десятках других форматов: 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* см. «SYNOPSIS».

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

pod2ipf > perl.ipf

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

ipfc /inf perl.ipf

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

Текстовый формат

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

perldoc perlfunc
perldoc less
perldoc ExtUtils::MakeMaker

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

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

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

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

man perlfunc
man 3 less
man ExtUtils.MakeMaker

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

man perl

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

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

Файлы 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 выполняется максимально чисто. Проверьте, что os2/perlrexx.cmd работает нормально.

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

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

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

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

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

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

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

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

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

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

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

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

    CPAN> o conf index_expire 365
    CPAN> o conf commit

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    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), такие вещи легко сделать, повторив шаги, описанные в "Создание исполняемых файлов с набором статически загруженных расширений" и выполнив более подробные изменения в функции 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 с теми же опциями, что и DLL Perl. Однако много функций будет работать, даже если исполняемый файл не является приложением 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);
}

Раздел часто задаваемых вопросов по сборке

Some / стали \ в pdksh.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

setpriority, getpriority

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

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

system()

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

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

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

extproc /bin/bash    -x   -c

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

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

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

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

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

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

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

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

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

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

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

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

File::Copy::syscopy

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

DynaLoader::mod2fname

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

Cwd::current_drive()

Самоочевидный.

Cwd::sys_chdir(name)

диск остаётся прежним.

Cwd::change_drive(name)

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

Cwd::sys_is_absolute(name)

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

Cwd::sys_is_rooted(name)

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

Cwd::sys_is_relative(name)

меняется с текущим каталогом.

Cwd::sys_cwd(name)

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

Cwd::sys_abspath(name, dir)

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

Cwd::extLibpath([type])

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

Cwd::extLibpath_set( path [, type ] )

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

OS2::Error(do_harderror,do_exception)

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

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

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

OS2::Errors2Drive(drive)

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

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

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

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

OS2::SysInfo()

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

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

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

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

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

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

OS2::Serve_Messages(force)

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

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

OS2::Process_Messages(force [, cnt])

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

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

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

OS2::_control87(new,mask)

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

OS2::get_control87()

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

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

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

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

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

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

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

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

$OS2::emx_rev

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

$OS2::emx_env

совпадает со значением _emx_env в EMX, число, аналогичное 0x8001.

$OS2::os_ver

число OS_MAJOR + 0.001 * OS_MINOR.

$OS2::is_aout

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

$OS2::can_fork

истина, если текущий исполняемый файл — это исполняемый файл 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 использовала компилятор (в какой-то период времени около 1995 года?), который менял маску FP справа налево. Это не так уж плохо для программ IBM, но тот же компилятор использовался для DLL, которые используются с приложениями общего назначения. При использовании этих DLL состояние флагов с плавающей точкой в приложении непредсказуемо.

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

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

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

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

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

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

Изменения

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

popen

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

tmpnam

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

tmpfile

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

ctermid

фиктивная реализация.

stat

os2_stat обрабатывает случаи /dev/tty и /dev/con.

mkdir, rmdir

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

flock

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

Определение DLL

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

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

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

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

HAB

Чтобы получить HAB, расширение должно вызвать hab = perl_hab_GET() в C. После выполнения этого вызова, 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, разделенные

view perl perlrun
man perlrun
view cmdref extproc
help extproc
содержимым $^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 и точки входа были связаны напрямую для исполняемого файла/DLL Perl или из расширений 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() нужен для открытия канала в себя.

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. Мне не известны преимущества этого исполняемого файла по сравнению с perl.exe, но он вообще не может создавать дочерние процессы. Ну, одно преимущество заключается в том, что процесс сборки не столь запутан, как с perl.exe.

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

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

Поскольку Perl обрабатывает строку #! (см. "DESCRIPTION" в perlrun, "Command Switches" в perlrun, "No Perl script found in input" в 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 МБ виртуальной памяти «стандартной» ОС/2. Код файлов .EXE также совместно используется всеми процессами, которые используют конкретный .EXE, но они «совместно используются в частном адресном пространстве процесса»; это возможно, потому что адрес, по которому загружаются разные секции файла .EXE, определяется во время компиляции, поэтому все процессы загружают эти секции по тем же адресам, и нет необходимости в исправлении внутренних ссылок внутри .EXE.

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

Почему сборка chimera?

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

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

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

  • open FH, "|-",

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

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

СРЕДА

Здесь перечислены переменные среды, которые являются либо специфичными для ОС/2, DOS и Win*, либо более важными в ОС/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() при ошибке. Может быть полезно с некоторыми странными locale.

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 в ОС/2.

Возможно создание простого обходного решения, которое

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

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

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

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

Изменение имен DLL: 5.6.2 и новее

На самом деле изменение имен расширений DLL было сделано из-за неправильного понимания модели динамической загрузки ОС/2. ОС/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 могут быть загружены. Причиной является изменение имени Perl DLL. И поскольку DLL расширений связаны с Perl DLL, DLL расширений для более старых версий будут загружать более старую Perl DLL и, скорее всего, завершатся ошибкой (так как данные в этой DLL не инициализированы должным образом).

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

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

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

  • Новый исполняемый файл загружает расширение, скомпилированное для старого исполняемого файла, когда запущен старый исполняемый файл 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

(ignore multiple warning L4085).

Потоки

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

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

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

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

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

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

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

Обратите внимание, что эта проблема менее актуальна сейчас, когда 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–2023 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.38.0/perlos2

Spec-Zone.ru

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