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 достаточно поместить их в ваш путь. Не нужно указывать их явно (хотя это
emx perl_.exe -de 0тоже сработает.)
- RSX
-
Для запуска Perl на платформах DPMI необходима среда выполнения RSX. Это необходимо в DOS-внутри-OS/2, Win0.3*, Win0.95 и WinNT (см. "Другие операционные системы"). RSX не будет работать только с VCPI, как EMX, она требует DMPI.
Имея RSX и самую последнюю версию sh.exe, вы получаете полностью функциональную среду типа *nix в DOS, например,
fork,``и работу с каналами-open. Фактически, MakeMaker работает (для статической сборки), поэтому можно иметь среду разработки Perl в DOS.RSX можно получить, например, из
http://cd.textfiles.com/hobbesos29804/disk1/EMX09C/ ftp://crydee.sai.msu.ru/pub/comp/os/os2/leo/gnu/emx+gcc/contrib/Свяжитесь с автором по адресу
rainer@mathematik.uni-bielefeld.de.Последняя версия sh.exe с DOS-обработкой доступна в
http://www.ilyaz.org/software/os2/как sh_dos.zip или под похожими именами, начинающимися с
sh,pdkshи т. д. - HPFS
-
Perl не заботится о файловых системах, но библиотека perl содержит много файлов с длинными именами, поэтому для его целостной установки требуется файловая система, поддерживающая длинные имена файлов.
Обратите внимание, что если вы не планируете собирать сам perl, то возможно обмануть EMX, чтобы обрезать имена файлов. Это не поддерживается, ознакомьтесь с документацией EMX, чтобы узнать, как это сделать.
- pdksh
-
Для запуска внешних программ со сложными командными строками (например, с каналами и/или цитированием аргументов) Perl использует внешний интерпретатор команд. В порте EMX такой интерпретатор команд должен называться sh.exe и находиться либо в жестко заданных местах во время компиляции (обычно F:/bin), либо в настраиваемом месте (см. "
PERL_SH_DIR").Для наилучших результатов используйте EMX pdksh. Стандартная версия (5.2.14 или выше) работает и в DOS (с "RSX"), см.
http://www.ilyaz.org/software/os2/
Запуск программ Perl в OS/2 (и DOS и...)
Запустите вашу программу Perl foo.pl с аргументами arg1 arg2 arg3 так же, как и на любой другой платформе, набрав
perl foo.pl arg1 arg2 arg3 Если вы хотите указать параметры perl -my_opts самому perl (в отличие от вашей программы), используйте
perl -my_opts foo.pl arg1 arg2 arg3 В качестве альтернативы, если вы используете оболочку типа OS/2, например CMD или 4os2, поместите следующее в начале вашей программы perl:
extproc perl -S -my_opts переименуйте вашу программу в foo.cmd и запустите её, набрав
foo arg1 arg2 arg3 Обратите внимание, что из-за глупых ограничений OS/2 полный путь к скрипту perl недоступен при использовании extproc, поэтому вы вынуждены использовать переключатель -S perl, и ваш скрипт должен быть в PATH. В качестве плюса, если вы знаете полный путь к своему скрипту, вы можете все равно запустить его с
perl ../../blah/foo.cmd arg1 arg2 arg3 (обратите внимание, что аргумент -my_opts обрабатывается строкой extproc в вашем скрипте, см. "extproc" on the first line).
Чтобы понять, что делает вышеупомянутый магический код, прочитайте документацию perl по переключателю -S — см. perlrun, и документацию cmdref по extproc:
view perl perlrun
man perlrun
view cmdref extproc
help extproc или любым другим способом, который вам нравится.
Также существует множество возможностей использовать расширения исполняемых файлов 4os2, ассоциации WPS и т. д… Однако, если вы используете оболочку типа *nix (например, sh.exe, поставляемую в дистрибутиве), вам нужно следовать синтаксису, указанному в "Command Switches" in perlrun.
Обратите внимание, что переключатель -S поддерживает скрипты с дополнительными расширениями .cmd, .btm, .bat, .pl тоже.
Запуск программ OS/2 (и DOS) в Perl
Для этого предназначены функции system() (см. "system" in perlfunc), `` (см. "I/O Operators" in perlop) и открытие канала (см. "open" in perlfunc). (Избегайте exec() (см. "exec" in perlfunc), если вы не знаете, что делаете).
Обратите внимание, однако, что для использования некоторых из этих операторов вам нужна установленная оболочка с синтаксисом sh (см. "Pdksh", "Часто задаваемые вопросы"), и perl должен быть в состоянии её найти (см. "PERL_SH_DIR").
Случаи, когда используется оболочка:
-
Функция system() с одним аргументом (см. "system" in perlfunc), exec() (см. "exec" in perlfunc) с перенаправлением или символами метаязыка оболочки;
-
Открытие канала (см. "open" in perlfunc) с командой, содержащей перенаправление или символы метаязыка оболочки;
-
Операторы обратных кавычек
``(см. "I/O Operators" in perlop) с командой, содержащей перенаправление или символы метаязыка оболочки; -
Если исполняемый файл, вызываемый system()/exec()/pipe-open()/
``является скриптом с магической строкой#!или строкойextprocкоторая задаёт оболочку; -
Если исполняемый файл, вызываемый system()/exec()/pipe-open()/
``является скриптом без магической строки, и$ENV{EXECSHELL}установлен для оболочки; -
Если исполняемый файл, вызываемый system()/exec()/pipe-open()/
``не найден (не устарел ли этот комментарий?); -
Для подстановки шаблонов (см. "glob" in perlfunc, "I/O Operators" in 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. Необходимо каким-то образом заключить двойные кавычки в другое цитирование, обязательно с дополнительной не-юниксовой оболочкой посередине.
Используйте одну из
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.34.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-документации, доступной для браузеров WWW, и документации в бесчисленных других форматах:info,LaTeX,Acrobat,FrameMakerи так далее. [Используйте программы, такие как pod2latex и т. д.] - Руководство по Perl в формате .INF
-
unzip perl_inf.zip -d d:/os2/bookЭтот каталог лучше всего расположить в
BOOKSHELF. - Pdksh
-
unzip perl_sh.zip -d f:/binЭто используется perl для запуска внешних команд, которые явно требуют оболочки, например, команд, использующих перенаправление и метасимволы оболочки. Также используется вместо явного /bin/sh.
Установите
PERL_SH_DIR(см. "PERL_SH_DIR"), если вы перемещаете sh.exe из вышеупомянутого расположения.Примечание. Возможно использование какой-либо другой совместимой с sh оболочки (не протестировано).
После установки необходимых компонентов и соответствующего обновления Config.sys, вам нужно вручную отредактировать Config.pm. Этот файл находится где-то глубоко в месте установки вашей библиотеки perl, найдите его с помощью
perl -MConfig -le "print $INC{'Config.pm'}" Вам необходимо исправить все записи, которые выглядят как пути к файлам (в настоящее время они начинаются с f:/).
Предупреждение
Автоматическая и ручная установка perl оставляют предварительно скомпилированные пути внутри исполняемых файлов perl. Хотя эти пути можно перезаписать (см. "PERLLIB_PREFIX", "PERL_SH_DIR"), некоторые люди могут предпочесть двоичное редактирование путей внутри исполняемых файлов/DLL.
Доступ к документации
В зависимости от того, как вы построили/установили perl, у вас может быть (в остальном идентичная) документация Perl в следующих форматах:
Файл OS/2 .INF
Вероятно, самая удобная форма. В OS/2 это выглядит как
view perl
view perl perlfunc
view perl less
view perl ExtUtils::MakeMaker (в настоящее время последние два могут попасть в неправильное место, но это скоро может улучшиться). В Win* см. "ОПИСАНИЕ".
Если вы хотите сгенерировать документацию самостоятельно и у вас есть инструментарий OS/2, выполните
pod2ipf > perl.ipf в каталоге /perllib/lib/pod, затем
ipfc /inf perl.ipf (Ожидайте много ошибок во время обеих операций.) Теперь переместите его в свой каталог документации.
Текстовый формат
Если у вас есть документация 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 выше - для предотвращения конфликта с man-страницей less(1).
Убедитесь, что каталог над каталогом с документацией находится в нашем MANPATH, например так
set MANPATH=c:/man;f:/perllib/man для документации Perl в f:/perllib/man/man1/ и т. д.
HTML
Если у вас есть доступный веб-браузер, установлена документация Perl в исходной форме и утилиты Perl, вы можете сгенерировать HTML-документацию. Перейдите в каталог с файлами .pod и выполните следующие действия
cd f:/perllib/lib/pod
pod2html После этого вы можете открыть в браузере файл perl.html в этом каталоге и приступить к чтению документации, как показано ниже:
explore file:///f:/perllib/lib/pod/perl.html В качестве альтернативы вы можете получить эти документы, уже сгенерированные, с помощью CPAN.
Файлы GNU info
Пользователям Emacs это очень пригодится, особенно с загруженным режимом CPerl. Вам необходимо получить последние pod2texi с CPAN, или, в качестве альтернативы, уже сгенерированные страницы info.
Файлы PDF
для Acrobat доступны на CPAN (возможно, для немного более старой версии Perl).
Документация LaTeX
может быть сгенерирована с помощью pod2latex.
Сборка
Здесь мы обсудим, как собрать Perl под OS/2.
Краткое описание процесса
Предположим, что вы опытный пользователь, уверены, что все необходимые инструменты уже присутствуют в вашей системе, и знаете, как получить исходное распределение Perl. Извлеките его, перейдите в каталог с извлечёнными файлами и
gnupatch -p0 < os2\diff.configure
sh Configure -des -D prefix=f:/perllib
make
make test
make install
make aout_test
make aout_install Это поместит исполняемые файлы в f:/perllib/bin. Переместите их вручную в PATH, вручную переместите созданные perl*.dll в LIBPATH (здесь для Perl DLL * — не имеющий особого смысла шестнадцатеричный контрольный код) и выполните
make installcmd INSTALLCMDDIR=d:/ir/on/path Предполагая, что файлы man были помещены в соответствующее место, это завершает установку минимальной системы Perl. (Бинарное распределение также содержит множество дополнительных модулей и документацию в формате INF.)
Далее следует подробное руководство по этим шагам.
Предварительные условия
Вам нужна последняя среда разработки EMX, полный набор инструментов GNU (gawk переименован в awk, и GNU find.exe расположен выше в пути, чем OS/2 find.exe, также с sort.exe, чтобы проверить, используйте
find --version
sort --version ). Вам нужна последняя версия pdksh, установленная как sh.exe.
Проверьте, установлены ли библиотеки и заголовки BSD, а также — по желанию — заголовки и библиотеки Berkeley DB и crypt.
Возможные места для получения файлов:
ftp://ftp.uni-heidelberg.de/pub/os2/unix/
http://hobbes.nmsu.edu/h-browse.php?dir=/pub/os2
http://cd.textfiles.com/hobbesos29804/disk1/DEV32/
http://cd.textfiles.com/hobbesos29804/disk1/EMX09C/ Сообщается, что следующие архивы содержат достаточно утилит для сборки Perl: gnufutil.zip, gnusutil.zip, gnututil.zip, gnused.zip, gnupatch.zip, gnuawk.zip, gnumake.zip, gnugrep.zip, bsddev.zip и ksh527rt.zip (или более поздняя версия). Обратите внимание, что все эти утилиты, как известно, доступны в LEO:
ftp://crydee.sai.msu.ru/pub/comp/os/os2/leo/gnu/ Также обратите внимание, что db.lib и db.a из дистрибутива EMX не подходят для многопоточной компиляции (даже однопоточная версия Perl использует многопоточную C RTL для совместимости с XFree86-OS/2). Получите исправленную версию из
http://www.ilyaz.org/software/os2/db_mt.zip Если у вас установлена точно такая же версия Perl, убедитесь, что в данный момент не запущены какие-либо копии или экземпляры perl. Более поздние этапы сборки могут завершиться неудачей, так как в памяти может быть загружена более старая версия perl.dll. Запуск make test становится бессмысленным, так как тесты проверяют предыдущую версию сборки perl (эта ситуация обнаруживается и сообщается тестом os2/os2_base.t). Не забудьте сбросить PERL_EMXLOAD_SEC в среде.
Также убедитесь, что каталог /tmp находится на текущем диске и каталог . в вашей LIBPATH. Можно попытаться исправить последнее условие, выполнив
set BEGINLIBPATH .\. если вы используете что-то вроде CMD.EXE или последние версии 4os2.exe. (Установка BEGINLIBPATH только на . игнорируется ядром OS/2.)
Убедитесь, что ваш gcc подходит для -Zomf линковки: выполните скрипт omflibs в каталоге /emx/lib.
Проверьте, установлен ли link386. Он входит в стандартную поставку OS/2, но может быть не установлен из-за настройки. Если ввод
link386 показывает, что он отсутствует, выполните Выборочную установку и выберите Link object modules в Дополнительные системные утилиты/Ещё. Если вы попадете в приглашения link386, нажмите Ctrl-C для выхода.
Получение исходного кода Perl
Вам нужно получить последний исходный код Perl (включая релизы разработчиков). С определённой вероятностью он находится в
http://www.cpan.org/src/
http://www.cpan.org/src/unsupported Если нет, вам может потребоваться поискать его в индексах в каталоге текущего разработчика.
Быстрый цикл релизов разработчиков время от времени может нарушить процесс сборки под OS/2, поиск в
http://www.cpan.org/ports/os2/ может указать на последнюю версию, которая была опубликована разработчиком. Обратите внимание, что релиз может включать дополнительные исправления, которые нужно применить к текущему исходному коду Perl.
Извлеките его так:
tar vzxf perl5.00409.tar.gz Вы можете увидеть сообщение об ошибках при извлечении Configure. Это связано с конфликтом с аналогичным файлом configure.
Перейдите в каталог извлечения.
Применение исправлений
Вам нужно применить исправления из ./os2/diff.* следующим образом:
gnupatch -p0 < os2\diff.configure Вам также может потребоваться применить исправления, входящие в состав бинарного дистрибутива Perl. Также имеет смысл обратиться к списку рассылки perl5-porters по последним исправлениям, относящимся к OS/2 (см. http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/). Такие исправления обычно содержат строки /os2/ и patch, поэтому имеет смысл искать эти строки.
Редактирование вручную
Вы можете посмотреть файл ./hints/os2.sh и исправить любые ошибки, которые вы там найдёте. Я не ожидаю, что это потребуется в любом случае.
Сборка
sh Configure -des -D prefix=f:/perllib prefix означает: куда установить получившуюся библиотеку perl. Указав правильный префикс, вы можете избежать необходимости указывать PERLLIB_PREFIX, см. "PERLLIB_PREFIX".
Игнорируйте сообщение об отсутствии ln, и об опции -c для tr. Вероятно, последняя уже исправлена, если вы её видите и можете отследить, откуда исходит это ложное предупреждение, сообщите мне об этом.
Теперь
make В какой-то момент сборка может завершиться сбоем, сообщая о несоответствии версии или невозможности запустить perl. Это означает, что у вас нет . в вашей LIBPATH, поэтому perl.exe не может найти необходимый perl67B2.dll (рассматривайте эти шестнадцатеричные цифры как шумовые данные). После исправления этого сбоя сборка должна завершиться без особых проблем.
Тестирование
Теперь выполните
make test Все тесты должны быть пройдены (некоторые из них могут быть пропущены). Если у вас установлена та же версия Perl, крайне важно, чтобы . находилась в начале вашего LIBPATH (или в BEGINLIBPATH), в противном случае ваши тесты, скорее всего, будут проверять не ту версию Perl.
Некоторые тесты могут генерировать дополнительные сообщения, подобные
-
Множество
bad free -
в тестах базы данных, связанных с Berkeley DB. Это должно быть уже исправлено. Если проблема сохраняется, вы можете отключить эти предупреждения, см. "
PERL_BADFREE". - Процесс завершён по сигналу SIGTERM/SIGINT
-
Это стандартное сообщение, выдаваемое приложениями OS/2. Приложения *nix завершаются без сообщений. Это считается особенностью. Можно легко отключить это с помощью соответствующих обработчиков сигналов.
Однако система тестирования выводит эти сообщения на экран в неожиданные моменты. Два таких сообщения *должны* присутствовать во время тестирования.
Для получения более подробных отчётов о тестах вызовите
perl t/harness Отчёт с io/pipe.t, завершившимся ошибкой, может выглядеть так:
Failed Test Status Wstat Total Fail Failed List of failed
------------------------------------------------------------
io/pipe.t 12 1 8.33% 9
7 tests skipped, plus 56 subtests skipped.
Failed 1/195 test scripts, 99.49% okay. 1/6542 subtests failed,
99.98% okay. Причины самых важных пропущенных тестов:
- op/fs.t
-
- 18
-
Проверяет
atimeиmtimeвstat()— к сожалению, HPFS предоставляет только 2-секундную точность временных меток (для совместимости с FAT?). - 25
-
Проверяет
truncate()на файле, только что открытом для записи — я не знаю, почему это должно или не должно работать.
- op/stat.t
-
Проверяет
stat(). Тесты:- 4
-
Проверяет
atimeиmtimeвstat()— к сожалению, HPFS предоставляет только 2-секундную точность временных меток (для совместимости с FAT?).
Установка собранного Perl
Если вы ещё не перенесли perl*.dll в LIBPATH, сделайте это сейчас.
Выполните
make install Это поместит сгенерированные файлы в нужные места. Вручную поместите perl.exe, perl__.exe и perl___.exe в местоположение в вашем PATH, perl.dll — в местоположение в вашем LIBPATH.
Выполните
make installcmd INSTALLCMDDIR=d:/ir/on/path чтобы преобразовать утилиты perl в файлы .cmd и поместить их в PATH. Вам нужно вручную поместить утилиты с расширением .EXE в путь. Они установлены в $prefix/bin, здесь $prefix — то, что вы указали в Configure, см. "Сборка".
Если вы используете man, либо перенесите установленные каталоги */man/ в ваш MANPATH, либо измените MANPATH для соответствия расположению. (Можно было бы избежать этого, предоставив корректную опцию manpath для ./Configure или отредактировав ./config.sh между этапами конфигурирования и сборки.)
Сборка в стиле a.out
Продолжайте как выше, но создайте perl_.exe (см. "perl_.exe") с помощью
make perl_ тестируйте и устанавливайте с помощью
make aout_test
make aout_install Вручную поместите perl_.exe в местоположение в вашем PATH.
Примечание. Процесс сборки для perl_ не знает обо всех зависимостях, поэтому вы должны убедиться, что все обновлено, например, выполнив
make perl_dll сначала.
Сборка бинарного дистрибутива
[Этот раздел содержит только краткий обзор...]
Процесс сборки должен отличаться в зависимости от того, уже присутствует ли и используется ли устанавливаемая версия Perl в вашей системе или это новая версия, которая ещё не используется. Описание ниже предполагает, что версия новая, поэтому установка её DLL и файлов .pm не нарушит работу вашей системы, даже если некоторые промежуточные шаги ещё не полностью работают.
В других случаях требуются несколько более запутанные процедуры. Ниже я предполагаю, что текущая версия Perl — 5.8.2, поэтому исполняемые файлы имеют соответствующие имена.
-
Полностью создайте и протестируйте дистрибутив 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для ускорения пропуска поддиректорий с уже завершённой сборкой.Когда вы удовлетворены результатами тестов, установите библиотеки сборки для расширений:
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. -
Убедитесь, что установленные модули действительно установлены в расположении нового 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 можно легко пересобрать в любой момент. Более того, можно использовать интерфейс embedding (см. 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 и т. д.
Если вы чувствуете себя комфортно с интерфейсом embedding (см. perlembed), такие вещи легко сделать, повторив шаги, описанные в "Создание исполняемых файлов с настраиваемым набором статически загруженных расширений", и выполнив более полные правки в функции main() в perlmain.c. Люди, мало желающие понимать Perl, могут просто переименовать main() и выполнить необходимые изменения в пользовательской функции main(), которая вызывает переименованную функцию в соответствующее время.
Однако есть и третий способ: DLL Perl экспортирует функцию main() и несколько обратных вызовов для настройки пути поиска. Ниже приведён полный пример «загрузчика Perl», который
-
Ищет Perl DLL в каталоге
$exedir/../dll; -
Добавляет указанный выше каталог в
BEGINLIBPATH; -
Возникает ошибка, если Perl DLL, найденная по
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–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.34.0/perlos2