суббота, 17 апреля 2010 г.

[prog.work] (не)большой производственный лытдыбр

Последние три дня прошли в приключениях при портировании большого C++ного проекта под Linux. Точнее говоря, приключения были не столько с портированием, сколько с Linux-ом. Хотя и с портированием было интересно и поучительно :)

Linux я себе на “голое железо” зарекся ставить уже очень давно. Поскольку работаю на ноутбуках, а Linux-ы на ноутбуках – это отдельная песня. Поэтому на ноутбуки я ставлю Windows с родными драйверами от производителей, а Linux-ы держу под виртуалками. Очень удобно.

Последний Linux, который у меня был – это Kubuntu 8.04. Но я его не запускал, наверное, с прошлого года. Как пересел на новый ноутбук, так даже виртуальную машину не устанавливал. А тут понадобилось и, как всегда, в условиях цейтнота :) Поэтому поставил себе VirtualBox 3.1.6. Новый VirtualBox старый образ Kubuntu поднял, но оказалось, что я там чего-то начал переделывать, но не доделал и оставил систему в полуразобранном состоянии. Ну и чтобы не заниматься восстановлением старой системы, решил поставить себе Kubuntu 9.10.

К сожалению, решил делать я это в офисе, где доступ в Интернет через прокси. А инсталлятор Kubuntu, как мне показалось, этого очень не любит, даже не смотря на то, что параметры прокси в инсталляторе выставить можно. Поэтому Kubuntu стала как-то криво. Вроде бы и работала, но с помощью шаманских плясок и бубнов. Например, захотел я заменить Ruby 1.8 на Ruby 1.9, проинсталлировал пакет ruby1.9, но ruby не запускался. Хотя KPackageKit упорно показывал, что пакет есть. Какие-то странные вещи были с g++ – изначально в системе его не было, пришлось ставить пакет g++-4.4.1. Поставил, но g++ не запускался.

Случайно выяснилось, что все устанавливалось, но под странными именами: ruby назывался не ruby, а ruby1.9 и запускать его нужно было как ruby1.9. Аналогично и с g++ – вместо команды g++ была команда g++4.4. Но апофеозом всего этого стала попытка проинсталлировать rubygems через KPackageKit и apt-get. KPackageKit просто говорил, что нет зависимостей, но даже не сообщал, каких именно. Apt-get указывал, что нет RDoc, Irb, и еще чего-то, вплоть до readline5. А вот где взять readline5 я вообще не смог понять, поскольку в системе стоял readline6, а следов readline5 не было вообще.

Кое как настроил все это дело вручную, сказав много матерных слов в адрес самых разных людей :) Процесс портирования начался. Но вскоре началась новая беда – стоило чему-то произойти с сетевым окружением на host-машине, как guest-система в виртуалке переставала видеть svn-репозиторий. А потом и еще одна напасть – виртуальная машина не всегда стартовала при перезагрузках. То VirtualBox упадет, то сам Kubuntu где-то на середине загруки повиснет. В общем, хотел все сделать за один день, но пришлось отложить на следующий.

А на следующий день, с утреца, посмотрев на все это безобразие, решил установить Kubuntu заново. И правильно сделал. Повезло, что инсталляцию я проводил дома, где нормальный Интернет без проксей. Поскольку при инсталляции Kubuntu что-то увлеченно качала из Интернета и потом все встало как надо. И KPackageKit работает, и пакеты нормально устанавливаются, и с сетью проблемы нет, и при перезагрузках ничего не падает. Лепота, в общем.

Впечатления от Kubuntu 9.10 самые благоприятные. Аналогично и от VirtualBox-а. Тем, кто будет ставить Linux под VirtualBox-ом в первый раз, маленький совет: после установки Linux будет работать в разрешении 800x600. Чтобы его увеличить, нужно подмонтировать в качестве CD-ROM-а образ VBoxGuestAdditions.iso из VirtualBox-а, а потом запустить оттуда в guest-системе соответствующий файлик (VBoxLinuxAdditions-x86.run). После этого и разрешение в Linux-е станет больше, и появится очень удобная интеграция мыши.

После того, как Kubuntu нормально задышал, начался, собственно, процесс портирования моего большого проекта. В качестве компилятора использовался GCC 4.4.1. Был приятно поражен тем, что GCC сейчас анализирует форматные строки в sprintf-е и предупреждает, если спецификатор формата не соответствует переданному типу значения (попробуйте, например, указать “%02d” и передать значение long int).

Нашел у себя один серьезный баг, который сидел в программе не пойми сколько времени, и никогда не проявлялся ни под VC++ 7.1, ни под GCC 3.4.*. Но основная часть проблем заключалась в двух вещах:

  1. Для функций из стандартных C-шных библиотек, вроде sprintf и strcmp, не подключались соответствующие заголовочные файлы. Т.е. когда работаешь под VC++, то <cstdio> загружается где-нибудь в <iostreams> или <string>, поэтому функция sprintf оказывается в области видимости и без явной загрузки <cstdio>. А вот в GCC 4.4.1 стандартные заголовочные файлы загружают себя по другому и компилятор ругается на то, что символ sprintf не определен.
  2. Я постоянно забываю при определении своих классов исключений писать в деструкторе throw(). VC++ 7.1 это фиолетово, а вот GCC ругается, т.к. у std::exception деструктор имеет спецификатор throw().

В общем, сильно пожалел о том, что не делал периодического портирования этого проекта под Linux в течении последнего года. Раньше я это делал – и по производственной необходимости, и просто так – для профилактике. Поэтому такие ошибки выявлялись быстрее и в меньшем количестве. А тут их сразу несколько десятков, и все в разных модулях из разных подпроектов… Так что совет: если есть возможность, то гоняйте свои проекты под разными компиляторами, от разных производителей. C++, конечно, переносим на уровне исходников, но за эту переносимость приходится платить.

Еще одна штука, связанная с портированием. Меньше всего возни было со сторонними проектами, для которых мы сами сделали обвязки для нашей системы сборки и поместили их исходники в свой репозиторий. Такие проекты просто разворачивались самим svn через свойство svn:externals, а потом естественным образом компилировались в рамках всего большого проекта. А вот с libiconv и openssl-ем пришлось потрудится – ставить их отдельно и компилировать вручную (кстати, не понятно, почему в Kubuntu не оказалось пакетов для этих библиотек – чего-нибудь вроде libiconv-dev, openssl-dev). Так что еще один раз убедился в том, насколько удобно держать точные версии всех зависимостей в собственном репозитории.

Кстати еще о зависимостях и больших проектах. Сейчас нужно раздербанить проект на несколько разных частей, каждая из которых получит самостоятельное развитие. Плюс, в дебрях этого проекта скопилось несколько удобных и почти универсальных вещей, которые следует оформить в виде повторно-используемых самостоятельных компонентов. Т.е. большой проект начинает выглядеть как сборник не сильно связанных между собой пакетов. Вести их все в рамках одной ветки репозитория уже не кажется разумным. Хочется каждый из них выделить в отдельную ветку. И каким-то образом прописать между ними зависимости. А здесь уже напрашивается и следующий шаг – какая-то система пакетов, с манифестами и GUI-инструментом для выбора нужного их сочетания. Нестареющий велосипедостроитель внутри меня настойчиво уговаривает взяться за реализацию такой штуки :) Но, может быть уже есть готовые кроссплатформенные решения для C++? Вроде бы в CMake есть что-то связанное с пакетами – может кто-то знаком?

Еще есть небольшие подвижки на SObjectizer-овском фронте. Подружил SObjectizer 4.4.0-b6 с ACE-5.7.*. Оказалось, правда, что в ACE-5.7 нет проектных файлов для VC++7.1, поэтому с ACE 5.7.* SObjectizer будет работать только в VC++8 и VC++9. Но пока не удалось решить проблему с рестартом дефолтного реактора. Зараза, не работает с асинхронными сокетами при перезапуске SObjectizer Run-Time. И не понятно пока, мой ли это косяк, или же в ACE-овском реакторе есть баги. Буду разбираться. Получится или нет – не знаю, но хочу к концу апреля выкатить очередной патч для SObjectizer, чтобы на ACE 5.6.* не сидеть больше.

На неделе скачал себе ISO-шный образ с VisualStudio 2010 Express Edition. В котором C++ный компилятор с частичной поддержкой C++0x. Но не было времени поставить. А хочется уже познакомиться лично с лямбдами и rvalue references. Тем более, что на днях и GCC 4.5.0 вышел. Так что в двух мейнстримовых С++ных компиляторах лямбды уже есть, а у меня были связаны с ними большие надежды в плане сокращения многословности для SObjectizer-5. Еще хочется поскорее с VC++10 разобраться, чтобы в MxxRu новый тулсет добавить – vc10, в компанию к vc7, vc8 и vc9. Нужно только время найти для этого :/

Такие дела. В планах еще две-три заметки для блога по поводу моих впечатлений от Java. Stay tunned, в общем ;)

Отправить комментарий