Spec-Zone.ru › Perl 5.36

perlos2

СОДЕРЖАНИЕ

  • НАЗВАНИЕ
  • СИНOPSIS
  • ОПИСАНИЕ
    • Целевая аудитория
    • Другие операционные системы
    • Предварительные требования
    • Запуск программ 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.

СИНOPSIS

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

man perlos2
view perl perlos2
explorer perlos2.html
info perlos2

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

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

Копия просмотрщика Win* включена в пакет «Just add OS/2 Warp»

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

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

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

ОПИСАНИЕ

Целевая аудитория

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

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

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

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

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

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

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

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

Поскольку порт 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, поэтому вы вынуждены использовать переключатель Perl -S, а ваш скрипт должен находиться в 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()/pipe-open()/``, представляет собой скрипт со строкой "магии" #! или строкой extproc, которая указывает оболочку;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Не могу встроить Perl в свою программу или использовать perl.dll из своей программы.

Ваша программа скомпилирована под EMX с использованием -Zmt -Zcrtdll?

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

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

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

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

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

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

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

Невозможно запустить find.exe "pattern" file

Вся идея «стандартного API C для запуска приложений» заключается в том, что формы 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, двоичный дистрибутив OS/2 perl разделен на 11 компонентов. К сожалению, для обеспечения конфигурируемой установки двоичного файла пути к файлам в zip-архивах не являются абсолютными, а относительными к некоторому каталогу.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Руководство Perl в формате .INF
unzip perl_inf.zip -d d:/os2/book

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

Pdksh
unzip perl_sh.zip -d f:/bin

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

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

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

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

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

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

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

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

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

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

Файл OS/2 .INF

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

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

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

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

pod2ipf > perl.ipf

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

ipfc /inf perl.ipf

(Ожидайте много ошибок на обоих этапах.) Теперь перенесите её в каталог вашей БИБЛИОТЕКИ.

Текст

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

perldoc perlfunc
perldoc less
perldoc ExtUtils::MakeMaker

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

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

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

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

man perlfunc
man 3 less
man ExtUtils.MakeMaker

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

man perl

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

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

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

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

HTML

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

cd f:/perllib/lib/pod
pod2html

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

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

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

Файлы GNU info

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

Файлы PDF

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

LaTeX документы

можно создать с помощью pod2latex.

СОБРАНИЕ

Здесь обсуждается сборка Perl под OS/2.

Краткое изложение

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

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

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

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

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

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

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

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

find --version
sort --version

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

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

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

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

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

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

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

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

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

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

set BEGINLIBPATH .\.

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

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

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

link386

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

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

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

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

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

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

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

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

Распакуйте его так:

tar vzxf perl5.00409.tar.gz

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

Перейдите в каталог распаковки.

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

Вам нужно применить исправления в ./os2/diff.* так:

gnupatch -p0 < os2\diff.configure

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

Ручная правка

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

Компиляция

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

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

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

Теперь

make

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

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

Теперь запустите

make test

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

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

Множество bad free

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

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

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

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

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

perl t/harness

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

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

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

op/fs.t
18

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

25

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

op/stat.t

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

4

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

Установка скомпилированного perl

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

Запустите

make install

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

Запустите

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

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

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

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

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

make perl_

протестируйте и установите командой

make aout_test
make aout_install

Вручную поместите perl_.exe в каталог, указанный в вашем PATH.

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

make perl_dll

сначала.

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

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

Сборка должна проходить по-разному в зависимости от того, установлена ли версия perl, которую вы устанавливаете, уже на вашей системе и используется, или это новая версия, которая ещё не используется. Нижеприведённое описание предполагает, что версия новая, поэтому установка её DLL и файлов .pm не нарушит работу вашей системы, даже если некоторые промежуточные шаги ещё не полностью работают.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    CPAN> o conf index_expire 365
    CPAN> o conf commit

    Верните значение по умолчанию 1, когда вы закончите.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    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 -pu old new) внесённых вами исправлений, чтобы пользователи могли пересобрать вашу версию. Включите perl5.map, чтобы можно было использовать удалённую отладку.

  10. Поделитесь своими действиями с другими людьми. Расслабьтесь. Наслаждайтесь плодами вашего труда.

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

Создание настраиваемых файлов .EXE

Исполняемые файлы Perl можно легко пересобрать в любой момент. Более того, можно использовать интерфейс embedding (см. 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 и т. д.

Если вы чувствуете себя комфортно с интерфейсом embedding (см. 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. См. "Предварительные условия".

Ошибка segfault в make

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

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

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

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

setpriority, getpriority

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

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

system()

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

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

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

extproc /bin/bash    -x   -c

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

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

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

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

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

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

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

Если первые символы Perl-скрипта являются "extproc ", эта строка обрабатывается как #!-строка, поэтому все переключатели в этой строке обрабатываются (дважды, если скрипт был запущен через cmd.exe). См. "Описание" в 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 может выполнять виртуальное разделение. Не используйте это, используйте переносимую проверку для $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 (окна текстового режима) приложений.

    Некоторые другие (не полностью отлаженные) ситуации, когда изменяются флаги 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. Большинство Dos* API сообщают код ошибки в результате вызова (0 означает успех, и существуют различные типы ошибок). Большинство Win* API сообщают об успехе/ошибке через результат, являющийся 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().

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

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

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

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

Почему динамическая загрузка?

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

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

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

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

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

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

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

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

Почему chimera build?

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

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

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

  • open FH, "|-",

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

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

СРЕДА

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

PERLLIB_PREFIX

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

path1;path2

или

path1 path2

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

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

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

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

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

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

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

PERL_BADLANG

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

PERL_BADFREE

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

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

PERL_SH_DIR

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

USE_PERL_FLOCK

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

TMP или TEMP

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

Эволюция

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

Текстовые дескрипторы файлов

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

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

Приоритеты

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

Изменение имен DLL: до версии 5.6.2

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

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

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

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

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

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

Изменение имен DLL: 5.6.2 и выше

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

Глобальные DLL

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

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

загружаемые по полному имени.

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

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

BEGINLIBPATH и ENDLIBPATH

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

. из LIBPATH

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Потоки

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

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

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

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

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

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

Недостатки: в настоящее время sh.exe из pdksh вызывает внешние программы через fork()/exec(), а функция 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–2021 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.36.0/perlos2

Spec-Zone.ru

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