Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #51, ФЕВРАЛЬ 2005 г.

Из Windows в *nix

Крис Касперски ака мыщъх

Спецвыпуск: Хакер, номер #051, стр. 051-086-1


Пособие по портированию приложений

ЭПИГРАФ

…задачи, решаемые с помощью компьютера, нередко самим компьютером и порождаются.

Пол Грэм

Последнее время много разговоров о переносе *nix-программ на Windows. Только так, но никак не иначе. А ведь существует большое количество Windows-программ, аналога которым на других платформах не существует (прежде всего это твои собственные программы). Стоит ли их переносить на *nix, и если да, то как?

Абсолютного переносимого программного обеспечения не существует, как не существует абсолютного нуля. Понятие "переносимость" еще не означает, что портирование сводится к простой перекомпиляции. Всегда требуются дополнительные усилия по его адаптации. Иногда эти усилия настолько значительны, что проще переписать программу с нуля, чем гонять ее между платформами. Системно-ориентированные пакеты (FAR, soft-ice) переносить вообще бессмысленно.

В любом случае ты должен полностью разобраться в исходных текстах, которые переносишь. При доминирующем стиле кодирования интерфейс программы перемешан с "вычислительной" частью (спасибо визуальными средам разработки!), и разделить их не проще, чем сиамских близнецов (но разделять все же придется). Типичный код нашпигован большим количеством системно-зависимых функций: вместо стандартных библиотечных функций преобладают вызовы API и MFC. Активно используются ассемблерные вставки и повсеместно – умолчания компилятора. Это в Borland’е char по умолчанию unsigned, а в других компиляторах он ведет себя совсем не так! Про "умолчанную" кратность выравнивания структур я вообще молчу. Хуже только нестандартные расширения компилятора и специфические особенности его поведения. Большинство программ, созданных современными "программистами", не компилируются MS VC, если написаны на BCC и, соответственно, наоборот. До переноса на *nix им так же далеко, как их авторам до звания "программиста" (необязательно даже "почетного программиста", можно просто "стажера", путающего язык со средой разработки).

Считается, что перенос сокращает издержки на развитие и сопровождение проекта. Имея независимые версии для Windows и *nix, ты вынужден вносить исправления и гонять баги в обеих программах одновременно. Портабельный код этих недостатков лишен. Якобы. Скажи, когда-нибудь ты пробовал писать программу, компилируемую более чем одним компилятором? Ругался при этом? И правильно! Я бы тоже ругался. Ограничения, налагаемые переносимым кодом, лишают нас многих возможностей языка и значительно увеличивают трудоемкость разработки. Допустим, ты используешь шаблоны (Templates), и на MS VC все работает, но при переходе на другой компилятор программа разваливается к черту. А некоторые компиляторы не инициализируют статические экземпляры класса. Ну не инициализируют и все тут! Забудь о стандартах. Компиляторы все равно их не придерживаются.

При каждом внесении изменений в программу прогоняй ее через все целевые компиляторы. Код, специфичный для данной платформы, заботливо окружи #ifdef или вынеси в отельный файл, ну и т.д. В конечном счете ты получишь все те же два независимых проекта, но тесно переплетенные друг с другом, причем внесение изменений в один из них дает непредсказуемый эффект в другом. Нет-нет, не подумай! Я вовсе не противник переносимого кода, просто не понимаю тех, для кого переносимость является целью, а не средством. Никто не спорит, что такие проекты, как Apache или GCC, должны изначально разрабатываться как переносимые (процент системно-независимого кода в них очень велик), но вот мелкую утварь типа почтового клиента лучше затачивать под индивидуальную платформу, а при переходе на *nix переписывать заново.

Содержание  Вперед на стр. 051-086-2