Возможно, многие сталкивались с ситуацией, когда программа или библиотека из дистрибутива не содержит некоторой (нужной вам) функциональности, которая была добавлена в следующей версии. Или содержит баг, который был исправлен в следующей версии (или его исправление не было включено в основную ветку), а в репозитории вашего дистрибутива всё ещё содержится старая версия.
Именно с таким багом столкнулся я, а также все пользователи редактора JuffEd (новая версия которого, кстати, вышла на днях), использующие в качестве рабочего окружения среду GNOME под Linux. Баг этот заключается в том, что при использовании автокомплита его окошко появляется на мгновение, после чего пропадает, «унося» за собой фокус. На данном примере я покажу, как можно самостоятельно патчить программы из дистрибутива.
Описанный баг — это баг библиотеки QScintilla, который проявляется во всех программах, использующих данный компонент (например, аналогичное поведение наблюдается в Eric4). Если вы не пользуетесь ни одной из перечисленных программ, но руки чешутся попробовать — можете установить одну из них чисто в экспериментальных целях. Но, повторяю, баг проявляется только под GNOME, а под KDE всё работает.
Я отправил патч разработчикам и провёл некоторое его тестирование, но если они и включат этот патч, то в следующей версии. А что делать тем, кто использует не самые новые дистрибутивы? В данном случае ситуация ещё осложняется тем, что новая версия библиотеки (2.4) бинарно несовместима с предыдущей (2.3, которая содержится, например, в Ubuntu 9.04), поэтому просто собрать и установить версию 2.4 после того, как они решат данную проблему, будет нельзя — программы, собранные с использованием «родной» версии 2.3, при использовании версии 2.4 падают в 100% случаев.
Ну что, напугал? :) А теперь меньше слов, больше дела!
Будем собирать «родную» версию, но с нужным нам патчем. Я опишу весь процесс на случай, когда мы правим что-то с нуля, а также расскажу о более коротких путях, на случай, когда патч уже существует.
Итак, создадим каталог для экспериментов и перейдём в него:
Для начала нам понадобятся исходники ровно той версии, которая установлена у Вас в системе. Это делается не просто, а очень просто:
Но для этого у вас наравне с основными репозиториями должны быть подключены репозитории с исходниками:
Итак, получили ровно те исходники, из которых был собран тот пакет, который находится репозитории. Большинство (если не все) пакетов имеют дистро-специфичные патчи, которые в случае Debian-based дистрибутивов лежат в подкаталоге debian/patches. Эти патчи применяются перед самой сборкой, и наша задача — положить туда деб-патч с нужным нам исправлением. Для этого нам понадобится утилита dpatch. Устанавливаем её (а также несколько других утилит, которые понадобятся нам при сборке) и переходим в основной каталог с программой:
Мы видим, что в каталоге debian/patch находятся 3 файла: файл 00list и 2 файла с расширением .dpatch. Как нетрудно догадатся, файл 00list содержит список патчей, а оставшиеся файлы — это патчи и есть. Чтобы не возникало путаницы, те патчи, которые находятся в каталоге debian/patches и которые предназначены для программы dpatch, я буду называть деб-патчами, а просто патчами будут называться обычные исправления, которые могут быть созданны программой diff и которые обычно используются программой patch для внесения изменений.
Те, кого интересует результат, а сам процесс — не особо, могут скачать готовый деб-патч тут, положить его в каталог debian/patches и перейти к абзацу в конце данного раздела, который начинается словами «Если теперь мы заглянем в каталог debian/patches....»
Те же, кого интересует сам процесс, читают дальше инструкцию, как изготовить такой деб-патч самостоятельно.
Чтобы создать свой собственный деб-патч, находясь в основном каталоге программы выполним команду dpatch-edit-patch <patch_name>, где <patch_name> — имя нового деб-патча. При этом будет создана временная копия всего каталога исходных текстов, и наш шелл будет автоматически перенаправлен в неё. Тут мы можем править исходники так, как считаем нужным, после чего просто выходим из этого «вложенного шелла» командой exit, и результатом всех этих действий будет нужный нам деб-патч, содержащий все сделанные изменения. Править можно как вручную, так и при помощи команды patch (обычной patch, не dpatch), накладывая патчи, созданные кем-то другим.
Итак, правку вручную я оставляю за кадром, т.к. у каждого она может быть индивидуальна (можно убрать что-нибудь ненужное, а можно просто добавить в About-диалог «Мир, Труд, Май!» или что-нибудь ещё), а покажу как использовать готовые патчи на примере рассматриваемого случая, а именно для исправления автодополнения в QScintilla. Вот патч, который я послал разработчикам QScintilla. Сохраните его себе на диск.
Скачать патч
Итак, теперь всё то, что я рассказал выше многими непонятными словами, проделаем при помощи коротких и понятных команд :) Мы находимся в основном каталоге исходников qscintilla2-2.3.2:
Если теперь мы заглянем в каталог debian/patches, то увидим, что там появился ещё один файл с именем 03_autocomplete.dpatch. Всё, что нам осталось сделать — это добавить его имя (без расширения .dpatch) в файл 00list. Если вы забудете это сделать, то пакет соберётся без наших изменений и ничем не будет отличаться от того, что лежит в репозитории.
Находясь всё так же в основном каталоге исходников, выполняем
Он обязательно ругнётся, что удовлетворены не все зависимости для сборки. Устанавливаем всё, что он просит. На совершенно чистой машине для этого потребуется скачать 46.7 МБ архивов, после распаковки которых будет занято 181 МБ на диске. Если что-то из этого у вас уже установлено — то качать придётся меньше. Львиную долю составляют девелоперские библиотеки Qt4 (30.6 МБ и 124 МБ соответственно).
В комментариях ниже хабраюзер arty совершенно справедливо заметил, что зависимости можно установить при помощи
и таким образом не придётся руками перечислять все требуемые пакеты.
После установки всего требуемого запускаем сборку ещё раз:
Теперь всё должно пойти без вопросов.
Если вы всё сделали правильно на предыдущих этапах, то через некоторе время сборка окончится (ругнувшись на отсутствие цифровой подписи, но это можно проигнорировать), и в каталоге уровнем выше появится несколько deb-пакетов. Нас интересует один из них: libqscintilla2-3_2.3.2-0ubuntu2_i386.deb. Устанавливаем его
и [пере]запускаем программы, которые используют данную библиотеку (например, JuffEd).
Вуаля! Автокомплит работает!
Если есть дополнения или замечания — добро пожаловать в комментарии.
Для самых ленивых — уже собранный и пропатченный пакет для Ubuntu 9.04 (i386)
UPD1: прошу прощения, залил не тот пакет. Если скачали deb, установили и ничего по-прежнему не работает — скачайте ещё раз:
$ md5sum libqscintilla2-3_2.3.2-patched-1ubuntu2_i386.deb
e5047bb52011d80b06e82fafe5063a73 libqscintilla2-3_2.3.2-patched-1ubuntu2_i386.deb
UPD2: пропатченый пакет для Ubuntu 9.10 (i386)
Именно с таким багом столкнулся я, а также все пользователи редактора JuffEd (новая версия которого, кстати, вышла на днях), использующие в качестве рабочего окружения среду GNOME под Linux. Баг этот заключается в том, что при использовании автокомплита его окошко появляется на мгновение, после чего пропадает, «унося» за собой фокус. На данном примере я покажу, как можно самостоятельно патчить программы из дистрибутива.
Описанный баг — это баг библиотеки QScintilla, который проявляется во всех программах, использующих данный компонент (например, аналогичное поведение наблюдается в Eric4). Если вы не пользуетесь ни одной из перечисленных программ, но руки чешутся попробовать — можете установить одну из них чисто в экспериментальных целях. Но, повторяю, баг проявляется только под GNOME, а под KDE всё работает.
Я отправил патч разработчикам и провёл некоторое его тестирование, но если они и включат этот патч, то в следующей версии. А что делать тем, кто использует не самые новые дистрибутивы? В данном случае ситуация ещё осложняется тем, что новая версия библиотеки (2.4) бинарно несовместима с предыдущей (2.3, которая содержится, например, в Ubuntu 9.04), поэтому просто собрать и установить версию 2.4 после того, как они решат данную проблему, будет нельзя — программы, собранные с использованием «родной» версии 2.3, при использовании версии 2.4 падают в 100% случаев.
Ну что, напугал? :) А теперь меньше слов, больше дела!
Готовим ингредиенты
Будем собирать «родную» версию, но с нужным нам патчем. Я опишу весь процесс на случай, когда мы правим что-то с нуля, а также расскажу о более коротких путях, на случай, когда патч уже существует.
Итак, создадим каталог для экспериментов и перейдём в него:
$ mkdir -p experiments/qscintilla
$ cd experiments/qscintilla
Для начала нам понадобятся исходники ровно той версии, которая установлена у Вас в системе. Это делается не просто, а очень просто:
$ apt-get source libqscintilla2-3
Но для этого у вас наравне с основными репозиториями должны быть подключены репозитории с исходниками:
Итак, получили ровно те исходники, из которых был собран тот пакет, который находится репозитории. Большинство (если не все) пакетов имеют дистро-специфичные патчи, которые в случае Debian-based дистрибутивов лежат в подкаталоге debian/patches. Эти патчи применяются перед самой сборкой, и наша задача — положить туда деб-патч с нужным нам исправлением. Для этого нам понадобится утилита dpatch. Устанавливаем её (а также несколько других утилит, которые понадобятся нам при сборке) и переходим в основной каталог с программой:
$ sudo aptitude install dpatch cdbs fakeroot build-essential patch
$ cd qscintilla2-2.3.2/
Добавляем основную изюминку
Мы видим, что в каталоге debian/patch находятся 3 файла: файл 00list и 2 файла с расширением .dpatch. Как нетрудно догадатся, файл 00list содержит список патчей, а оставшиеся файлы — это патчи и есть. Чтобы не возникало путаницы, те патчи, которые находятся в каталоге debian/patches и которые предназначены для программы dpatch, я буду называть деб-патчами, а просто патчами будут называться обычные исправления, которые могут быть созданны программой diff и которые обычно используются программой patch для внесения изменений.
Те, кого интересует результат, а сам процесс — не особо, могут скачать готовый деб-патч тут, положить его в каталог debian/patches и перейти к абзацу в конце данного раздела, который начинается словами «Если теперь мы заглянем в каталог debian/patches....»
Те же, кого интересует сам процесс, читают дальше инструкцию, как изготовить такой деб-патч самостоятельно.
Чтобы создать свой собственный деб-патч, находясь в основном каталоге программы выполним команду dpatch-edit-patch <patch_name>, где <patch_name> — имя нового деб-патча. При этом будет создана временная копия всего каталога исходных текстов, и наш шелл будет автоматически перенаправлен в неё. Тут мы можем править исходники так, как считаем нужным, после чего просто выходим из этого «вложенного шелла» командой exit, и результатом всех этих действий будет нужный нам деб-патч, содержащий все сделанные изменения. Править можно как вручную, так и при помощи команды patch (обычной patch, не dpatch), накладывая патчи, созданные кем-то другим.
Итак, правку вручную я оставляю за кадром, т.к. у каждого она может быть индивидуальна (можно убрать что-нибудь ненужное, а можно просто добавить в About-диалог «Мир, Труд, Май!» или что-нибудь ещё), а покажу как использовать готовые патчи на примере рассматриваемого случая, а именно для исправления автодополнения в QScintilla. Вот патч, который я послал разработчикам QScintilla. Сохраните его себе на диск.
--- Qt4/SciClasses.cpp 2009-10-16 10:09:48.000000000 -0400
+++ Qt4/SciClasses.cpp 2009-10-16 10:11:01.000000000 -0400
@@ -128,7 +128,7 @@
SciListBox::SciListBox(QWidget *parent, ListBoxQt *lbx_)
: QListWidget(parent), lbx(lbx_)
{
- setWindowFlags(Qt::Tool|Qt::FramelessWindowHint);
+ setWindowFlags(Qt::ToolTip|Qt::WindowStaysOnTopHint);
setAttribute(Qt::WA_StaticContents);
setFocusProxy(parent);
Скачать патч
Итак, теперь всё то, что я рассказал выше многими непонятными словами, проделаем при помощи коротких и понятных команд :) Мы находимся в основном каталоге исходников qscintilla2-2.3.2:
$ dpatch-edit-patch 03_autocomplete (создаём новый деб-патч и попадаем в каталог с копией исходников)
$ patch -p0 < /path/to/our/qscintilla_autocomplete.patch (патчим исходники существующим патчем)
$ exit (выходим из "виртуального шелла")
Если теперь мы заглянем в каталог debian/patches, то увидим, что там появился ещё один файл с именем 03_autocomplete.dpatch. Всё, что нам осталось сделать — это добавить его имя (без расширения .dpatch) в файл 00list. Если вы забудете это сделать, то пакет соберётся без наших изменений и ничем не будет отличаться от того, что лежит в репозитории.
$ echo "03_autocomplete" >> debian/patches/00list
Варим! То есть собираем
Находясь всё так же в основном каталоге исходников, выполняем
$ dpkg-buildpackage -rfakeroot
Он обязательно ругнётся, что удовлетворены не все зависимости для сборки. Устанавливаем всё, что он просит. На совершенно чистой машине для этого потребуется скачать 46.7 МБ архивов, после распаковки которых будет занято 181 МБ на диске. Если что-то из этого у вас уже установлено — то качать придётся меньше. Львиную долю составляют девелоперские библиотеки Qt4 (30.6 МБ и 124 МБ соответственно).
$ sudo aptitude install libqt4-dev python-all-dev sip4 python-sip4 python-sip4-dev python-qt4-dev python-qt4
В комментариях ниже хабраюзер arty совершенно справедливо заметил, что зависимости можно установить при помощи
apt-get build-dep [package name]
и таким образом не придётся руками перечислять все требуемые пакеты.
После установки всего требуемого запускаем сборку ещё раз:
$ dpkg-buildpackage -rfakeroot
Теперь всё должно пойти без вопросов.
Если вы всё сделали правильно на предыдущих этапах, то через некоторе время сборка окончится (ругнувшись на отсутствие цифровой подписи, но это можно проигнорировать), и в каталоге уровнем выше появится несколько deb-пакетов. Нас интересует один из них: libqscintilla2-3_2.3.2-0ubuntu2_i386.deb. Устанавливаем его
$ sudo dpkg -i ../libqscintilla2-3_2.3.2-0ubuntu2_i386.deb
и [пере]запускаем программы, которые используют данную библиотеку (например, JuffEd).
Вуаля! Автокомплит работает!
Если есть дополнения или замечания — добро пожаловать в комментарии.
Для самых ленивых — уже собранный и пропатченный пакет для Ubuntu 9.04 (i386)
UPD1: прошу прощения, залил не тот пакет. Если скачали deb, установили и ничего по-прежнему не работает — скачайте ещё раз:
$ md5sum libqscintilla2-3_2.3.2-patched-1ubuntu2_i386.deb
e5047bb52011d80b06e82fafe5063a73 libqscintilla2-3_2.3.2-patched-1ubuntu2_i386.deb
UPD2: пропатченый пакет для Ubuntu 9.10 (i386)