до сих пор работают без изменений на нынешних реализациях системы X. В мире Unix подобное долголетие является нормой, а причиной этого является позиция 'стандарт как ДНК'.
Таким образом, опыт показывает, что культура Unix, культивирующая уважение к стандартам, а также отбрасывание и переделку ошибочного кода, часто приводит к большей возможности взаимодействия в течение более продолжительного периода времени, чем постоянное исправление базы кода без стандарта, который обеспечивает управление и непрерывность. Это, несомненно, может быть одним из наиболее важных уроков Unix.
Последнее замечание Кита непосредственно приводит к вопросу, который выдвигается на передний план благодаря успеху Unix-систем с открытым исходным кодом — связь между открытыми стандартами и открытым исходным кодом. Данная проблема рассматривается в конце главы, но перед этим необходимо изучить практический вопрос: каким образом Unix-программисты могут действительно
17.5. Программирование, обеспечивающее переносимость
Переносимость программ обычно рассматривается в квази-пространственных понятиях: возможно ли перенести данный код на существующее аппаратно-программное обеспечение, отличное от того, для которого код создавался? Однако десятки лет опыта Unix подсказывают, что долговечность во времени важна в той же степени, если не в большей. Если бы можно было подробно предсказать будущее программного обеспечения, то оно, вероятно, было бы настоящим. Тем не менее, в программировании, обеспечивающем переносимость, следует пытаться обдумывать варианты построения программ на основе тех функций окружающей системы, которые, вероятнее всего, сохранятся, и избегать технологий, которые, скорее всего, в обозримом будущем прекратят свое существование.
Что касается Unix, два десятка лет изучения вопросов определения переносимых API-интерфейсов позволили полностью решить данную проблему. Средства, описанные в Единой спецификации Unix, вероятно, будут присутствовать во всех современных Unix-платформах и вряд ли не будут поддерживаться в будущем.
Однако не все зависимости от платформы разрешаются с помощью системных или библиотечных API-интерфейсов. Язык реализации также имеет значение; кроме того, проблемы могут быть обусловлены структурой файловой системы и конфигурационными отличиями между исходной и целевой системой. Однако практика Unix уже подтвердила способы решения данных проблем.
17.5.1. Переносимость и выбор языка
Первым вопросом в программировании, обеспечивающем переносимость, является выбор языка реализации. Все основные языки, рассмотренные в главе 14, являются высоко переносимыми в том смысле, что совместимые реализации доступны на всех современных Unix-системах, а для большинства из них также доступны реализации для Windows и MacOS. Проблемы переносимости часто возникают не в основных языках, а в библиотеках поддержки и степени интеграции с локальным окружением (особенно в IPC-методах и управлении параллельными процессами, включая инфраструктуру для GUI- интерфейсов).
17.5.1.1. Переносимость С
Базовый язык С в высшей степени переносим. Его стандартной реализацией в Unix является GNU C-компилятор, который повсеместно распространен не только Unix-системах с открытым исходным кодом, но и современных коммерческих вариантах операционной системы. GNU С был перенесен на Windows и классическую MacOS, но ни в одной из этих сред не стал широко распространенным, поскольку испытывает недостаток в переносимых привязках к собственным GUI-интерфейсам данных систем.
Стандартная библиотека ввода/вывода, математические подпрограммы и поддержка интернационализации переносимы во всех реализациях С. Файловый ввод/вывод, сигналы и управление процессами являются переносимыми между вариантами Unix, при условии, что используются только современные API-интерфейсы, описанные в Единой спецификации Unix; более старый C-код часто содержит нагромождения условных операторов препроцессора, направленных на достижение переносимости, но они поддерживают интерфейсы, появившиеся до стандарта POSIX, из старых коммерческих Unix-систем, которые по состоянию на 2003 год устарели или близки к этому.
Более серьезные проблемы с переносимостью С начинаются в области IPC, параллельных процессов и GUI-интерфейсов. Вопросы переносимости IPC и параллельных процессов обсуждались в главе 7. Реальную практическую проблему создают GUI-инструментарии. Большое количество GUI- инструментариев с открытым исходным кодом универсально переносятся между современными вариантами Unix, а также в Windows и классическую MacOS — Tk, wxWindows, GTK и Qt — четыре хорошо известных вида инструментария с открытым исходным кодом и документацией, которую нетрудной найти в Web. Однако ни один из них не распространяется со всеми платформами, и (по причинам более юридическим, чем техническим) ни один из них не предоставляет на всех платформах естественный вид и восприятие GUI-интерфейса. В главе 15 даны некоторые рекомендации, позволяющие справиться с данной проблемой.
По теме разработки переносимого C-кода написаны целые тома. Эта книга не входит в их число, и авторы рекомендуют внимательно изучить
17.5.1.2. Переносимость С++
Для С++ на уровне операционной системы характерны те же проблемы переносимости, что и для С, а также ряд собственных. Одной из дополнительных проблем является то, что GNU компилятор с открытым исходным кодом для С++ значительно отстает от коммерческих реализаций; поэтому к середине 2003 года не существовало универсально внедряемого эквивалента GNU С, на котором можно основывать стандарт де-факто. Более того, ни один из компиляторов С++ не реализовывает полностью ISO-стандарт C++99, хотя GNU С++ подошел к этому очень близко.
17.5.1.3. Переносимость shell
Переносимость shell-сценариев, к сожалению, является низкой. Проблема заключается не в самой оболочке;