суббота, 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, в общем ;)

12 комментариев:

Quaker комментирует...

Джон Кармак (id Software) давно говорил о том же: написание Linux версий ПО (игр) повышает качество кода.

Евгений Охотников комментирует...

Имхо, ничто так не повышает качество ПО, как отсутствие отладчика :)

Alex комментирует...

Я бы посмотрел в сторону VMWare Player, который стал бесплатным. Его killer feauture - Unity режим, в котором приложения запущенные из гостя отображаются как нормальные (обычные) окны хост системы. Есть интеграция меню. Я опробовал это на Windows гостях/хостах, но поддержка Linux тоже есть.
Знаю, что есть проблемы с установкой guest extensions для Slackware (например), но если речь идёт об *buntu, то проблем быть не должно.
Несколько лет сижу с VirtualBox. Система снэпшотов вызывает недоумение, стабильность работы (и снэпшотов, и вирт машин) - некоторые вопросы. Всё это ИМХО, конечно. Player с этой точки зрения умеет может и меньше, но делает это лучше.
Ещё один вариант - andLinux, но только для x86 Windows. Linux ядро, собранное для вызовов ядра windows. в каком-то смысле - лучше вирт машины, но это надо пробовать в конкретные сценариях использования.

Евгений Охотников комментирует...

2Alex:

я начинал с VMWare Workstation, не понравилось. Жрет много ресурсов, машина дольше грузится (даже если виртуалки не запускаются). В этом плане VirtualBox меня устраивает гораздо больше.

Alex комментирует...

На вкус и цвет...

Пользуюсь Боксом 3ей ветки (начиная со второй) и недавно попробовал VMWare Workstation 7 и Player 3. Процессор - Amd Athlon 64, не сильно новый, но с поддержкой виртуализации, Windows 7/x64, 4 гига памяти. В боксе бывают странные подвисания, когда старушка ни на что не реагирует. Раньше, когда таких процессоров не было в принципе (P4 Northwood, если не ошибаюсь) VMware тормозил просто ужасно, и Бокс производил гораздо лучшее впечатление.
Сейчас субъективно - VMWare Player шустрее.
Опять же, на ноутбуке от Intel Бокс кажется тормознее, чем Бокс на десктопе, но тут может играть роль медленный винт, т.к. памяти там 3 гига
.
Ну и в силу специфики использования, когда в виртуалке что-то крутится и надо постоянно переключать хост/гостя, то режим Unity - просто сказка.
Seamless integration, относительно недавно добавленный в Бокс - это что-то очень странное.

У VMWare реальная интеграция панели задач.

Евгений Охотников комментирует...

2Alex: спасибо за информацию. Если буду менять VM, обязательно посмотрю на VMWare Player.

Rustam комментирует...

Alex а чем Unity в VMware отличается от "режима интеграции дисплея" в VirtualBox?
У меня опыт наоборот Бокс устойчивей и шустрее работает, к нему у меня была только одна претензия кривые снимки но в 3.x версиях их исправили теперь они вполне нормальные без идиотских зависимостей.

Alex комментирует...

Снэпшоты я вообще не умею готовить. Каждый раз, когда я вижу названия пунктов меню, связанные со снэпшотами - впадаю в ступор и лезу в документацию, потому что возникает сильное ощущение, что какой бы вариант я не выбрал, случится что-то нехорошее. :-)
Про режим интеграции дисплея - я пробовал только Windows хосты, может быть в Linux хостах иначе (?)
Режим интеграции дисплея позволяет "вытащить" окна гостя из вирт машины и расположить их рядом с окнами приложений запущенных на хосте. Но переключение задач по Alt-tab:
1) если активно окно хоста, то в общем списке будет лишь значок вирт. бокса
2) если активно окно гостя, то будут показаны окна, запущенные в вирт. машине. Чтобы из вирт машины переключиться в хост, надо по-прежнему нажать "хост" клавишу (правый Alt) и только потом Alt-tab. Ну или пользоваться мышью.
Unity интегрирует окна гостя в панель задач хоста и показывает их при Alt-tab (и из гостя, и из хоста). У окон гостя - border (настраиваемого) цвета. Совсем другой ритм работы. Вроде бы также работает Parallels (под Mac), но там другое название этого режима и я его не видел.
Ну а относительно стабильности/скорости трудно спорить. Теперь есть бесплатная версия VMWare player и можно экспериментировать. Хотя Player не поддерживает снэпшоты вообще никак.

Alex комментирует...

P.S. И Player 3ей версии позволяет создавать машины (раньше был нужен Workstation). И можно конвертировать диск Бокса в VMWare, хотя и с шаманством - экспорт/импорт не работает.
Справедливости ради - на работе нужно было тестить под MacOS, запускал под VMWare 6.5 сборку iDeneb - это было ужасно. Может это специфика конфигурации, тормоза очень ощущались.

Quaker комментирует...

На Windows (в качестве хост-системы) VMWare гораздо лучше работает, чем VirtualBox. У VirtualBox встречаются иногда полные замирания гостевого Linux даже на мощных системах. Под Linux в качестве хост-системы говорят, что все чуть ли не с точностью до наоборот, но сам не проверял, подтвердить не могу. Как выйдет финальная версия 7.1 vmware workstation, переползу на нее с виртуалбокса.

Quaker комментирует...

И еще в дополнение темы про Linux. По моему мнению, Kubuntu не так хорошо отшлифован, как Ubuntu. Среди KDE дистрибутивов советую обратить внимание на недавно вышедший PCLinuxOS (http://pclinuxos.com/). Под VirtualBox он у меня работал лучше всего. Или в крайнем случае на Mandriva 2010.0 (тоже достаточно хорошо работает, но не так быстро, как PCLinuxOS).

Евгений Охотников комментирует...

2Quaker: спасибо, когда придет время ставить себе новый linux, обязательно гляну и в ту сторону.