perlos2
СОДЕРЖАНИЕ
- ИМЯ
- СИНОПСИС
- ОПИСАНИЕ
- Часто задаваемые вопросы
- УСТАНОВКА
- Доступ к документации
- СБОРКА
- Сборка двоичного дистрибутива
- Сборка пользовательских .EXE файлов
- Вопросы и ответы по сборке
- Особенности (недостатки) порта под OS/2
- Варианты Perl
- ОКРУЖЕНИЕ
- Эволюция
- ОШИБКИ
- АВТОР
- СМОТРИ ТАКЖЕ
ИМЯ
perlos2 - Perl под OS/2, DOS, Win0.3*, Win0.95 и WinNT.
СИНОПСИС
Данный документ можно прочитать в следующих форматах:
man perlos2
view perl perlos2
explorer perlos2.html
info perlos2 чтобы перечислить некоторые (не все могут быть доступны одновременно), или его можно прочитать как есть: как README.os2 или pod/perlos2.pod.
Чтобы прочитать версию документации в формате .INF (крайне рекомендуется) вне OS/2, вам потребуется программа-просмотрщик от IBM (возможно, доступна на ftp-сайтах IBM (?) (ссылка?)) или поставляется с PC DOS 7.0 и Visual Age C++ 3.5 от IBM.
Копия просмотрщика для Win* содержится в пакете "Just add OS/2 Warp".
ftp://ftp.software.ibm.com/ps/products/os2/tools/jaow/jaow.zip в ?:\JUST_ADD\view.exe. Это даёт доступ к документации EMX в формате .INF (текстовая форма доступна в /emx/doc в дистрибутиве EMX). Также существует другой просмотрщик под названием xview.
Обратите внимание, что если у вас установлены lynx.exe или netscape.exe, вы можете переходить по ссылкам WWW в этом документе в формате .INF. Если у вас правильно установлена документация EMX, вы можете переходить по ссылкам на библиотеки (вам нужно убедиться, что view emxbook работает, установив переменную среды EMXBOOK, как описано в документации EMX).
ОПИСАНИЕ
Целевая платформа
Цель состоит в том, чтобы сделать OS/2 одной из наиболее поддерживаемых платформ для использования, создания и разработки Perl и приложений Perl, а также сделать Perl лучшим языком для использования под OS/2. Вторичная цель — попытаться заставить это работать и под DOS и Win* (но не слишком усердно).
Текущее состояние довольно близко к этой цели. Известные ограничения:
-
Некоторые программы *nix активно используют fork(); в большинстве полезных версий Perl для OS/2 (они собираются одновременно) это поддерживается; но некоторые версии этого не поддерживают (например, когда Perl вызывается из REXX). Использование fork() после использования динамически загружаемых расширений не будет работать с очень старыми версиями EMX.
-
Вам нужен отдельный исполняемый файл Perl perl__.exe (см. "perl__.exe"), если вы хотите использовать код PM в своём приложении (как Perl/Tk или OpenGL Perl модули) без наличия текстового окна.
Хотя использование стандартного perl.exe из текстового окна возможно, я сталкивался с случаями, когда это приводило к ухудшению стабильности системы. Использование perl__.exe предотвращает такое ухудшение.
-
Нет простого способа доступа к объектам WPS. Единственный известный способ — через
OS2::REXXиSOMрасширения (см. OS2::REXX, SOM). Однако у нас нет доступа к удобным методам Object-REXX. (Возможно ли это вообще? Мне не известен API Object-REXX.) РасширениеSOM(в настоящее время в альфа-тексте) может в конечном итоге устранить этот недостаток; однако из-за того, что DII не поддерживается модулемSOM, использованиеSOMне так удобно, как хотелось бы.
Пожалуйста, поддерживайте этот список актуальным, сообщив мне о других пунктах.
Другие операционные системы
Так как порт OS/2 для Perl использует замечательную среду EMX, он может работать (и создавать расширения, и, возможно, сам компилироваться) в любой среде, способной запускать EMX. Текущий список включает DOS, DOS-внутри-OS/2, Win0.3*, Win0.95 и WinNT. Из многих вариантов Perl работает только один, см. "perl_.exe".
Обратите внимание, что не все функции Perl доступны в этих средах. Это зависит от функций, которые расширитель (скорее всего, RSX) решил реализовать.
См. "Предварительные требования".
Предварительные требования
- EMX
-
Необходим запуск EMX (может быть заменён RSX). Обратите внимание, что можно заставить perl_.exe работать под DOS без какой-либо внешней поддержки, связав emx.exe/rsx.exe с ним, см.
emxbind. Обратите внимание, что в DOS для достижения наилучших результатов следует использовать среду RSX, которая имеет гораздо больше работающих функций (например,fork,popenи так далее). Фактически, RSX необходим, если отсутствует VCPI. Обратите внимание, что RSX требует DPMI. Многие реализации DPMI известны своей высокой ошибочностью, будьте осторожны!Поддерживается только последняя версия среды, в настоящее время
0.9d fix 03. Perl может работать под более ранними версиями EMX, но это не тестировалось.Различные компоненты EMX можно получить, например, из
ftp://crydee.sai.msu.ru/pub/comp/os/os2/leo/gnu/emx+gcc/ http://hobbes.nmsu.edu/h-browse.php?dir=/pub/os2/dev/emx/v0.9d/Компонент среды выполнения должен иметь имя emxrt.zip.
ПРИМЕЧАНИЕ. При использовании emx.exe/rsx.exe достаточно разместить их в вашей переменной PATH. Нет необходимости указывать их явно (хотя это
emx perl_.exe -de 0также сработает).
- RSX
-
Для запуска Perl на платформах DPMI необходима среда RSX. Это необходимо в DOS-внутри-OS/2, Win0.3*, Win0.95 и WinNT (см. "Other OSes"). RSX не будет работать только с VCPI, как EMX, он требует DMPI.
Имея RSX и последнюю версию sh.exe, вы получите полностью функциональную среду типа *nix под DOS, например,
fork,``и работу с каналами-open. Фактически, MakeMaker работает (для статической сборки), поэтому можно создать среду разработки Perl под DOS.RSX можно получить, например, из
http://cd.textfiles.com/hobbesos29804/disk1/EMX09C/ ftp://crydee.sai.msu.ru/pub/comp/os/os2/leo/gnu/emx+gcc/contrib/Свяжитесь с автором по адресу
rainer@mathematik.uni-bielefeld.de.Последняя версия sh.exe с поддержкой DOS доступна в
http://www.ilyaz.org/software/os2/как sh_dos.zip или под похожими именами, начинающимися с
sh,pdkshи т. д. - HPFS
-
Perl не заботится о файловых системах, но библиотека Perl содержит множество файлов с длинными именами, поэтому для успешной установки необходимо использовать файловую систему, поддерживающую длинные имена файлов.
Обратите внимание, что если вы не планируете устанавливать сам Perl, возможно обмануть EMX, чтобы он усекал имена файлов. Это не поддерживается, ознакомьтесь с документацией EMX, чтобы узнать, как это сделать.
- pdksh
-
Для запуска внешних программ со сложными командными строками (например, с каналами и/или экранированием аргументов) Perl использует внешнюю оболочку. В порте EMX эта оболочка должна называться sh.exe и располагаться либо в предопределённых местах (обычно F:/bin), либо в конфигурируемом месте (см. "
PERL_SH_DIR").Для наилучших результатов используйте EMX pdksh. Стандартная двоичная версия (5.2.14 или более поздняя) работает под DOS (с "RSX"), см.
http://www.ilyaz.org/software/os2/
Запуск программ Perl под OS/2 (и DOS и...)
Запустите свою программу Perl foo.pl с аргументами arg1 arg2 arg3 так же, как и на любой другой платформе, используя
perl foo.pl arg1 arg2 arg3 Если вы хотите указать параметры Perl -my_opts самому Perl (в отличие от вашей программы), используйте
perl -my_opts foo.pl arg1 arg2 arg3 В качестве альтернативы, если вы используете оболочку типа OS/2, такую как CMD или 4os2, поместите следующее в начало вашего скрипта Perl:
extproc perl -S -my_opts переименуйте свою программу в foo.cmd и запустите её, набрав
foo arg1 arg2 arg3 Обратите внимание, что из-за ограничений OS/2 полный путь к скрипту Perl недоступен при использовании extproc, поэтому вы вынуждены использовать переключатель -S Perl, и ваш скрипт должен находиться в PATH. В качестве преимущества, если вы знаете полный путь к вашему скрипту, вы можете запустить его с помощью
perl ../../blah/foo.cmd arg1 arg2 arg3 (обратите внимание, что аргумент -my_opts обрабатывается строкой extproc в вашем скрипте, см. "extproc в первой строке").
Чтобы понять, что делает приведенное выше "волшебство", прочитайте документацию Perl о переключателе -S — см. perlrun, и справку по extproc:
view perl perlrun
man perlrun
view cmdref extproc
help extproc или любой другой предпочитаемый вами метод.
Также существуют бесконечные возможности использования выполняемых расширений 4os2, ассоциаций WPS и т. д.... Однако, если вы используете оболочку типа *nix (например, sh.exe, предоставленную в дистрибутиве), вы должны следовать синтаксису, указанному в "Командные переключатели" в perlrun.
Обратите внимание, что переключатель -S поддерживает скрипты с дополнительными расширениями .cmd, .btm, .bat, .pl также.
Запуск программ OS/2 (и DOS) под Perl
Для этого предназначены функции system() (см. "system" в perlfunc), `` (см. "Операторы ввода/вывода" в perlop) и открытие канала (см. "open" в perlfunc). (Избегайте exec() (см. "exec" в perlfunc), если вы не знаете, что делаете).
Однако обратите внимание, что для использования некоторых из этих операторов необходима установленная оболочка с синтаксисом sh (см. "Pdksh", "Часто задаваемые вопросы"), и Perl должен иметь возможность её найти (см. "PERL_SH_DIR").
Случаи использования оболочки:
-
Функция system() с одним аргументом (см. "system" в perlfunc), exec() (см. "exec" в perlfunc) с перенаправлением или символами метаязыка оболочки;
-
Открытие канала (см. "open" в perlfunc) с командой, содержащей перенаправление или символы метаязыка оболочки;
-
Обратные кавычки
``(см. "Операторы ввода/вывода" в perlop) с командой, содержащей перенаправление или символы метаязыка оболочки; -
Если исполняемый файл, вызываемый system()/exec()/open pipe/
``, является скриптом со строкой "магии"#!илиextproc, которая задаёт оболочку; -
Если исполняемый файл, вызываемый system()/exec()/open pipe/
``, является скриптом без строки "магии", и$ENV{EXECSHELL}установлена на оболочку; -
Если исполняемый файл, вызываемый system()/exec()/open pipe/
``, не найден (не устарело ли это замечание?); -
Для подстановки шаблонов (см. "glob" в perlfunc, "Операторы ввода/вывода" в perlop) (устарело? Perl теперь использует встроенную подстановку шаблонов...).
Для повышения скорости в обычном случае обратные слэши в имени команды не рассматриваются как символы метаязыка оболочки.
Perl запускает скрипты, начинающиеся с маркеров extproc или #! непосредственно без вмешательства оболочки. Perl использует тот же алгоритм поиска исполняемого файла, что и pdksh: если путь в строке #! не работает и содержит /, то часть каталога исполняемого файла игнорируется, и исполняемый файл ищется в текущем каталоге и в PATH. Для поиска аргументов этих скриптов Perl использует другой алгоритм, чем pdksh: распознаётся до 3 аргументов, и отбрасываются хвостовые пробелы.
Если скрипт не содержит такой маркер, для избегания вызова sh.exe Perl использует тот же алгоритм, что и pdksh: если $ENV{EXECSHELL} установлена, скрипт передаётся в качестве первого аргумента этой команде, если не установлена, используется $ENV{COMSPEC} /c (или жёстко заданное предположение, если $ENV{COMSPEC} не установлена).
При запуске скриптов непосредственно Perl использует точно такой же алгоритм, как и для поиска скрипта, заданного опцией командной строки -S: он будет искать в текущем каталоге, затем в компонентах $ENV{PATH} с использованием следующего порядка добавляемых расширений: без расширения, .cmd, .btm, .bat, .pl.
Обратите внимание, что Perl начнёт поиск скриптов только если OS/2 не сможет запустить указанное приложение, поэтому system 'blah' не будет искать скрипт, если существует исполняемый файл blah.exe в любом месте в PATH. Другими словами, PATH фактически ищется дважды: сначала операционной системой как исполняемый файл, затем Perl как скрипт.
Также обратите внимание, что исполняемые файлы под OS/2 могут иметь любое расширение, но .exe будет автоматически добавлен, если в имени нет точки. Способ решения прост: так как blah. и blah обозначают один и тот же файл (по крайней мере, в файловых системах FAT и HPFS), чтобы запустить исполняемый файл, находящийся в файле n:/bin/blah (без расширения), передайте аргумент n:/bin/blah. (с добавленной точкой) в system().
Perl будет запускать программы PM из процесса VIO (=текстового) Perl в отдельной сессии PM; обратное неверно: когда вы запускаете программу, не являющуюся PM, из процесса Perl PM, Perl не запустит её в отдельной сессии. Если требуется отдельная сессия, либо убедитесь, что будет использована оболочка, как в system 'cmd /c myprog', либо запустите её с помощью необязательных аргументов функции system(), описанных в модуле OS2::Process. Это рассматривается как функция.
Часто задаваемые вопросы
'"Это не работает"'
Дистрибутивы Perl поставляются со скриптом testperl.cmd, который пытается обнаружить распространённые проблемы с неправильно настроенными установками. Есть большая вероятность, что он выяснит, на каком этапе установки вы допустили ошибку. ;-)
Не удаётся запустить внешние программы
-
Вы запустили свои программы с переключателем
-w? См. "Запуск программ OS/2 (и DOS) под Perl". -
Вы пытаетесь выполнить внутренние команды оболочки, такие как
`copy a b`(внутренняя для cmd.exe) или`glob a*b`(внутренняя для ksh)? Вам необходимо явно указать вашу оболочку, как`cmd /c copy a b`, так как Perl не может определить, какие команды являются внутренними для вашей оболочки.
Не удаётся встроить Perl в моё приложение или использовать perl.dll из моего приложения.
-
Является ли ваша программа EMX-скомпилированной с
-Zmt -Zcrtdll? -
Ну, в наши дни DLL Perl должна быть пригодна и для программы с другой компиляцией… Если вы можете запускать Perl-код из REXX-скриптов (см. OS2::REXX), то существуют и другие аспекты взаимодействия, которые игнорируются текущим костыльным кодом для поддержки программ с разной компиляцией.
Если всё остальное не сработает, вам нужно создать автономную DLL для perl. Свяжитесь со мной, я это делал однажды. Сокеты не будут работать, как и многое другое.
- Использовали ли вы ExtUtils::Embed?
-
Некоторое время назад поступали сообщения о том, что это не работает. В настоящее время это проверяется в наборе тестов Perl, поэтому выполните поиск в подкаталоге ./t дерева построения (а также в файлах *.t в подкаталоге ./lib), чтобы узнать, как это сделать «правильно».
`` и pipe-open не работают в DOS.
Это может быть вариантом проблемы «я не могу запустить внешние программы» или более глубокой проблемой. В принципе: вам необходим RSX (см. «Предварительные требования») для работы этих команд, и вам может потребоваться порт sh.exe, который понимает аргументы команд. Один из таких портов указан в «Предварительные требования» в разделе RSX. Не забудьте также установить переменную "PERL_SH_DIR".
Для RSX требуется DPMI.
Не удается запустить find.exe "pattern" file
Вся идея «стандартного C-API для запуска приложений» заключается в том, что формы foo и "foo" аргументов программы полностью взаимозаменяемы. find нарушает эту парадигму;
find "pattern" file
find pattern file не эквивалентны; find нельзя запустить напрямую с помощью вышеуказанного API. Нужно каким-то образом заключить двойные кавычки в другую конструкцию цитирования, обязательно используя дополнительную не-подобную-Unix оболочку между ними.
Используйте одну из
system 'cmd', '/c', 'find "pattern" file';
`cmd /c 'find "pattern" file'` Это запустит find.exe через cmd.exe через sh.exe через perl.exe, но это цена, которую нужно заплатить, если вы хотите использовать несоответствующую программу.
УСТАНОВКА
Автоматическая установка двоичных файлов
Самый удобный способ установки двоичного распределения perl — через установщик perl install.exe. Просто следуйте инструкциям, и 99% проблем с установкой исчезнут.
Однако имейте в виду, что unzip.exe должен быть в вашей переменной PATH, и среда EMX запущена. Последнее означает, что если вы только что установили EMX и внесли все необходимые изменения в Config.sys, вам может потребоваться перезагрузка между этапами. Проверьте запуск EMX, выполнив
emxrev Двоичный установщик также создаёт папку на рабочем столе с некоторыми полезными объектами. Если вам нужно изменить некоторые аспекты работы двоичного установщика, вы можете изменить файл Perl.pkg. Это может быть полезно, например, если вам нужно запускать установщик много раз и вы не хотите вносить много интерактивных изменений в графический интерфейс.
Элементы, не обрабатываемые автоматической установкой двоичных файлов:
PERL_BADLANG-
может потребоваться, если вы измените свою кодировку после установки perl, а новое значение не поддерживается EMX. См. "
PERL_BADLANG". PERL_BADFREE-
см. "
PERL_BADFREE". - Config.pm
-
Этот файл находится где-то глубоко в каталоге, куда вы установили свою библиотеку perl, найдите его, выполнив
perl -MConfig -le "print $INC{'Config.pm'}"Хотя большинство важных значений в этом файле обновляются двоичным установщиком, некоторые из них могут потребовать ручного редактирования. Мне не известно ни одной такой информации, пожалуйста, сообщите мне, если вы найдёте. Кроме того, ручные изменения в установленной версии могут потребовать редактирования этого файла.
ПРИМЕЧАНИЕ. Из-за опечатки двоичный установщик версии 5.00305 установит переменную PERL_SHPATH в Config.sys. Пожалуйста, удалите эту переменную и вместо неё вставьте "PERL_SH_DIR".
Ручная установка двоичных файлов
Начиная с версии 5.00305, двоичное распределение perl для OS/2 разделено на 11 компонентов. К сожалению, для обеспечения конфигурируемой установки двоичных файлов пути файлов в zip-архивах не абсолютные, а относительные к какому-то каталогу.
Обратите внимание, что извлечение сохранёнными путями всё ещё необходимо (по умолчанию с unzip, укажите -d для pkunzip). Однако вам нужно знать, куда извлекать файлы. Вам также необходимо вручную изменить записи в Config.sys, чтобы отразить, куда вы поместили файлы. Обратите внимание, что если у вас есть примитивный распаковщик (например, pkunzip), при распаковке может появиться много предупреждений/ошибок. Обновитесь до (w)unzip.
Ниже приведен пример того, что нужно сделать, чтобы воспроизвести конфигурацию на моём компьютере. В VIEW.EXE вы можете нажать Ctrl-Insert сейчас и скопировать/вставить из полученного файла — созданного в каталоге, из которого вы запустили VIEW.EXE.
Для каждого компонента мы упоминаем переменные среды, связанные с каждым каталогом установки. Либо выберите каталоги, соответствующие вашим значениям переменных, либо создайте/добавьте в переменные, чтобы учесть каталоги.
- Исполняемые файлы Perl VIO и PM (динамически связанные)
-
unzip perl_exc.zip *.exe *.ico -d f:/emx.add/bin unzip perl_exc.zip *.dll -d f:/emx.add/dll(каталоги с
*.exeв PATH и*.dllв LIBPATH); - Исполняемый файл Perl_ VIO (статически связанный)
-
unzip perl_aou.zip -d f:/emx.add/bin(каталог в PATH);
- Исполняемые файлы для утилит Perl
-
unzip perl_utl.zip -d f:/emx.add/bin(каталог в PATH);
- Основная библиотека Perl
-
unzip perl_mlb.zip -d f:/perllib/libЕсли этот каталог точно такой же, как префикс, который был скомпилирован в perl.exe, вам ничего не нужно менять. Однако, чтобы perl нашёл библиотеку, если вы используете другой путь, вам нужно
set PERLLIB_PREFIXв Config.sys, см. "PERLLIB_PREFIX". - Дополнительные модули Perl
-
unzip perl_ste.zip -d f:/perllib/lib/site_perl/5.28.3/То же замечание, что и выше. Кроме того, если этот каталог не является одним из каталогов в @INC (и @INC зависит от
PERLLIB_PREFIX), вам нужно поместить этот каталог и подкаталог ./os2 в переменнуюPERLLIBилиPERL5LIB. Не используйтеPERL5LIB, если вы её уже не установили. См. "СРЕДА" в perl.[Проверьте, остаётся ли этот каталог извлечения применимым с новой структурой расположения каталогов!]
- Инструменты для компиляции модулей Perl
-
unzip perl_blb.zip -d f:/perllib/libТо же замечание, что и для perl_ste.zip.
- Справочные страницы для Perl и утилит
-
unzip perl_man.zip -d f:/perllib/manЭтот каталог лучше поместить в
MANPATH. Вам нужна работающая утилита man для доступа к этим файлам. - Справочные страницы для модулей Perl
-
unzip perl_mam.zip -d f:/perllib/manЭтот каталог лучше поместить в
MANPATH. Вам нужна работающая утилита man для доступа к этим файлам. - Исходный код документации Perl
-
unzip perl_pod.zip -d f:/perllib/libИспользуется программой
perldoc(см. perldoc) и может использоваться для генерации HTML-документации, доступной для веб-браузеров, и документации в бесчисленных других форматах:info,LaTeX,Acrobat,FrameMakerи так далее. [Используйте программы, такие как pod2latex и т. д.] - Справочник Perl в формате .INF
-
unzip perl_inf.zip -d d:/os2/bookЭтот каталог лучше поместить в
BOOKSHELF. - Pdksh
-
unzip perl_sh.zip -d f:/binИспользуется perl для запуска внешних команд, которые явно требуют оболочки, таких как команды с использованием перенаправления и метасимволов оболочки. Также используется вместо явного /bin/sh.
Установите
PERL_SH_DIR(см. "PERL_SH_DIR"), если вы перемещаете sh.exe из указанного выше места.Примечание. Возможно использование другой совместимой с sh оболочки (не протестировано).
После установки необходимых компонентов и соответствующего обновления Config.sys вам нужно вручную отредактировать Config.pm. Этот файл находится где-то глубоко в каталоге, куда вы установили свою библиотеку perl, найдите его, выполнив
perl -MConfig -le "print $INC{'Config.pm'}" Вам нужно исправить все записи, которые выглядят как пути к файлам (в настоящее время они начинаются с f:/).
Предупреждение
Автоматическая и ручная установка perl оставляют предварительно скомпилированные пути внутри исполняемых файлов perl. Хотя эти пути можно перезаписать (см. "PERLLIB_PREFIX", "PERL_SH_DIR"), некоторые люди могут предпочесть двоичное редактирование путей внутри исполняемых файлов/DLL.
Доступ к документации
В зависимости от того, как вы построили/установили perl, у вас может быть (в противном случае идентичная) документация Perl в следующих форматах:
Файл OS/2 .INF
Вероятно, самый удобный формат. В OS/2 отображается как
view perl
view perl perlfunc
view perl less
view perl ExtUtils::MakeMaker (в настоящее время последние два могут попасть в неправильное место, но это может быть исправлено вскоре). В Win* см. "ОБЗОР".
Если вы хотите самостоятельно создать документацию и имеете OS/2 toolkit, выполните
pod2ipf > perl.ipf в каталоге /perllib/lib/pod, затем
ipfc /inf perl.ipf (Ожидайте много ошибок во время обоих этапов.) Теперь перенесите его в свой каталог BOOKSHELF.
Текст
Если у вас есть исходный текст документации perl, установлены утилиты perl и установлена GNU groff, вы можете использовать
perldoc perlfunc
perldoc less
perldoc ExtUtils::MakeMaker для доступа к документации perl в текстовой форме (обратите внимание, что вы можете получить лучшие результаты, используя справочные страницы perl).
В качестве альтернативы попробуйте запустить pod2text на файлах .pod.
Справочные страницы
Если у вас установлена утилита man на вашей системе и установлены справочные страницы perl, используйте что-то вроде этого:
man perlfunc
man 3 less
man ExtUtils.MakeMaker для доступа к документации различных компонентов Perl. Начните с
man perl Обратите внимание, что точка (.) используется в качестве разделителя пакетов для документации пакетов, и, как обычно, иногда вам нужно указать раздел — 3 выше — чтобы избежать перекрытия со справочной страницей less(1) manpage.
Убедитесь, что каталог выше каталога со справочными страницами находится в нашем MANPATH, например так
set MANPATH=c:/man;f:/perllib/man для справочных страниц perl в f:/perllib/man/man1/ и т. д.
HTML
Если у вас есть доступный веб-браузер, установлена документация Perl в исходной форме и утилиты Perl, вы можете сгенерировать HTML-документацию. Перейдите в каталог с файлами .pod и выполните следующие действия
cd f:/perllib/lib/pod
pod2html После этого вы можете открыть в браузере файл perl.html в этом каталоге и приступить к чтению документации, как показано ниже:
explore file:///f:/perllib/lib/pod/perl.html В качестве альтернативы вы можете получить эти документы, уже сгенерированные, с помощью CPAN.
Файлы GNU info
Пользователям Emacs это очень пригодится, особенно с загруженным режимом CPerl. Вам необходимо получить последние pod2texi с CPAN, или, в качестве альтернативы, уже сгенерированные страницы info.
Файлы PDF
для Acrobat доступны на CPAN (возможно, для немного более старой версии Perl).
Документация LaTeX
может быть сгенерирована с помощью pod2latex.
Сборка
Здесь мы обсудим, как собрать Perl под OS/2.
Краткое описание процесса
Предположим, что вы опытный пользователь, уверены, что все необходимые инструменты уже присутствуют в вашей системе, и знаете, как получить исходное распределение Perl. Извлеките его, перейдите в каталог с извлечёнными файлами и
gnupatch -p0 < os2\diff.configure
sh Configure -des -D prefix=f:/perllib
make
make test
make install
make aout_test
make aout_install Это поместит исполняемые файлы в f:/perllib/bin. Переместите их вручную в PATH, вручную переместите созданные perl*.dll в LIBPATH (здесь для Perl DLL * — не имеющий особого смысла шестнадцатеричный контрольный код) и выполните
make installcmd INSTALLCMDDIR=d:/ir/on/path Предполагая, что файлы man были помещены в соответствующее место, это завершает установку минимальной системы Perl. (Бинарное распределение также содержит множество дополнительных модулей и документацию в формате INF.)
Далее следует подробное руководство по этим шагам.
Предварительные условия
Вам нужна последняя среда разработки EMX, полный набор инструментов GNU (gawk переименован в awk, и GNU find.exe расположен выше в пути, чем OS/2 find.exe, также с sort.exe, чтобы проверить, используйте
find --version
sort --version ). Вам нужна последняя версия pdksh, установленная как sh.exe.
Проверьте, установлены ли библиотеки и заголовки BSD, а также — по желанию — заголовки и библиотеки Berkeley DB и crypt.
Возможные места для получения файлов:
ftp://ftp.uni-heidelberg.de/pub/os2/unix/
http://hobbes.nmsu.edu/h-browse.php?dir=/pub/os2
http://cd.textfiles.com/hobbesos29804/disk1/DEV32/
http://cd.textfiles.com/hobbesos29804/disk1/EMX09C/ Сообщается, что следующие архивы содержат достаточно утилит для сборки Perl: gnufutil.zip, gnusutil.zip, gnututil.zip, gnused.zip, gnupatch.zip, gnuawk.zip, gnumake.zip, gnugrep.zip, bsddev.zip и ksh527rt.zip (или более поздняя версия). Обратите внимание, что все эти утилиты, как известно, доступны в LEO:
ftp://crydee.sai.msu.ru/pub/comp/os/os2/leo/gnu/ Также обратите внимание, что db.lib и db.a из дистрибутива EMX не подходят для многопоточной компиляции (даже однопоточная версия Perl использует многопоточную C RTL для совместимости с XFree86-OS/2). Получите исправленную версию из
http://www.ilyaz.org/software/os2/db_mt.zip Если у вас установлена точно такая же версия Perl, убедитесь, что в данный момент не запущены какие-либо копии или экземпляры perl. Более поздние этапы сборки могут завершиться неудачей, так как в памяти может быть загружена более старая версия perl.dll. Запуск make test становится бессмысленным, так как тесты проверяют предыдущую версию сборки perl (эта ситуация обнаруживается и сообщается тестом os2/os2_base.t). Не забудьте сбросить PERL_EMXLOAD_SEC в среде.
Также убедитесь, что каталог /tmp находится на текущем диске и каталог . в вашей LIBPATH. Можно попытаться исправить последнее условие, выполнив
set BEGINLIBPATH .\. если вы используете что-то вроде CMD.EXE или последние версии 4os2.exe. (Установка BEGINLIBPATH только на . игнорируется ядром OS/2.)
Убедитесь, что ваш gcc подходит для -Zomf линковки: выполните скрипт omflibs в каталоге /emx/lib.
Проверьте, установлен ли link386. Он входит в стандартную поставку OS/2, но может быть не установлен из-за настройки. Если ввод
link386 показывает, что он отсутствует, выполните Выборочную установку и выберите Link object modules в Дополнительные системные утилиты/Ещё. Если вы попадете в приглашения link386, нажмите Ctrl-C для выхода.
Получение исходного кода Perl
Вам нужно получить последний исходный код Perl (включая релизы разработчиков). С определённой вероятностью он находится в
http://www.cpan.org/src/
http://www.cpan.org/src/unsupported Если нет, вам может потребоваться поискать его в индексах в каталоге текущего разработчика.
Быстрый цикл релизов разработчиков время от времени может нарушить процесс сборки под OS/2, поиск в
http://www.cpan.org/ports/os2/ может указать на последнюю версию, которая была опубликована разработчиком. Обратите внимание, что релиз может включать дополнительные исправления, которые нужно применить к текущему исходному коду Perl.
Извлеките его так:
tar vzxf perl5.00409.tar.gz Вы можете увидеть сообщение об ошибках при извлечении Configure. Это связано с конфликтом с аналогичным файлом configure.
Перейдите в каталог извлечения.
Применение исправлений
Вам нужно применить исправления из ./os2/diff.* следующим образом:
gnupatch -p0 < os2\diff.configure Вам также может потребоваться применить исправления, входящие в состав бинарного дистрибутива Perl. Также имеет смысл обратиться к списку рассылки perl5-porters по последним исправлениям, относящимся к OS/2 (см. http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/). Такие исправления обычно содержат строки /os2/ и patch, поэтому имеет смысл искать эти строки.
Редактирование вручную
Вы можете посмотреть файл ./hints/os2.sh и исправить любые ошибки, которые вы там найдёте. Я не ожидаю, что это потребуется в любом случае.
Сборка
sh Configure -des -D prefix=f:/perllib prefix означает: куда установить получившуюся библиотеку perl. Указав правильный префикс, вы можете избежать необходимости указывать PERLLIB_PREFIX, см. "PERLLIB_PREFIX".
Игнорируйте сообщение об отсутствии ln, и об опции -c для tr. Вероятно, последняя уже исправлена, если вы её видите и можете отследить, откуда исходит это ложное предупреждение, сообщите мне об этом.
Теперь
make В какой-то момент сборка может завершиться сбоем, сообщая о несоответствии версии или невозможности запустить perl. Это означает, что у вас нет . в вашей LIBPATH, поэтому perl.exe не может найти необходимый perl67B2.dll (рассматривайте эти шестнадцатеричные цифры как шумовые данные). После исправления этого сбоя сборка должна завершиться без особых проблем.
Тестирование
Теперь выполните
make test Все тесты должны быть пройдены (некоторые из них могут быть пропущены). Если у вас установлена та же версия Perl, крайне важно, чтобы . находилась в начале вашего LIBPATH (или в BEGINLIBPATH), в противном случае ваши тесты, скорее всего, будут проверять не ту версию Perl.
Некоторые тесты могут генерировать дополнительные сообщения, подобные
-
Множество
bad free -
в тестах базы данных, связанных с Berkeley DB. Это должно быть уже исправлено. Если проблема сохраняется, вы можете отключить эти предупреждения, см. "
PERL_BADFREE". - Процесс завершён по сигналу SIGTERM/SIGINT
-
Это стандартное сообщение, выдаваемое приложениями OS/2. Приложения *nix завершаются без сообщений. Это считается особенностью. Можно легко отключить это с помощью соответствующих обработчиков сигналов.
Однако система тестирования выводит эти сообщения на экран в неожиданные моменты. Два таких сообщения *должны* присутствовать во время тестирования.
Для получения более подробных отчётов о тестах вызовите
perl t/harness Отчёт с io/pipe.t, завершившимся ошибкой, может выглядеть так:
Failed Test Status Wstat Total Fail Failed List of failed
------------------------------------------------------------
io/pipe.t 12 1 8.33% 9
7 tests skipped, plus 56 subtests skipped.
Failed 1/195 test scripts, 99.49% okay. 1/6542 subtests failed,
99.98% okay. Причины самых важных пропущенных тестов:
- op/fs.t
-
- 18
-
Проверяет
atimeиmtimeвstat()— к сожалению, HPFS предоставляет только 2-секундную точность временных меток (для совместимости с FAT?). - 25
-
Проверяет
truncate()на файле, только что открытом для записи — я не знаю, почему это должно или не должно работать.
- op/stat.t
-
Проверяет
stat(). Тесты:- 4
-
Проверяет
atimeиmtimeвstat()— к сожалению, HPFS предоставляет только 2-секундную точность временных меток (для совместимости с FAT?).
Установка собранного Perl
Если вы ещё не перенесли perl*.dll в LIBPATH, сделайте это сейчас.
Выполните
make install Это поместит сгенерированные файлы в нужные места. Вручную поместите perl.exe, perl__.exe и perl___.exe в местоположение в вашем PATH, perl.dll — в местоположение в вашем LIBPATH.
Выполните
make installcmd INSTALLCMDDIR=d:/ir/on/path чтобы преобразовать утилиты perl в файлы .cmd и поместить их в PATH. Вам нужно вручную поместить утилиты с расширением .EXE в путь. Они установлены в $prefix/bin, здесь $prefix — то, что вы указали в Configure, см. "Сборка".
Если вы используете man, либо перенесите установленные каталоги */man/ в ваш MANPATH, либо измените MANPATH для соответствия расположению. (Можно было бы избежать этого, предоставив корректную опцию manpath для ./Configure или отредактировав ./config.sh между этапами конфигурирования и сборки.)
Сборка в стиле a.out
Продолжайте как выше, но создайте perl_.exe (см. "perl_.exe") с помощью
make perl_ тестируйте и устанавливайте с помощью
make aout_test
make aout_install Вручную поместите perl_.exe в местоположение в вашем PATH.
Примечание. Процесс сборки для perl_ не знает обо всех зависимостях, поэтому вы должны убедиться, что все обновлено, например, выполнив
make perl_dll сначала.
Сборка бинарного дистрибутива
[Этот раздел содержит только краткий обзор...]
Процесс сборки должен отличаться в зависимости от того, уже присутствует ли и используется ли устанавливаемая версия Perl в вашей системе или это новая версия, которая ещё не используется. Описание ниже предполагает, что версия новая, поэтому установка её DLL и файлов .pm не нарушит работу вашей системы, даже если некоторые промежуточные шаги ещё не полностью работают.
В других случаях требуются несколько более запутанные процедуры. Ниже я предполагаю, что текущая версия Perl — 5.8.2, поэтому исполняемые файлы имеют соответствующие имена.
-
Полностью постройте и протестируйте дистрибутив Perl. Убедитесь, что никакие тесты не терпят неудачу с целями
testиaout_test; исправьте ошибки в Perl и наборе тестов Perl, обнаруженные этими тестами. Убедитесь, что цельall_testmake выполняется максимально чисто. Проверьте, что os2/perlrexx.cmd работает нормально. -
Полностью установите Perl, включая цель
installcmd. Скопируйте сгенерированные DLL-файлы вLIBPATH; скопируйте пронумерованные исполняемые файлы Perl (как в perl5.8.2.exe) вPATH; скопируйтеperl_.exeвPATHкакperl_5.8.2.exe. Подумайте, нужны ли вам DLL-файлы обратной совместимости. В большинстве случаев вам пока не нужно их устанавливать; но иногда это может упростить последующие шаги. -
Убедитесь, что
CPAN.pmможет загружать файлы из CPAN. Если нет, возможно, вам нужно вручную установитьNet::FTP. -
Установите пакет
Bundle::OS2_defaultperl5.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по завершении. -
По завершении выполнения, перезапустите цель
installcmd. Теперь вы можете скопироватьperl5.8.2.exeвperl.exe, и установить другие исполняемые файлы OMF-build:perl__.exeи т.д. Они готовы к использованию. -
Перейдите в директорию
./podдерева сборки, загрузите логотип Perl CamelGrayBig.BMP и выполните( perl2ipf > perl.ipf ) |& tee 00ipf ipfc /INF perl.ipf |& tee 00infЭто создает онлайн-книгу документации Perl
perl.INF. Установите её в путьBOOKSHELF. -
Сейчас самое время создать статически связанный исполняемый файл perl_.exe, включающий недавно установленные через
Bundle::OS2_defaultмодули. Тестирование черезCPAN.pmбудет очень медленным, так как для каждого XS-расширения создается новый исполняемый файл.Вот возможный обходной путь: создайте файл Makefile.PL в корне в $CPANHOME/.cpan/build/ с содержимым (сравните с "Создание исполняемых файлов с набором статически загружаемых расширений")
use ExtUtils::MakeMaker; WriteMakefile NAME => 'dummy';выполните это как
perl_5.8.2.exe Makefile.PL <nul |& tee 00aout_c1 make -k all test <nul |& 00aout_t1Опять же, этот процесс не должен быть совершенно гладким. Некоторые
Makefile.PLв поддиректориях могут быть ошибочными и не будут работать как «дочерние» скрипты. Взаимозависимость модулей может вас удивить; однако, так как не-XS модули уже установлены, предшественники большинства модулей, скорее всего, присутствуют.Если вы обнаружите какие-либо проблемы, переместите каталоги проблемных модулей в другое место; если эти модули являются не-XS модулями, вы можете просто их пропустить — они уже установлены; оставшиеся, XS-модули, необходимо установить вручную по одному.
После каждого такого удаления необходимо перезапустить процесс
Makefile.PL/make; обычно этот процесс быстро сходится. (Но убедитесь, что все необходимые внешние библиотеки C преобразованы из формата .lib в формат .a: выполните одну изemxaout foo.lib emximp -o foo.a foo.lib(которую следует выбрать). Также убедитесь, что DLL-файлы внешних библиотек совместимы с исполняемыми файлами, скомпилированными без опций
-Zmtd.Когда вы уверены, что только несколько подкаталогов приводят к ошибкам, вы можете добавить опцию
-j4кmakeдля ускорения пропуска подкаталогов с уже завершенной сборкой.Когда вы удовлетворены результатами тестов, установите библиотеки C для сборки расширений:
make install |& tee 00aout_iТеперь вы можете переименовать файл ./perl.exe, сгенерированный на последнем этапе, в perl_5.8.2.exe; поместите его в
PATH; если существует взаимозависимость между некоторыми XS-модулями, вам может потребоваться повторить циклtest/installс этим новым исполняемым файлом и некоторыми исключенными модулями — до тех пор, пока процедура не сойдётся.Теперь у вас есть все необходимые библиотеки .a для этих модулей Perl в местах, где их может найти Perl-строитель. Используйте Perl-строитель: перейдите в пустую директорию, создайте еще один «фиктивный» файл Makefile.PL и выполните
perl_5.8.2.exe Makefile.PL |& tee 00c make perl |& tee 00pЭто должно создать исполняемый файл ./perl.exe со всеми статически загруженными расширениями, встроенными в него. Сравните сгенерированные файлы perlmain.c, чтобы убедиться, что при итерациях число загруженных расширений только увеличивается. Переименуйте ./perl.exe в perl_5.8.2.exe в
PATH.Когда процедура сойдётся, вы получите функциональную версию perl_5.8.2.exe; скопируйте её в
perl_.exe. Вы завершили генерацию локальной установки Perl. -
Убедитесь, что установленные модули действительно установлены в местоположение нового 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. -
Теперь вы можете сгенерировать двоичный дистрибутив. Для этого выполните тест дистрибутива CPAN
OS2::SoftInstaller. Сначала настройте файл test.pl в соответствии с макетом текущей версии Perl. Не забудьте соответствующим образом упаковать необходимые внешние DLL-файлы. Включите описание ошибок и сбоев набора тестов, которые вы не смогли исправить. Включите версии Perl с небольшим стеком из каталога сборки Perl.Включите perl5.def, чтобы пользователи могли повторно связать DLL Perl, сохраняя двоичную совместимость, или могли создать DLL-файлы совместимости. Включите файлы diff (
diff -pu old new) исправлений, которые вы внесли, чтобы пользователи могли перестроить вашу версию. Включите perl5.map, чтобы можно было использовать удаленное отладку. -
Поделитесь тем, что вы сделали с другими людьми. Отдохните. Наслаждайтесь плодами своего труда.
-
Приготовьтесь к благодарностям, сообщениям об ошибках, ненавистным письмам и спаму, которые придут в результате предыдущего шага. Нет добрых дел, которые остаются невознагражденными!
Создание пользовательских файлов .EXE
Исполняемые файлы Perl можно легко перестроить в любое время. Более того, можно использовать интерфейс встраивания (см. perlembed), чтобы создавать очень настраиваемые исполняемые файлы.
Создание исполняемых файлов с набором статически загружаемых расширений
Немного проще сделать это, уменьшив список статически загружаемых расширений. Мы рассматриваем только этот случай.
-
Перейдите в пустую директорию и создайте файл-заглушку <Makefile.PL>:
use ExtUtils::MakeMaker; WriteMakefile NAME => 'dummy'; -
Запустите его с требуемой версией Perl (perl.exe или perl_.exe), которую вы хотите перестроить.
perl_ Makefile.PL -
Попросите его создать новый исполняемый файл Perl:
make perl(возможно, вам нужно будет вручную добавить
PERLTYPE=-DPERL_COREк этой команде в некоторых версиях Perl; признаком является то, что команда-глобальный поиск не работает из оболочек OS/2 с недавно скомпилированным исполняемым файлом; проверьте с помощью.\perl.exe -wle "print for @ARGV" *).
-
На предыдущем шаге был создан perlmain.c, который содержит список вызовов newXS() в конце. Удаление ненужных вызовов и повторное выполнение
make perlсоздаст настраиваемый исполняемый файл.
Создание исполняемых файлов с пользовательскими путями поиска
Стандартный исполняемый файл perl достаточно гибкий, чтобы поддерживать большинство применений. Однако, возможно, потребуется что-то еще более гибкое; например, может потребоваться найти DLL Perl относительно расположения файла EXE; или может потребоваться игнорировать среду при установке пути поиска библиотек Perl и т.д.
Если вы чувствуете себя комфортно с интерфейсом встраивания (см. perlembed), такие вещи легко сделать, повторив шаги, описанные в L/<Создание исполняемых файлов с пользовательским набором статически загружаемых расширений> и выполнив более подробные правки в main() в perlmain.c. Люди с небольшим желанием понимать Perl могут просто переименовать main() и внести необходимые изменения в пользовательскую функцию main(), которая вызывает переименованную функцию в соответствующее время.
Однако существует третий способ: DLL Perl экспортирует функцию main() и несколько обратных вызовов для настройки пути поиска. Ниже приведен полный пример «загрузчика Perl», который
-
Ищет DLL Perl в директории
$exedir/../dll; -
Добавляет вышеуказанную директорию в начало
BEGINLIBPATH; -
Возвращает ошибку, если DLL Perl, найденная с помощью
BEGINLIBPATH, отличается от загруженной на шаге 1; например, другой процесс мог загрузить её изLIBPATHили из другого значенияBEGINLIBPATH. В этих случаях необходимо изменить настройки системы, чтобы этот другой процесс либо не запускался, либо загружал DLL изBEGINLIBPATHсLIBPATHSTRICT=T(доступно в ядрах после сентября 2000 года). -
Загружает библиотеку Perl из
$exedir/../dll/lib/. -
Использует оболочку Bourne из
$exedir/../dll/sh/ksh.exe.
Для наилучших результатов скомпилируйте нижеприведенный файл C с теми же опциями, что и Perl DLL. Однако, многие функции будут работать даже если исполняемый файл не является приложением EMX, например, если он скомпилирован с
gcc -Wall -DDOSISH -DOS2=1 -O2 -s -Zomf -Zsys perl-starter.c \
-DPERL_DLL_BASENAME=\"perl312F\" -Zstack 8192 -Zlinker /PM:VIO Вот пример файла C:
#define INCL_DOS
#define INCL_NOPM
/* These are needed for compile if os2.h includes os2tk.h, not
* os2emx.h */
#define INCL_DOSPROCESS
#include <os2.h>
#include "EXTERN.h"
#define PERL_IN_MINIPERLMAIN_C
#include "perl.h"
static char *me;
HMODULE handle;
static void
die_with(char *msg1, char *msg2, char *msg3, char *msg4)
{
ULONG c;
char *s = " error: ";
DosWrite(2, me, strlen(me), &c);
DosWrite(2, s, strlen(s), &c);
DosWrite(2, msg1, strlen(msg1), &c);
DosWrite(2, msg2, strlen(msg2), &c);
DosWrite(2, msg3, strlen(msg3), &c);
DosWrite(2, msg4, strlen(msg4), &c);
DosWrite(2, "\r\n", 2, &c);
exit(255);
}
typedef ULONG (*fill_extLibpath_t)(int type,
char *pre,
char *post,
int replace,
char *msg);
typedef int (*main_t)(int type, char *argv[], char *env[]);
typedef int (*handler_t)(void* data, int which);
#ifndef PERL_DLL_BASENAME
# define PERL_DLL_BASENAME "perl"
#endif
static HMODULE
load_perl_dll(char *basename)
{
char buf[300], fail[260];
STRLEN l, dirl;
fill_extLibpath_t f;
ULONG rc_fullname;
HMODULE handle, handle1;
if (_execname(buf, sizeof(buf) - 13) != 0)
die_with("Can't find full path: ", strerror(errno), "", "");
/* XXXX Fill 'me' with new value */
l = strlen(buf);
while (l && buf[l-1] != '/' && buf[l-1] != '\\')
l--;
dirl = l - 1;
strcpy(buf + l, basename);
l += strlen(basename);
strcpy(buf + l, ".dll");
if ( (rc_fullname = DosLoadModule(fail, sizeof fail, buf, &handle))
!= 0
&& DosLoadModule(fail, sizeof fail, basename, &handle) != 0 )
die_with("Can't load DLL ", buf, "", "");
if (rc_fullname)
return handle; /* was loaded with short name; all is fine */
if (DosQueryProcAddr(handle, 0, "fill_extLibpath", (PFN*)&f))
die_with(buf,
": DLL exports no symbol ",
"fill_extLibpath",
"");
buf[dirl] = 0;
if (f(0 /*BEGINLIBPATH*/, buf /* prepend */, NULL /* append */,
0 /* keep old value */, me))
die_with(me, ": prepending BEGINLIBPATH", "", "");
if (DosLoadModule(fail, sizeof fail, basename, &handle1) != 0)
die_with(me,
": finding perl DLL again via BEGINLIBPATH",
"",
"");
buf[dirl] = '\\';
if (handle1 != handle) {
if (DosQueryModuleName(handle1, sizeof(fail), fail))
strcpy(fail, "???");
die_with(buf,
":\n\tperl DLL via BEGINLIBPATH is different: \n\t",
fail,
"\n\tYou may need to manipulate global BEGINLIBPATH"
" and LIBPATHSTRICT"
"\n\tso that the other copy is loaded via"
BEGINLIBPATH.");
}
return handle;
}
int
main(int argc, char **argv, char **env)
{
main_t f;
handler_t h;
me = argv[0];
/**/
handle = load_perl_dll(PERL_DLL_BASENAME);
if (DosQueryProcAddr(handle,
0,
"Perl_OS2_handler_install",
(PFN*)&h))
die_with(PERL_DLL_BASENAME,
": DLL exports no symbol ",
"Perl_OS2_handler_install",
"");
if ( !h((void *)"~installprefix", Perlos2_handler_perllib_from)
|| !h((void *)"~dll", Perlos2_handler_perllib_to)
|| !h((void *)"~dll/sh/ksh.exe", Perlos2_handler_perl_sh) )
die_with(PERL_DLL_BASENAME,
": Can't install @INC manglers",
"",
"");
if (DosQueryProcAddr(handle, 0, "dll_perlmain", (PFN*)&f))
die_with(PERL_DLL_BASENAME,
": DLL exports no symbol ",
"dll_perlmain",
"");
return f(argc, argv, env);
} Вопросы и ответы по сборке
Некоторые / стали \ в pdksh.
У вас очень старая версия pdksh. См. "Предварительные требования".
'errno' - неразрешенная внешняя ссылка
У вас нет безопасной для многопоточности библиотеки db.lib. См. "Предварительные требования".
Проблемы с tr или sed
сообщаются при использовании очень старых версий tr и sed.
Некоторая проблема (забыл какая ;-)
У вас старая версия perl.dll в вашем каталоге LIBPATH, из-за которой произошла ошибка сборки расширений.
Библиотека ... не найдена
Вы не выполнили omflibs. См. "Предварительные требования".
Ошибка сегментации в make
Вы используете старую версию GNU make. См. "Предварительные требования".
Ошибка теста op/sprintf
Это может быть следствием ошибки в emx sprintf, которая была исправлена в 0.9d фикс 03.
Особенности (недостатки) порта для OS/2
setpriority, getpriority
Обратите внимание, что эти функции совместимы с *nix, но не с более старыми портами 94-95 годов. Приоритеты абсолютны, изменяются от 32 до -95, более низкий приоритет означает более высокую скорость. 0 — это приоритет по умолчанию.
ПРЕДУПРЕЖДЕНИЕ. Вызов getpriority для несуществующего процесса может заблокировать систему до исправления Warp3 fixpak22. Начиная с Warp3, Perl будет использовать обходной путь: он прерывает getpriority(), если процесс отсутствует. Это невозможно в старых версиях 2.*, и в любом случае существует проблема гонки.
system()
Многоаргументная форма system() позволяет использовать дополнительный числовой аргумент. Значение этого аргумента описано в OS2::Process.
При поиске программы для запуска Perl сначала просит ОС искать исполняемые файлы в PATH (OS/2 добавляет расширение .exe, если расширение отсутствует). Если не найдено, ищется скрипт с возможными расширениями в таком порядке: без расширения, .cmd, .btm, .bat, .pl. Если найден, Perl проверяет начало файла на наличие магических строк "#!" и "extproc ". Если найдены, Perl использует остальную часть первой строки как начало командной строки для запуска этого скрипта. Единственная обработка первой строки — извлечение аргументов (в настоящее время до 3) и игнорирование части пути в имени «интерпретатора», если его невозможно найти, используя полный путь.
Например, system 'foo', 'bar', 'baz' может привести Perl к поиску C:/emx/bin/foo.cmd, где первая строка будет
extproc /bin/bash -x -c Если /bin/bash.exe не найден, тогда Perl ищет исполняемый файл bash.exe в PATH. Если он найден в C:/emx.add/bin/bash.exe, то вышеприведенный вызов system() преобразуется в
system qw(C:/emx.add/bin/bash.exe -x -c C:/emx/bin/foo.cmd bar baz) Выполняется дополнительный перевод: вместо /bin/sh Perl использует жёстко заданную или настраиваемую оболочку (см. "PERL_SH_DIR").
Вышеописанный поиск «интерпретатора» рекурсивен: если исполняемый файл bash не найден, но bash.btm найден, Perl будет исследовать его первую строку и т. д. Единственное жёстко заданное ограничение на глубину рекурсии неявное: существует ограничение в 4 на количество дополнительных аргументов, вставленных перед фактическими аргументами, переданными в system(). В частности, если в «магических» первых строках не указаны дополнительные аргументы, то ограничение по глубине равно 4.
Если Perl определяет, что найденный исполняемый файл является типа PM, когда текущая сессия не PM, он запустит новый процесс в отдельной сессии необходимого типа. Для отключения этой «магии» вызовите OS2::Process.
ПРЕДУПРЕЖДЕНИЕ. Из-за описанной логики вам необходимо явно указать расширение .com, если это необходимо. Более того, если запрашивается исполняемый файл perl5.6.1, Perl не будет искать perl5.6.1.exe. [Это может измениться в будущем.]
extproc в первой строке
Если первые символы Perl-скрипта — "extproc ", эта строка обрабатывается как #!-строка, поэтому все переключатели в этой строке обрабатываются (дважды, если сценарий был запущен через cmd.exe). См. "DESCRIPTION" в perlrun.
Дополнительные модули:
OS2::Process, OS2::DLL, OS2::REXX, OS2::PrfDB, OS2::ExtAttr. Эти модули обеспечивают доступ к дополнительным числовым аргументам для system и к информации о работающем процессе, к DLL, содержащим функции с синтаксисом REXX, и к среде выполнения REXX, к базам данных OS/2 в формате .INI и к расширенным атрибутам.
Два дополнительных расширения Андрея Кайзера, OS2::UPM, и OS2::FTP, включены в каталог ILYAZ, дублирующийся на CPAN. Также доступны другие расширения, относящиеся к OS/2.
Встроенные методы:
-
File::Copy::syscopy -
используется
File::Copy::copy, см. File::Copy. -
DynaLoader::mod2fname -
используется
DynaLoaderдля преобразования имен DLL. -
Cwd::current_drive() -
Самодокументирующаяся функция.
-
Cwd::sys_chdir(name) -
оставляет диск без изменений.
-
Cwd::change_drive(name) -
изменяет "текущий" диск.
-
Cwd::sys_is_absolute(name) -
имеет букву диска и является корневым.
-
Cwd::sys_is_rooted(name) -
имеет ведущий
[/\\](возможно, после буквы диска :). -
Cwd::sys_is_relative(name) -
изменяется в зависимости от текущей директории.
-
Cwd::sys_cwd(name) -
Интерфейс к cwd из EMX. Используется
Cwd::cwd. -
Cwd::sys_abspath(name, dir) -
Действительно очень неприятная функция для реализации. Возвращает абсолютное имя файла, которое имело бы
name, если бы текущая директория былаdir.Dirпо умолчанию - текущая директория. -
Cwd::extLibpath([type]) -
Получить текущее значение расширенного пути поиска библиотек. Если
typeприсутствует и положительно, работает сEND_LIBPATH, если отрицательно, работает сLIBPATHSTRICT, в противном случае сBEGIN_LIBPATH. -
Cwd::extLibpath_set( path [, type ] ) -
Установить текущее значение расширенного пути поиска библиотек. Если
typeприсутствует и положительно, работает с <END_LIBPATH>, если отрицательно, работает сLIBPATHSTRICT, в противном случае сBEGIN_LIBPATH. -
OS2::Error(do_harderror,do_exception) -
Возвращает
undefесли еще не вызывалась, в противном случае бит 1 установлен, если на предыдущем вызове do_harderror был включен, бит 2 установлен, если на предыдущем вызове do_exception был включен.Эта функция включает/выключает всплывающие окна ошибок, связанные с аппаратными ошибками (диск не готов и т.п.), и программными ошибками.
Я не знаю способа узнать состояние всплывающих окон *до* первого вызова этой функции.
-
OS2::Errors2Drive(drive) -
Возвращает
undefесли еще не вызывалась, в противном случае возвращает false, если ошибки не были запрошены для записи на жесткий диск, или букву диска, если это было запрошено.Эта функция может перенаправить всплывающие окна ошибок, связанные с аппаратными ошибками (диск не готов и т.п.), и программными ошибками, в файл POPUPLOG.OS2 в корневой директории указанного диска. Переопределяет OS2::Error(), указанный отдельными программами. Аргумент undef отключит перенаправление.
Действует глобально, сохраняется после завершения работы приложения.
Я не знаю способа узнать состояние перенаправления всплывающих окон на диск *до* первого вызова этой функции.
- OS2::SysInfo()
-
Возвращает хеш с системной информацией. Ключи хеша:
MAX_PATH_LENGTH, MAX_TEXT_SESSIONS, MAX_PM_SESSIONS, MAX_VDM_SESSIONS, BOOT_DRIVE, DYN_PRI_VARIATION, MAX_WAIT, MIN_SLICE, MAX_SLICE, PAGE_SIZE, VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, MS_COUNT, TIME_LOW, TIME_HIGH, TOTPHYSMEM, TOTRESMEM, TOTAVAILMEM, MAXPRMEM, MAXSHMEM, TIMER_INTERVAL, MAX_COMP_LENGTH, FOREGROUND_FS_SESSION, FOREGROUND_PROCESS - OS2::BootDrive()
-
Возвращает букву без двоеточия.
-
OS2::MorphPM(serve),OS2::UnMorphPM(serve) -
Преобразует текущее приложение в приложение PM и обратно. Аргумент true означает, что будет обслуживаться настоящий цикл обработки сообщений. OS2::MorphPM() возвращает дескриптор очереди сообщений PM как целое число.
См. "Централизованное управление ресурсами" для получения дополнительных сведений.
-
OS2::Serve_Messages(force) -
Вымышленный запрос на получение необработанных сообщений PM. Если
forceложно, не будет отправлять сообщения, если настоящий цикл обработки сообщений известен. Возвращает количество полученных сообщений.Завершается с сообщением "QUITing..." при получении сообщения WM_QUIT.
-
OS2::Process_Messages(force [, cnt]) -
Получение сообщений PM до создания/уничтожения окна. Если
forceложно, не будет отправлять сообщения, если настоящий цикл обработки сообщений известен.Возвращает изменение количества окон. Если
cntзадан, он увеличивается на количество полученных сообщений.Завершается с сообщением "QUITing..." при получении сообщения WM_QUIT.
-
OS2::_control87(new,mask) -
то же, что и _control87(3) в EMX. Принимает целые числа в качестве аргументов, возвращает предыдущее слово управления сопроцессором как целое число. Только биты в
new, которые присутствуют вmask, изменяются в слове управления. - OS2::get_control87()
-
получает слово управления сопроцессором как целое число.
-
OS2::set_control87_em(new=MCW_EM,mask=MCW_EM) -
Вариант OS2::_control87() с значениями по умолчанию, подходящий для обработки маски исключений: если нет
mask, используется только часть маски исключенийnew. Если нетnew, отключаются все исключения с плавающей точкой.См. "Недостатки" для получения дополнительной информации.
-
OS2::DLLname([how [, \&xsub]]) -
Предоставляет информацию о Perl DLL или DLL, содержащей C-функцию, связанную с
&xsub. Значениеhow: по умолчанию (2): полное имя; 0: дескриптор; 1: имя модуля.
(Обратите внимание, что некоторые из них могут быть перемещены в разные библиотеки - со временем).
Переменные по умолчанию:
- $OS2::emx_rev
-
числовое значение совпадает с _emx_rev в EMX, строковое значение совпадает с _emx_vprt (аналогично
0.9c). - $OS2::emx_env
-
аналогично _emx_env в EMX, число, аналогичное 0x8001.
- $OS2::os_ver
-
число
OS_MAJOR + 0.001 * OS_MINOR. - $OS2::is_aout
-
true, если Perl-библиотека скомпилирована в формате AOUT.
- $OS2::can_fork
-
true, если текущий исполняемый файл - исполняемый файл AOUT EMX, поэтому Perl может выполнить fork. Не используйте это, используйте переносимую проверку $Config::Config{dfork}.
- $OS2::nsyserror
-
Эта переменная (по умолчанию 1) управляет тем, будет ли содержимое $^E начинаться с идентификатора типа
SYS0003. Если установлено в 0, то строковое значение $^E - это то, что доступно из файла сообщений OS/2. (Некоторые сообщения в этом файле имеют префикс типаSYS0003, некоторые нет.)
Недостатки
-
Поскольку flock(3) присутствует в EMX, но не работает, он эмулируется Perl. Чтобы отключить эмуляцию, установите переменную среды
USE_PERL_FLOCK=0. -
Вот список вещей, которые могут быть "сломаны" в EMX (из документации EMX):
-
Функции recvmsg(3), sendmsg(3) и socketpair(3) не реализованы.
-
sock_init(3) не требуется и не реализована.
-
flock(3) еще не реализован (пустая функция). (В Perl есть обходной путь.)
-
kill(3): Специальное обращение с PID=0, PID=1 и PID=-1 не реализовано.
-
WUNTRACED Not implemented. waitpid() is not implemented for negative values of PID.
Обратите внимание, что
kill -9не работает с текущей версией EMX. -
-
Unix-сокеты в OS/2 находятся в псевдофайловой системе
/sockets/.... Чтобы избежать отказа от создания сокета с именем другой формы,"/socket/"добавляется к имени сокета (если оно не начинается с этого уже).Это может привести к проблемам позже, если к сокету обращаются через "обычные" файловые вызовы с использованием "начального" имени.
-
По-видимому, IBM использовала компилятор (в какой-то период времени около '95?), который изменяет маску FP влево и вправо. Это не *такое* плохое решение для программ IBM, но тот же компилятор использовался для DLL, используемых в приложениях общего назначения. При использовании этих DLL состояние флагов с плавающей точкой в приложении непредсказуемо.
Что гораздо хуже, некоторые DLL изменяют флаги с плавающей точкой при вызове _DLLInitTerm() (например, TCP32IP). Это означает, что даже если вы не вызываете ни одну функцию в DLL, сам факт загрузки этой DLL сбросит ваши флаги. Что еще хуже, тот же компилятор использовался для компиляции некоторых DLL-модулей HOOK. Учитывая, что DLL HOOK выполняются в контексте *всех* приложений в системе, это означает полную непредсказуемость флагов с плавающей точкой на системах, использующих такие DLL HOOK. Например, GAMESRVR.DLL от DIVE origin изменяет флаги с плавающей точкой при каждом записи в TTY приложений VIO (окно в текстовом режиме).
Другие (не полностью отлаженные) ситуации, когда меняются флаги FP, включают некоторые драйверы видео (?), и некоторые операции, связанные с созданием окон. У людей, которые работают с OpenGL, может быть больше опыта в этом.
Perl обычно используется в ситуации, когда все исключения с плавающей точкой игнорируются, как и по умолчанию в EMX. Если они не игнорируются, некоторые доброкачественные программы Perl получат
SIGFPEи погибнут ужасной смертью.Для обхода этой проблемы Perl использует два хакерских приема. Они помогают только против *одного* типа повреждений: флагов FP, изменившихся при загрузке DLL.
Один из хаков - отключение исключений с плавающей точкой при запуске Perl (как и по умолчанию в EMX). Это помогает только с DLL, связанными во время компиляции, которые изменяют флаги до того, как main() успел вызваться.
Другой хак - восстановление флагов FP после вызова dlopen(). Это помогает против аналогичного повреждения, нанесенного DLL _DLLInitTerm() во время выполнения. В настоящее время нет способа отключить эти хаки.
Изменения
Perl изменяет некоторые стандартные вызовы C-библиотек следующим образом:
popen-
my_popenиспользует sh.exe, если требуется оболочка, см. "PERL_SH_DIR". tmpnam-
создается с помощью переменной среды
TMPилиTEMPчерезtempnam. tmpfile-
Если текущая директория недоступна для записи, файл создаётся с модифицированным
tmpnam, поэтому может возникнуть гонка ресурсов. ctermid-
имитация.
stat-
os2_statобрабатывает /dev/tty и /dev/con как специальные случаи. -
mkdir,rmdir -
эти функции EMX не работают, если путь содержит конечный
/. Perl содержит обходной путь для этого. flock-
Поскольку flock(3) присутствует в EMX, но не функционален, он эмулируется perl. Чтобы отключить эмуляцию, установите переменную среды
USE_PERL_FLOCK=0.
Идентификация DLL
Все DLL, построенные с текущими версиями Perl, содержат строки ID, определяющие имя расширения, его версию и требуемую версию Perl для этой DLL. Запустите bldlevel DLL-name для получения этой информации.
Централизованное управление ресурсами
Поскольку для вызова определённых API OS/2 необходимо иметь правильно инициализированный подсистему Win, расширения, специфичные для OS/2, могут потребовать получения HAB и HMQ. Если расширение будет делать это самостоятельно, другое расширение может не пройти инициализацию.
Perl обеспечивает централизованное управление этими ресурсами:
HAB-
Для получения HAB расширение должно вызвать
hab = perl_hab_GET()в C. После этого вызоваPerl_habможет быть доступен какPerl_hab. Нет необходимости освобождать HAB после его использования.Если по каким-либо причинам perl.h не может быть включён, используйте
extern int Perl_hab_GET(void);вместо этого.
HMQ-
Есть два случая:
-
расширению требуется
HMQтолько потому, что некоторые API в противном случае не будут работать. Используйтеserve = 0ниже. -
расширению требуется
HMQтак как оно хочет участвовать в цикле событий PM. Используйтеserve = 1ниже.
Для получения
HMQрасширение должно вызватьhmq = perl_hmq_GET(serve)в C. После этого вызоваhmqможет быть доступен какPerl_hmq.Чтобы сигнализировать Perl о том, что HMQ больше не нужен, вызовите
perl_hmq_UNSET(serve). Процесс Perl автоматически превратится/превратится обратно в процесс PM, если HMQ необходим/не необходим. Perl автоматически включит/выключит сообщенияWM_QUITво время завершения работы, если очередь сообщений обслуживается/не обслуживается.ПРИМЕЧАНИЕ. Если во время завершения работы есть очередь сообщений, которая не отключила WM_QUIT и не обработала полученное сообщение WM_QUIT, завершение автоматически отменяется. Не вызывайте
perl_hmq_GET(1), если не собираетесь обрабатывать сообщения упорядоченным образом. -
- Обработка ошибок, сообщённых API OS/2
-
Существует две основные конвенции (полезно назвать их
Dos*иWin*- хотя эта часть сигнатуры функции не всегда определяется именем API) для сообщения об ошибках API OS/2. Большинство APIDos*сообщают код ошибки в качестве результата вызова (так, 0 означает успех, и существует много типов ошибок). Большинство APIWin*сообщают успех/неуспех через результат, являющийсяTRUE/FALSE; чтобы определить причину неудачи, следует вызвать API WinGetLastError().Некоторые точки входа
Win*также перегружают «осмысленное» возвращаемое значение индикатором ошибки; возвращаемое значение 0 указывает на ошибку. Однако некоторые другие точки входаWin*перегружают вещи ещё больше, и возвращаемое значение 0 может означать успешный вызов, возвращающий действительное значение 0, а также условие ошибки; в случае возвращаемого значения 0 следует вызвать API WinGetLastError(), чтобы отличить успешный вызов от неудачного.По соглашению, все вызовы API OS/2 должны указывать на ошибки, сбрасывая $^E. Все доступные в Perl функции, которые вызывают API OS/2, можно разделить на два класса: некоторые вызывают die(), когда возникает ошибка API, другие сообщают об ошибке через ложное возвращаемое значение (конечно, это не касается функций, доступных в Perl, которые ожидают ошибки вызова API OS/2, имея обходные пути).
Очевидно, в случае последнего типа сигнатуры API OS/2 для пользователей будет удобнее, если ошибка сигнализируется с помощью die(): нет необходимости проверять $^E, чтобы узнать, что-то пошло не так. Однако, если по какой-либо причине это решение нежелательно, код должен сбросить $^E в 0 перед выполнением этого вызова API OS/2, чтобы вызывающий эту доступную в Perl функцию имел возможность отличить значение возврата 0 от успеха от ошибки. (Можно вернуть undef в качестве альтернативного способа сообщения об ошибке.)
Макросы для упрощения этого типа распространения ошибок
-
CheckOSError(expr) -
Возвращает true при ошибке, устанавливает $^E. Ожидается, что expr() будет вызовом API стиля
Dos*. -
CheckWinError(expr) -
Возвращает true при ошибке, устанавливает $^E. Ожидается, что expr() будет вызовом API стиля
Win*. -
SaveWinError(expr) -
Возвращает
expr, устанавливает $^E из WinGetLastError(), еслиexprложно. -
SaveCroakWinError(expr,die,name1,name2) -
Возвращает
expr, устанавливает $^E из WinGetLastError(), еслиexprложно, и вызывается die(), еслиdieи $^E истинны. Сообщение для die() - это конкатенированные строкиname1иname2, разделенные": "из содержимого $^E. WinError_2_Perl_rc-
Устанавливает
Perl_rcв возвращаемое значение WinGetLastError(). FillWinError-
Устанавливает
Perl_rcв возвращаемое значение WinGetLastError(), и устанавливает $^E в соответствующее значение. -
FillOSError(rc) -
Устанавливает
Perl_rcвrc, и устанавливает $^E в соответствующее значение.
-
- Загрузка DLL и порядковых номеров в DLL
-
Некоторые DLL присутствуют только в некоторых версиях OS/2 или в некоторых конфигурациях OS/2. Некоторые экспортируемые точки входа присутствуют только в DLL, поставляемых с некоторыми версиями OS/2. Если эти DLL и точки входа были связаны напрямую для исполняемого файла Perl/DLL или из расширений Perl, этот двоичный файл будет работать только с указанными версиями/настройками. Даже если эти точки входа не требовались, загрузка исполняемого файла (или DLL) завершится неудачей.
Например, многие новые полезные API отсутствуют в OS/2 v2; многие API, связанные с PM, требуют DLL, которые недоступны при установке с флоппи-диска.
Чтобы сделать эти вызовы неудачными только при их выполнении, следует вызывать эти API через API динамической загрузки. В Perl есть подсистема для упрощения такого типа вызовов. Предоставлен большой набор точек входа для такой загрузки (см.
entries_ordinals- и такжеPMWIN_entries- в os2ish.h). К этим порядковым номерам можно получить доступ через API:CallORD(), DeclFuncByORD(), DeclVoidFuncByORD(), DeclOSFuncByORD(), DeclWinFuncByORD(), AssignFuncPByORD(), DeclWinFuncByORD_CACHE(), DeclWinFuncByORD_CACHE_survive(), DeclWinFuncByORD_CACHE_resetError_survive(), DeclWinFunc_CACHE(), DeclWinFunc_CACHE_resetError(), DeclWinFunc_CACHE_survive(), DeclWinFunc_CACHE_resetError_survive()Подробности об использовании этих функций см. в заголовочных файлах и C-коде в прилагаемых модулях OS/2.
Некоторые из этих функций также сочетают семантику динамической загрузки с семантикой распространения ошибок, обсуждаемой выше.
Варианты Perl
Из-за особенностей OS/2 невозможно поместить все яйца в одну корзину (хотя среда EMX старается преодолеть эти ограничения, поэтому ситуация может как-то улучшиться). Распространение предоставляет 4 исполняемых файла для Perl:
perl.exe
Основной рабочий инструмент. Это исполняемый файл-химера: он компилируется как исполняемый файл типа a.out, но связан с динамической библиотекой типа omf perl.dll и динамической библиотекой CRT. Этот исполняемый файл является приложением VIO.
Он может загружать динамические расширения Perl и выполнять fork().
Примечание. Имейте в виду, что fork() необходим для открытия канала к себе.
perl_.exe
Это статически скомпилированный исполняемый файл типа a.out. Он не может загружать динамические расширения Perl. Исполняемый файл, поставляемый в двоичных распределениях, имеет множество предварительно скомпилированных расширений, поэтому вышеупомянутое ограничение важно только если вы используете расширения собственной разработки. Этот исполняемый файл является приложением VIO.
Это единственный исполняемый файл, который не требует OS/2. Друзья, запертые в мире M$ оценят тот факт, что этот исполняемый файл работает под DOS, Win0.3*, Win0.95 и WinNT с соответствующим расширителем. См. "Другие ОС".
perl__.exe
Этот исполняемый файл такой же, как perl___.exe, но это приложение PM.
Примечание. Обычно (если не перенаправлено явно во время запуска) STDIN, STDERR и STDOUT приложения PM перенаправляются в nul. Однако их можно увидеть, если запустить perl__.exe из программы PM, которая эмулирует окно консоли, например, режим оболочки Emacs или EPM. Таким образом, можно использовать отладчик Perl (см. perldebug) для отладки приложения PM (но будьте осторожны с блокировками цикла обработки сообщений - это не сработает, если у вас есть очередь сообщений для обработки, если вы не включите обработку в функцию getc() отладчика).
Другой способ увидеть вывод программы PM - запустить её как
pm_prog args 2>&1 | cat - с оболочкой отличной от cmd.exe, чтобы не создавать связь между сеансом VIO и сеансом pm_porg. (Такая связь закрывает окно VIO.) Например, это работает с sh.exe - или с Perl!
open P, 'pm_prog args 2>&1 |' or die;
print while <P>; Вариант perl__.exe требуется, если вы хотите запустить свою программу без окна VIO, но не detach (запустите help detach для получения дополнительной информации). Очень полезно для расширений, использующих PM, например, Perl/Tk или OpenGL.
Обратите также внимание, что различия между исполняемыми файлами PM и VIO заключаются только в поведении по умолчанию. Можно запустить любой исполняемый файл в любом типе сессии, используя ключи /fs, /pm или /win команды start (CMD.EXE или аналогичной оболочки). В качестве альтернативы можно использовать числовой первый аргумент функции system Perl (см. OS2::Process).
perl___.exe
Это исполняемый файл в формате omf, динамически связанный с perl.dll и CRT DLL. Мне неизвестны преимущества этого исполняемого файла по сравнению с perl.exe, но он не может использовать функцию fork(). Ну, одно преимущество заключается в том, что процесс сборки не такой запутанный, как с perl.exe.
Это приложение VIO.
Почему такие странные имена?
Поскольку Perl обрабатывает строку #! (см. "DESCRIPTION" в perlrun, "Команды переключения" в perlrun, "Скрипт Perl не найден в вводе" в perldiag), он должен знать, когда программа является Perl. Существует некоторая соглашение об именовании, которое позволяет Perl различать правильные строки и неправильные. Вышеперечисленные имена — почти единственные разрешенные соглашением об именовании, которые не содержат цифр (у которых совершенно другое семантическое значение).
Почему динамическая компоновка?
Ну, наличие нескольких исполняемых файлов, динамически связанных с одной большой библиотекой, имеет свои преимущества, но это не оправдывает дополнительных усилий по его компиляции. Причина заключается в сложной для разработчиков, но очень быстрой и удобной для пользователей «жесткой» динамической компоновке, используемой в OS/2.
Есть две отличительные особенности модели динамической компоновки OS/2: во-первых, все ссылки на внешние функции разрешаются на этапе компиляции; во-вторых, нет исправления ссылок DLL во время выполнения после их загрузки в память. Первое свойство является огромным преимуществом по сравнению с другими моделями: оно предотвращает конфликты, когда несколько DLL, используемых приложением, экспортируют записи с одинаковым именем. В таких случаях «другие» модели динамической компоновки просто выбирают между этими двумя точками входа, используя какой-то случайный критерий — с предсказуемыми катастрофическими результатами. Но именно второе свойство требует создания perl.dll.
Таблицы адресов DLL исправляются только один раз при их загрузке. Адреса точек входа в DLL гарантированно одинаковы для всех программ, использующих одну и ту же DLL. Это устраняет исправление во время выполнения — после загрузки DLL ее код становится только для чтения.
Хотя это позволяет получить некоторые (значительные?) преимущества производительности, это сильно затрудняет работу разработчикам, так как приведенная выше схема делает невозможным связывание DLL с символом в файле .EXE. Действительно, для этого DLL потребовались бы разные таблицы перемещений для (разных) исполняемых файлов, использующих эту DLL.
Однако динамически загружаемый Perl-расширение вынужден использовать некоторые символы из исполняемого файла perl, например, для того, чтобы знать, как найти аргументы для функций: аргументы находятся в внутренней стеке вычислений perl. Решение заключается в том, чтобы поместить основной код интерпретатора в DLL, а файл .EXE просто загружает эту DLL в память и предоставляет аргументы командной строки. Расширение DLL не может ссылаться на символы в файле .EXE, но у него нет проблем со ссылками на символы в файле .DLL.
Это значительно увеличивает время загрузки приложения (а также сложность компиляции). Поскольку интерпретатор находится в DLL, C RTL фактически вынужден находиться в DLL также (иначе расширения не смогут использовать CRT). Существуют некоторые преимущества, если вы используете разные версии perl, такие как одновременный запуск perl.exe и perl__.exe: они используют общую память perl.dll.
ПРИМЕЧАНИЕ. Существует один дополнительный эффект, который делает DLL более затратными: DLL загружаются в общую область памяти, которая является ограниченным ресурсом, учитывая барьер в 512 МБ «стандартной» виртуальной памяти OS/2. Код файлов .EXE также используется всеми процессами, которые используют конкретный .EXE, но они «делятся в частном адресном пространстве процесса»; это возможно, потому что адрес, по которому загружаются различные секции файла .EXE, определяется на этапе компиляции, поэтому все процессы загружают эти секции по тем же адресам, и исправление внутренних ссылок внутри .EXE не требуется.
Поскольку DLL могут загружаться во время выполнения, чтобы иметь ту же механику для DLL, необходимо иметь диапазон адресов любой из загруженных DLL в системе, доступный во всех процессах, которые еще не загрузили конкретную DLL. Вот почему DLL отображаются в общей области памяти.
Почему сборка химеры?
Текущая среда EMX не позволяет DLL, скомпилированным в формате Unixish a.out, экспортировать символы для данных (или, по крайней мере, некоторых типов данных). Это вынуждает использовать стиль компиляции omf для perl.dll.
Текущая среда EMX не позволяет файлам .EXE, скомпилированным в формате omf , использовать fork(). fork() необходим для ровно трех операций Perl:
-
явный fork() в скрипте,
-
open FH, "|-" -
open FH, "-|", другими словами, открытие каналов для себя.
Хотя эти операции не являются вопросом жизни и смерти, они необходимы для многих полезных скриптов. Это вынуждает использовать стиль компиляции a.out для perl.exe.
СРЕДА
Здесь перечислены переменные среды, которые являются либо специфичными для OS/2, DOS и Win*, либо более важными в OS/2, чем в других ОС.
PERLLIB_PREFIX
Специфично для порта EMX. Должно иметь вид
path1;path2 или
path1 path2 Если начало некоторого предопределённого пути совпадает с path1, оно заменяется на path2.
Следует использовать, если библиотека perl перемещена из стандартного расположения в предпочтение PERL(5)LIB, так как это не оставит неправильных записей в @INC. Например, если скомпилированная версия perl ищет @INC в f:/perllib/lib, а вы хотите установить библиотеку в h:/opt/gnu, сделайте
set PERLLIB_PREFIX=f:/perllib/lib;h:/opt/gnu Это заставит Perl с предварительно определённым @INC
f:/perllib/lib/5.00553/os2
f:/perllib/lib/5.00553
f:/perllib/lib/site_perl/5.00553/os2
f:/perllib/lib/site_perl/5.00553
. использовать следующий @INC:
h:/opt/gnu/5.00553/os2
h:/opt/gnu/5.00553
h:/opt/gnu/site_perl/5.00553/os2
h:/opt/gnu/site_perl/5.00553
. PERL_BADLANG
Если 0, perl игнорирует setlocale(), возвращающее ошибку. Может быть полезно с некоторыми странными локаль.
PERL_BADFREE
Если 0, perl не будет предупреждать о ненужном free(). С более старыми версиями perl это может быть полезно в сочетании с модулем DB_File, который был глючным при динамической компоновке и построении OMF.
Не следует устанавливать с более новыми версиями Perl, так как это может скрыть некоторые реальные проблемы.
PERL_SH_DIR
Специфично для порта EMX. Указывает директорию части местоположения sh.exe.
USE_PERL_FLOCK
Специфично для порта EMX. Поскольку flock(3) присутствует в EMX, но не функционален, он эмулируется perl. Чтобы отключить эмуляцию, установите переменную среды USE_PERL_FLOCK=0.
TMP или TEMP
Специфично для порта EMX. Используется в качестве места хранения временных файлов.
Эволюция
Здесь перечислены основные изменения, которые могут вас удивить.
Файловые дескрипторы в текстовом режиме
Начиная с версии 5.8, Perl использует встроенный уровень перевода для файлов в текстовом режиме. Это заменяет эффективную проверенную версию EMX некоторым кодом, который лучше всего можно охарактеризовать как «быстрый хак».
В дополнение к возможным ошибкам и невозможности отслеживать изменения в политике перевода с помощью переключателей включения/выключения перевода TERMIO, это вносит серьезное несовместимое изменение: раньше sysread() для файловых дескрипторов в текстовом режиме проходил через слой перевода, теперь нет.
Приоритеты
setpriority и getpriority несовместимы с более ранними портами Андрея Кайзера. См. "setpriority, getpriority".
Изменение имён DLL: до 5.6.2
С выпуском 5.003_01 динамически загружаемые библиотеки должны быть пересобраны при компиляции другой версии Perl. В частности, DLL (включая perl.dll) теперь создаются с именами, содержащими контрольную сумму, что позволяет обойти схему кэширования DLL в OS/2.
Возможно, можно написать простое решение, которое
-
найдёт старые DLL, просматривая старый @INC;
-
изменит имена в соответствии со схемой нового perl и скопирует DLL в эти имена;
-
изменит внутренние таблицы
LXDLL, чтобы отразить изменение имени (вероятно, не требуется для 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-расширения Perl всегда загружаются с полным путем, нет необходимости изменять их имена специфичным для версии способом: их каталог уже отражает соответствующую версию Perl, а @INC учитывает бинарную совместимость со старыми версиями. Начиная с 5.6.2 схема изменения имен закреплена такой же, как для Perl 5.005_53 (такой же, как в популярном двоичном выпуске). Таким образом, новые версии Perl смогут распознать имена старых DLL-расширений, если @INC позволяет найти их каталоги.
Однако это все равно не гарантирует, что эти DLL могут быть загружены. Причина заключается в изменении имени DLL Perl. И поскольку расширения DLL связываются с DLL Perl, расширения DLL для старых версий загружали бы старую DLL Perl и, скорее всего, бы зависли (так как данные в этой DLL не инициализированы должным образом).
Существует частичное решение (которое можно сделать полным с помощью более новых ядер OS/2): создать DLL-перенаправитель с тем же именем, что и DLL старой версии Perl, которая перенаправляет точки входа в DLL новой версии Perl. Сделайте эту DLL доступной (например) в BEGINLIBPATH нового исполняемого файла Perl. Когда новый исполняемый файл обращается к старым DLL-расширениям Perl, они запросят старую DLL Perl по имени, получат вместо нее перенаправитель, поэтому фактически свяжутся с текущей (новой) DLL Perl.
Это может нарушиться двумя способами:
-
Запущен старый исполняемый файл Perl, когда новый исполняемый файл загрузил расширение, скомпилированное для старого исполняемого файла (упс!). В этом случае старый исполняемый файл получит DLL-перенаправитель вместо старой DLL Perl, поэтому будет связан с новой DLL Perl. Хотя это не является непосредственно фатальным, он будет вести себя так же, как и новый исполняемый файл. Это разрушает всю цель явного запуска старого исполняемого файла.
-
Новый исполняемый файл загружает расширение, скомпилированное для старого исполняемого файла, когда запущен старый исполняемый файл Perl. В этом случае расширение не получит перенаправитель — с фатальными последствиями.
С поддержкой LIBPATHSTRICT это можно обойти — если один из DLL не запущен из . из LIBPATH (я не знаю, влияет ли LIBPATHSTRICT на этот случай).
ПРИМЕЧАНИЕ. Если более новые ядра позволяют . в BEGINLIBPATH (старые не позволяют), эта проблема не может быть полностью устранена. (Оказывается, что по состоянию на начало 2002 года . не разрешено, но .\. — да, и это имеет тот же эффект).
ПРИМЕЧАНИЕ. LIBPATHSTRICT, BEGINLIBPATH и ENDLIBPATH не являются переменными среды, хотя cmd.exe эмулирует их в SET ... строках. Из Perl они могут быть доступны по ссылкам Cwd::extLibpath и Cwd::extLibpath_set.
Генерация DLL-перенаправителя
Предположим, что старая DLL называется perlE0AC.dll (как одна для 5.005_53), а новая версия — 5.6.1. Создайте файл perl5shim.def-leader со следующим содержимым:
LIBRARY 'perlE0AC' INITINSTANCE TERMINSTANCE
DESCRIPTION '@#perl5-porters@perl.org:5.006001#@ Perl module for 5.00553 -> Perl 5.6.1 forwarder'
CODE LOADONCALL
DATA LOADONCALL NONSHARED MULTIPLE
EXPORTS изменив версии/имена по мере необходимости. Запустите
perl -wnle "next if 0../EXPORTS/; print qq( \"$1\")
if /\"(\w+)\"/" perl5.def >lst в каталоге построения Perl (чтобы сделать DLL меньше, замените perl5.def на файл определения для более старой версии Perl, если он есть).
cat perl5shim.def-leader lst >perl5shim.def
gcc -Zomf -Zdll -o perlE0AC.dll perl5shim.def -s -llibperl (проигнорируйте несколько warning L4085).
Потоки
Начиная с выпуска 5.003_01 perl связан с многопоточной DLL C RTL. Если сам perl не скомпилирован с поддержкой многопоточности, то и malloc() perl не будет многопоточным. Однако расширения могут использовать несколько потоков на свой страх и риск.
Это было необходимо для компиляции Perl/Tk для XFree86-OS/2 "из коробки" и связи с DLL других полезных библиотек, которые обычно компилируются с -Zmt -Zcrtdll.
Вызовы внешних программ
По популярному требованию вызов внешних программ perl был изменен по сравнению с портом Андрэаса Кайзера. Если perl нужно вызвать внешнюю программу через оболочку, будет вызван f:/bin/sh.exe, или любая другая замена, см. "PERL_SH_DIR".
Таким образом, вам также потребуется копия sh.exe (я использую одну из pdksh). Путь F:/bin выше автоматически устанавливается во время сборки до правильного значения на машине сборки, но может быть переопределён во время выполнения.
Причины: в результате соглашения по perl5-porters было решено, что perl должен использовать одну неизменяемую оболочку на платформу. Очевидные варианты для OS/2 — cmd.exe и sh.exe. Если бы perl сам создавал оболочку, это было бы невозможно с cmd.exe в качестве оболочки, поэтому я выбрал sh.exe. Это обеспечивает почти 100% совместимость со скриптами из *nix. В качестве дополнительного преимущества это работает и в DOS, если вы используете DOS-совместимую версию pdksh (см. "Требования").
Недостатки: в настоящее время sh.exe pdksh вызывает внешние программы через fork()/exec(), а exec() в OS/2 не работает. Exec() эмулируется EMX с помощью асинхронного вызова, в то время как вызывающая программа ожидает завершения дочернего процесса (чтобы создать иллюзию, что pid не изменилось). Это означает, что создается 1 дополнительная копия sh.exe, активная через fork()/exec(), что может привести к использованию дополнительных ресурсов системы (даже если мы не учитываем дополнительную работу, необходимую для fork()ing).
Обратите внимание, что эта проблема сейчас менее актуальна, поскольку мы не запускаем sh.exe, если это не требуется (обнаружены метасимволы).
Вы всегда можете явно запустить cmd.exe с помощью
system 'cmd', '/c', 'mycmd', 'arg1', 'arg2', ... Если вам нужно использовать cmd.exe и вы не хотите вручную редактировать тысячи ваших скриптов, долгосрочное решение, предложенное в p5-p, заключается в наличии директивы
use OS2::Cmd; которая переопределит system(), exec(), ``, и open(,'...|'). В текущей версии perl вы можете переопределить только system(), readpipe() — явную версию ``, и, возможно, exec(). Код заменит вызов system() с одним аргументом на CORE::system('cmd.exe', '/c', shift).
Если у вас есть рабочий код для OS2::Cmd, пришлите его мне, я включу его в дистрибутив. Мне не нужен такой модуль, поэтому я не могу его протестировать.
Подробности текущей ситуации с вызовом внешних программ см. в разделе "Запуск программ OS/2 (и DOS) в Perl". Заметим несколько особенностей:
-
Внешние скрипты могут вызываться по своему имени без расширения. Perl будет пробовать те же расширения, что и при обработке параметра командной строки -S.
-
Внешние скрипты, начинающиеся с
#!илиextprocбудут выполняться непосредственно, без вызова оболочки, вызывая программу, указанную в остальной части первой строки.
Выделение памяти
Perl использует свой собственный malloc() в OS/2 — интерпретаторы обычно ограничены malloc для скорости, но perl нет, так как его malloc очень быстрый. Тесты производительности, настроенные для использования памяти Perl, показывают, что malloc Perl в 5 раз быстрее, чем EMX.
Сочетание malloc() Perl и жёсткого разрешения имён DLL создаёт особую проблему с функциями библиотек, которые ожидают, что их возвращаемое значение будет освобождено system's free(). Чтобы облегчить расширения, которым нужно вызывать такие функции, функции выделения памяти системы все ещё доступны с префиксом emx_ добавленным. (В настоящее время это только для DLL perl, оно должно вскоре распространиться и на perl_.exe.)
Потоки
Можно скомпилировать perl с поддержкой потоков, указав параметр -D usethreads в Configure. В настоящее время поддержка потоков в OS/2 находится на очень предварительной стадии.
Основные проблемы:
COND_WAIT-
может иметь гонку (но, вероятно, нет из-за реактивного характера семафоров событий OS/2). (Нужно переделать (в терминах цепочки ожидающих потоков, с связанным списком, хранящимся в структуре потока?)?)
- os2.c
-
использует несколько статических переменных в OS/2-специфических функциях. (Нужно перенести в структуру каждого потока или сериализовать?)
Обратите внимание, что эти проблемы не должны отговаривать от экспериментов, поскольку у них низкая вероятность повлиять на небольшие программы.
ОШИБКИ
Это описание не обновляется часто (с 5.6.1?), см. ./os2/Changes для получения дополнительной информации.
АВТОР
Илья Захаревич, cpan@ilyaz.org
См. также
perl(1).
© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.28.3/perlos2