Иногда бывает так, что необходимо что-нибудь исправить в исходнике и пересобрать какую-нибудь программу. Причем, дело осложняется тем, что программа - часть какого-нибудь большого проекта, например KDE4 или GNOME. Взять отдельно её исходники и пересобрать программу с помощью "configure; make; make install (checkinstall)" практически невозможно. Невозможно потому, что для компиляции наверняка потребуются исходники или, как минимум заголовки, общих для всего проекта библиотек. Причем исходники библиотек потребуются именно той версии среды, которая установлена в системе. Спрашивается, где их взять, если в официальном VCS даже для вашей ветки проект "уехал" вперед? Ужос и кошмар одним словом.
Правильный выход в данной ситуации - подключить deb-src репозитарии, и пересобрать программу именно из тех исходников, которые использовали авторы дистрибутива.
Действия будем проводить на конкретном примере - нам надо подправить исходники программы Konsole из среды рабочего стола KDE4. Программа Konsole уже установлена в систему, но нам что-то не нравится в её работе, например форма курсора. Мы скачем исходники, внесём изменения, скомпилируем и установим в систему нашу новособранную программу. Итак, начнем.
Шаг первый - подготовка
Вначале надо убедиться, что в файле /etc/apt/sources.list есть строки, в которых прописаны репозитарии исходников. Например, в Debian Squeeze должны присутсвовать строки:
deb http://ftp.ru.debian.org/debian/ squeeze main non-free contrib
deb-src http://ftp.ru.debian.org/debian/ squeeze main non-free contrib
Строка, начинающаяся с deb-src - это и есть репозитарий исходников.
Для дальнейшего понимания нужно объяснить пару вещей, которые в документации почему-то зачастую пропускают.
Во-первых, нужно запомнить, что для каждого пакета из deb обязательно существует его исходник в deb-src. Исключение составляют только мета-пакеты, но они нам неинтересны. То есть, если вы в synaptic видите пакет с именем, например, iptables, то в командах получения исходников нужно использовать это же имя iptables.
Во-вторых, нужно знать, что после прописывания строк, начинающихся с deb-src в /etc/apt/sources.list, и после последующей команды "apt-get update", вы в synaptic или aptitude не увидите пакетов с исходниками. Они будут подключены, система будет знать об пакетах-исходниках, но вы не увидите их наличие.
Шаг второй - получение и распаковка исходников
В своей рабочей директории нужно создать какой-нибудь каталог, который будет использоваться для сборки. Надо зайти в него, и последующие команды нужно выполнять в этом каталоге.
От обычного пользователя (не от рута) даём команду:
$ apt-get source konsole
В результате будут скачаны файлы исходников и размещены в текущем каталоге. Вывод будет примерно вот такой:
Необходимо получить 4 082 kб архивов исходного кода.
Получено:1 http://ftp.ru.debian.org/debian/ squeeze/main kdebase 4:4.4.5-2 (dsc) [2 068 B]
Получено:2 http://ftp.ru.debian.org/debian/ squeeze/main kdebase 4:4.4.5-2 (tar) [4 046 kB]
Получено:3 http://ftp.ru.debian.org/debian/ squeeze/main kdebase 4:4.4.5-2 (diff) [33,6 kB]
Получено 4 082 kБ за 44с (91,3 kБ/c)
dpkg-source: инфо: извлечение kdebase в kdebase-4.4.5
dpkg-source: инфо: распаковывается kdebase_4.4.5.orig.tar.bz2
dpkg-source: инфо: распаковывается kdebase_4.4.5-2.debian.tar.gz
dpkg-source: инфо: накладывается debian-T-addition.diff
Шаг третий - установка зависимых пакетов
Далее нужно получить зависимые пакеты, которые могут понадобиться для сборки нашей программы. От рута даём команду:
# apt-get build-dep konsole
В результате чего будут закачаны и установлены все пакеты, без которых не заработает сборка нашей программы.
Шаг четвёртый - компиляция
Для компиляции нажно сделать не совсем обычную вещь. В нашем текущем каталоге, в результате наших действий, образовались всякие новые файлы и подкаталоги. Нам нужно нужно найти файл с именем "rules". Это исполнимый файл. У меня он оказался расположен так:
./kdebase-4.4.5/debian/rules
После того, как его нашли, нужно относительно него подняться на каталог выше, и дать от обычного пользователя команду:
$ fakeroot ./debian/rules binary
В результате работы этой команды вначале запустится компиляция, а затем в текущем рабочем каталоге должен появиться *.deb-файл, внутри которого будет лежать только что скомпилированная программа. Может оказаться так, что будет сгенерирован не один *.deb, а несколько, соответсвущих другим программам, находящихся в том же пакете с исходниками.
Например, у меня были сгенерированы следующие пакеты:
dolphin_4.4.5-2_i386.deb
kappfinder_4.4.5-2_i386.deb
kdebase-apps_4.4.5-2_all.deb
kdebase-bin_4.4.5-2_i386.deb
kdebase-data_4.4.5-2_all.deb
kdebase-dbg_4.4.5-2_i386.deb
kdepasswd_4.4.5-2_i386.deb
kfind_4.4.5-2_i386.deb
kinfocenter_4.4.5-2_i386.deb
konqueror_4.4.5-2_i386.deb
konqueror-nsplugins_4.4.5-2_i386.deb
konsole_4.4.5-2_i386.deb
kwrite_4.4.5-2_i386.deb
libkonq5_4.4.5-2_i386.deb
libkonq5-dev_4.4.5-2_i386.deb
libkonq5-templates_4.4.5-2_all.deb
libkonqsidebarplugin4a_4.4.5-2_i386.deb
libkonqsidebarplugin-dev_4.4.5-2_i386.deb
plasma-widget-folderview_4.4.5-2_i386.deb
Среди этих пакетов есть и интересующий нас konsole_4.4.5-2_i386.deb.
Шаг пятый - установка
Чтобы установить новый пакет поверх имеющегося, нужно от рута дать команду:
# dpkg -i konsole_4.4.5-2_i386.deb
Хехе, скорее всего команду эту вы будете выполнять в Konsole? Это делать ненадо, а то установка вылетит на середине, когда будут заменять файлы Konsole. Нужно запустить xterm, и там выполнить от рута данную команду.
Исправление исходника
На шагах 1...5 мы убедились, что исходники у нас имеются, и они собираются без ошибок. Теперь можно внести изменения в исходники, и получить исправленную нами программу.
Как было написано вначале, нам не нравится форма курсора в Konsole. Многие олдфаги привыкли к мигающем курсору в виде подчеркивания. Такая форма курсора есть в терминале Konsole среды KDE4, но форма представлена в виде тоненькой чёрточки высотой в 1 пиксель. Такой курсор трудно находить на экране.
В то же время, если внимательно рассмотреть курсор в Text Mode, можно убедиться, что он имеет высоту как минимум 2 пикселя, и за счет такой жирности хорошо детектируется на пространстве экрана. При этом курсор не является вырвиглазным блоком, занимающим целое знакоместо.
Небольшой экскурс в историю.
Знакосимвольные терминалы обычно имели два вида курсора, которые можно было переключать, записывая в определённый порт нужное значение. Был курсор-подчеркивание, и курсор-блок. Кроме того, можно было настраивать, мигает курсор или нет. Эти настройки были реализованы как в советских микрокомпьютерах, имеющих видеоадаптер на микросхеме КР580ВГ75, так и на более старших моделях - всяких ЕС и IBM PC/XT.
Вот так выглядел курсор-подчеркивание:
Обратите внимание на общие размеры курсора относительно букв, и на то, что верхняя линия курсора находится на том же уровне, что и точка, то есть курсор не "провален" вниз. Еще фотографии дисплеев:
ДВК-3М2: http://www.leningrad.su/museum/show_big.php?n=1059
ДВК-2: http://www.leningrad.su/museum/show_big.php?n=1190
ДВК-2М: http://www.leningrad.su/museum/show_big.php?n=1054
Электроника-88: http://www.leningrad.su/museum/show_big.php?n=1270
EC 1845: http://www.leningrad.su/museum/show_big.php?n=310
EC 1845: http://www.leningrad.su/museum/show_big.php?n=320
Роботрон: http://www.leningrad.su/museum/show_big.php?n=308
Общее на всех этих фотографиях то, что высота курсора два пикселя, а не один. Отцы-основатели знали что делали, в отличие от нынешних кодеров-обезьянок.
Итак, нам нужно изменить толщину курсора. Рендеринг курсора был найден в файле:
./kdebase-4.4.5/apps/konsole/src/TerminalDisplay.cpp
В этом файле находим метод drawCursor, и находим место, в котором отрисовывается курсор в виде подчеркивания. Вот это место:
...
else if ( _cursorShape == UnderlineCursor )
painter.drawLine(cursorRect.left(),
cursorRect.bottom(),
cursorRect.right(),
cursorRect.bottom());
...
Нам нужно нарисовать две линии, поэтому заменяем данный код вот таким:
...
else if ( _cursorShape == UnderlineCursor )
{
painter.drawLine(cursorRect.left(),
cursorRect.bottom(),
cursorRect.right(),
cursorRect.bottom());
painter.drawLine(cursorRect.left(),
cursorRect.bottom()-1,
cursorRect.right(),
cursorRect.bottom()-1);
}
...
Далее выполняем шаги 4 и 5, запускем Konsole, и видим прекрасный курсор, такой, какой нам надо. Теперь моя консоль выглядит просто прелестно: