27 февр. 2009 г.

Autotools с нуля

На этот раз, я постараюсь объяснить, возможно, знакомую всем по предыдущим постам тему об использовании Autotools. Мне пришлось этот путь пройти заново, и немного по-другому, для того, чтобы мой проект выглядел так, как того требуют Gnome Games. Так получилось, что я написал им письмо о том, что у меня есть игра Gnome Quod (для Ubuntu вы сможете использовать мой автоматический репозиторий на PPA), и я бы хотел привести её к виду, соответствующему Gnome Games. Автор сборника игр, выделил мне ряд требований, решив которые, я смогу попробовать заново попросить его о включении моей игры в их пакет. Ну да ладно, это будет не скоро, и я сомневаюсь в этом, но давайте приступим к подготовке нового пакета, прежней игры.

Здесь я буду описывать конкретные вещи, что я делал, и по-возможности, что получал. Для подробной информации по тому или иному макросу, советую вам поискать в мануалах.

Для начала создадим папку с названием gnome-quod. Так будет называться мой каталог, где будут находиться все исходники, весь пакет, откуда потом, мы будем создавать пакеты. Затем, создаём файл-шаблон configure.ac. Его будет просматривать скрипт Autotools с названием autoreconf. Этот скрипт занимает одно из главных положений, в нашем проекте. Первоначальное содержание configure.ac будет следующим (комментарии только для осмысления.):

# ======================== initialization ===============================
Здесь будет описываться инициализация проекта: имя, начальный каталог и пр.

# ==================== basic compiler settings ==========================
Основные опции компилятора (например, используемый язык)

# ==================== checks for libraries =============================
Проверка существования библиотек

# ==================== checks for header files ==========================
Проверка существования заголовочных файлов (если нужно)

# ===== checks for typedefs, structures and compiler characteristics ====
Проверка типов, структур, особенностей компилятора

# ==================== checks for library functions =====================
Проверка функций библиотек. Полезно, когда версия библиотеки мало ли соответствует требуемой, но в ней нет функции, или, например, вы не уточняете версию библиотеки, и потому в случае отсутствия функции, можете реализовать её сами.

# ==================== generate files ===================================
Здесь создаются файлы, которые потом используются make'ом

AC_OUTPUT -- эта строка даёт всему начало

Порядок, который я описал, важен, но не существенно. Но главное не путать конец с началом. А вообще лучше придерживаться этого шаблона. Я встречал его во многих исходных файлах. Так что, будет у вас как у всех , если конечно, вам это не мешает. Теперь давайте добавим, в отдельные группы следующие макросы. Они должны описывать наш проект так, чтобы он работал.

# ======================== initialization ===============================
AC_INIT([Gnome Quod],
        [0.4.0],
        [vest@mail.com],
        [gnome-quod]) -- длинное имя, версия пакета, адрес куда стоит писать bug-репорты, краткое имя пакета

AC_CONFIG_SRCDIR([src/main.c]) -- проверка безопасности, что по этому адресу находится заведомо известный исходный файл
AC_CONFIG_HEADERS([config.h]) -- здесь создаётся заголовочный конфигурационный файл, который может быть использован в исходных файлах (в частности, там определена директива NDEBUG, см. ниже)
AM_INIT_AUTOMAKE([-Wall -Werror dist-bzip2]) -- включаем компилятору все предостережения и ошибки, чтобы подробно видеть всё на экране, о процессе компилции, дистрибутив распространяется в виде упакованного файла bz2
AC_DEFINE([NDEBUG], [], [Disable debugging information]) -- эта строка нужна лично мне, так как я использую assert функции, и если что, мне их нужно отключать

# ==================== basic compiler settings ==========================
AC_PROG_CC -- используем только Си компилятор
AM_PROG_CC_C_O -- нужно использовать вместо AC_PROG_CC_C_O, позволяет использовать флаги для каждой цели в Makefile
AC_HEADER_STDC -- проверка стандартных заголовочных файлов "stdlib.h", "stdarg.h", "string.h", "float.h". Это уже не нужно, так как они всегда есть, можно не проверять.

# ==================== generate files ===================================
AC_CONFIG_FILES([
  Makefile
  src/Makefile
]) -- происходит вызов AC_OUTPUT для каждого файла.
AC_OUTPUT -- создаёт много файлов, которые нам нужны

Далее создаём файлы-шаблоны Makefile.am и src/Makefile.am:

# Makefile.am
SUBDIRS = src

# src/Makefile.am
bin_PROGRAMS = quod
quod_SOURCES = main.c

Конечно же нам нужно создать main.c, с неким Hello World'ом.

#include <config.h>
#include <stdio.h>

int main(int argc, char** argv)
{
    printf("Hello World!\n");

    return 0;
}

Вот собственно и всё, на данный момент, далее выполняем следующие команды:

~/gnome-quod$ autoreconf --install
/usr/share/aclocal/lf_x11.m4:33: warning: underquoted definition of LF_PATH_XLIB
/usr/share/aclocal/lf_x11.m4:33: run info '(automake)Extending aclocal'
/usr/share/aclocal/lf_x11.m4:33: or see http://sources.redhat.com/automake/automake.html#Extending-aclocal
configure.ac:14: installing `./compile'
configure.ac:9: installing `./install-sh'
configure.ac:9: installing `./missing'
src/Makefile.am: installing `./depcomp'
Makefile.am: installing `./INSTALL'
Makefile.am: required file `./NEWS' not found
Makefile.am: required file `./README' not found
Makefile.am: required file `./AUTHORS' not found
Makefile.am: required file `./ChangeLog' not found
Makefile.am: installing `./COPYING'
autoreconf: automake failed with exit status: 1

Как вы видите, получили ошибки. Связаны они с тем, что наш проект полностью соответствует GNU стандарту, согласно configure.ac, но на деле таковым не является. Требуется создать самому следующие файлы, и желательно заполнить их. Вы можете посмотреть пример заполнения в любом серьёзном проекте, либо обратившись к Learning the GNU development tools. Создадим их и попробуем ещё раз (я ещё создал файл THANKS, название говорит само за себя):

$ ls
AUTHORS ChangeLog configure.ac Makefile.am NEWS README THANKS src

$ autoreconf --install
/usr/share/aclocal/lf_x11.m4:33: warning: underquoted definition of LF_PATH_XLIB
/usr/share/aclocal/lf_x11.m4:33: run info '(automake)Extending aclocal'
/usr/share/aclocal/lf_x11.m4:33: or see http://sources.redhat.com/automake/automake.html#Extending-aclocal
configure.ac:14: installing `./compile'
configure.ac:9: installing `./install-sh'
configure.ac:9: installing `./missing'
src/Makefile.am: installing `./depcomp'
Makefile.am: installing `./INSTALL'
Makefile.am: installing `./COPYING'

Каждый раз, когда меняется один из шаблонов, следует вызывать autoreconf без параметров. Иногда вы встретите в пакетах файл autogen.sh, по идеи он похож с предыдущим. Не вдаваясь в подробности этапов конфигурирования, здесь осуществляется поочерёдный вызов некоторых скриптов, входящих в состав Autotools.

Можно избежать проблем с тем, что не существует файлов, для этого стоит "сказать", что мы не соответствуем стандарту, для этого следует изменить макрос AM_INIT_AUTOMAKE следующим образом:

...
AM_INIT_AUTOMAKE([-Wall -Werror dist-bzip2 foreign])
...

Теперь поочерёдно выполним следующие команды, и взглянем на результат:

$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
....
checking for ANSI C header files... yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing depfiles commands

$ make
make all-recursive
make[1]: Вход в каталог `/home/vest/gnome-quod'
Making all in src
make[2]: Вход в каталог `/home/vest/gnome-quod/src'
gcc -DHAVE_CONFIG_H -I. -I.. -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
mv -f .deps/main.Tpo .deps/main.Po
gcc -g -O2 -o quod main.o
make[2]: Выход из каталога `/home/vest/gnome-quod/src'
make[2]: Вход в каталог `/home/vest/gnome-quod'
make[2]: Выход из каталога `/home/vest/gnome-quod'
make[1]: Выход из каталога `/home/vest/gnome-quod'

$ src/quod
Hello World!

Здесь я решил не урезать вывод, чтобы вы могли заметить. Тут поэтапно проходит конфигурирование, компиляция программы и последующий её запуск. Если вам нужен распространяемый пакет, выполните следующую команду make dist, в текущем каталоге вы получите следующие два файла:

$ ls -l gnome-quod-*
-rw-r--r-- 1 vest vest 73173 2009-02-27 01:01 gnome-quod-0.4.0.tar.bz2
-rw-r--r-- 1 vest vest 87568 2009-02-27 01:01 gnome-quod-0.4.0.tar.gz

Итак, на сегодня это пока всё. Вся вышеперечисленная информация, чуть более чем подробно объясняется в этой презентации (http://www.lrde.epita.fr/~adl/autotools.html). Советую с ней ознакомиться.

25 янв. 2009 г.

Игра на КДЕ. День последний.

Вот собственно игра окончилась, можно сказать, по-честному, прошла она не очень, но в то же время всё-таки прошла.

Короче... я стёр KDE и поставил себе Чистый Gnome.

Как высказались мои друзья, после KDE я потерял всякую мораль, стал замкнутым и отчуждённым. Глупо, но такое ощущение, что KDE может повлиять на человека не в лучшую сторону... не в лучшую.

Вы спросите буду ли я играть на KDE вновь? — Быть может, быть может. Я не хочу обещать, может быть это будет традицией, неделя Gnome, неделя KDE. Но если честно, KDE меня нервирует.

Я сожалею о том, что играл на KDE...

23 янв. 2009 г.

Игра на КДЕ. День пятый.

Вот идёт ещё один день моего смелого пребывания в KDE. Что у меня изменилось за последнее время? Я начинаю привыкать к проблемам со звуком и постоянно вылетающими теперь Konqueror и Firefox. Вчера Firefox удивил меня тем, что когда я заходил на какой-то из сайтов он тихо закрылся. Причем эту ошибку отследить было нельзя, потому я запустил его в консольном режиме, и вот что я получил:

$ firefox
QPixmap: Invalid pixmap parameters

(firefox:10500): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed <-- многократное появление таких строчек

The program 'firefox' received an X Window System error.
This probably reflects a bug in the program.
The error was 'RenderBadPicture (invalid Picture parameter)'.
(Details: serial 3472708 error_code 169 request_code 155 minor_code 7)
(Note to programmers: normally, X errors are reported asynchronously;
that is, you will receive the error a while after causing it.
To debug your program, run it with the --sync command line
option to change this behavior. You can then get a meaningful
backtrace from your debugger if you break on the gdk_x_error() function.)
Locking assertion failure. Backtrace:
#0 /usr/lib/libxcb-xlib.so.0 [0xb80347c7]
#1 /usr/lib/libxcb-xlib.so.0(xcb_xlib_lock+0x2e) [0xb803496e]
#2 /usr/lib/libX11.so.6 [0xb6b2b619]
#3 /usr/lib/libXrender.so.1(XRenderFreePicture+0x41) [0xb6bdcf41]
#4 /usr/lib/libQtGui.so.4 [0xb41d86bf]
... многократное появление похожих строчек связанных с этой библиотекой]
#17 /usr/lib/libQtGui.so.4 [0xb41d2d5a]
#18 /lib/tls/i686/cmov/libc.so.6(exit+0x89) [0xb7dc2d69]
#19 /usr/lib/libgdk-x11-2.0.so.0 [0xb66e26b7]
Segmentation fault

Меня насторожила строка, сразу же после выполнения команды. Похоже имеется какая-то проблема с QPixmap. И это мне не понравилось. Потому я решил обновиться на KDE 4.2-rc-1. Воспользовавшись ссылкой, так "заботливо" предоставленной моими друзьями, которые они аргументировали следующим образом:

Один: http://www.kubuntu.org/news/kde-4.2-rc1
Вест
сделайте этот смертельный номер
один хрен потом вам кеды сносить, а то и всю ось переставлять :)
Другой: Да, поставьте бету, ведь вам уже всё равно :)

Заодно и помогли ссылкой. Аргументы были весомые, я не мог ничего сказать плохого в сторону KDE и решил обновиться. Скачивать пришлось около 250 мб пакетов, что собственно я и сделал.

Надо добавить, что обновление может не пройти с первого раза, по разным причинам, возможно надо было делать это при закрытом KDE. Но обновиться можно, нужно быть настойчивее. Одна из причин может быть такой:

E: /var/cache/apt/archives/kdebase-workspace-data_4%3a4.1.96-0ubuntu4~intrepid1~ppa1_all.deb: попытка перезаписать /usr/share/doc/kde4/HTML/en/kcontrol/windowspecific/index.cache.bz2, который уже имеется в пакете kde-window-manager

Итак, обновление прошло почти с первого раза... После гламурного, красивого и приятного глазу моего KDE 4.1.4 я получил почти не изменившееся окно:

Что сразу хочется отметить: изменилось меню в красивую сторону, иконки раньше имеющие баг на протяжении года жизни KDE в System Tray'e, связаный с некорректным отображением прозрачности в виде чёрного квадрата вокруг них, сейчас исправились. Почему-то пришла идея, что на чёрном чёрный квадрат не видно, и потому решили в Tray'е "вырезать" прямоугольник и закрасить его чёрным цветом, что по-моему сделано почти правильно. Ведь это же KDE! Меню тоже похорошело, приобрело красивую рамочку. Кстати сказать о плазмоидах. Теперь плазмоиды могут масштабировать так, как нормальные окна, то есть один из углов становится фиксированным, а другой перемещается за мышью (раньше это было от центра плазмоида, и он постоянно уходил за пределы экрана). Ещё хочется добавить то, что при масштабировании не происходит увеличения или уменьшения иконок, то есть всё вроде бы даже хорошо и KDE могло бы заполучить ещё одного пользователя, но... Как вы видите, справа внизу я оставил ошибку, связанную с Phonon'ом. Но у меня звук продолжал работать, Amarok играл, как? Не знаю, наверное через PulseAudio.

Удивительная вещь №5 заключается в том, что можно вытянуть уведомление, что я и сделал, но после чего остался маленький квадратик, тоже плазмоид. Промастабировав его и развернув, видно, что antialiasing по-прежнему не работает. Причём на некоторые рамки распространяется, но на шрифты нет. Вообще-то, вращение плазмоидов является основной фишкой KDE4, так как до этого я нигде похожего не видел. Зачем это нужно? Я пока не решил, наверняка это требует ресурсов (раз уж это у меня даже на выключенных эффектах подтормаживает). Зато представьте, у вас немного перекошен стол, на котором стоит монитор и "о чудо!", вы можете внести поправку на все плазмоиды, которые есть на рабочем столе. Вращение окон пока остаётся за гранью мыслемого... Подождём.

Ах да! Я вспомнил, опять же вчера, то есть на четвёртый день, меня поразило то, что безопасность KDE может быть под угрозой. Не верите? Итак, Удивительная вещь №6. Включив однажды компьютер, залогинившисть в KDE, мне предстало следующее окошко:

Не знаю как вы, но я испугался, хорошо, что у меня есть KDE и оно мена предупредило, что моя мышка может быть захвачена. Теперь моя безопасность уже выросла. Кстати сказать, Konqueror не стал стабильней и по-прежнему аварийно завершался... и не он один, другие, неизвестные мне приложения, закрывались тоже. Вот, например, что происходит при завершении System Tray'a (GTK приложения остаются обделёнными, в то время как QT'шные нет. KDE - единоличник!):

Но и эта вещь легко исправляется, достаточно закрыть эти окошки, как они тут же радостные, что я их освободил от оконного плена, возвращаются назад к себе в tray. Но радость Gajim'a была больше чем у Pidgin'a. Он показал мне уведомление о том, что пришло новое сообщение (конвертик), но на радостях забыл, что при этом "человечек" должен скрыться. То есть теперь это человечек с конвертиком в руках (кстати были случаи, когда конвертик был прикреплён к незадачливому почтальону сзади, как у Карлсона):

Запустив так привычный мне inkscape (мне нужно было подрисовать один градиент в SVG-файле) я получил Удивительную вещь №7. В чём она заключается? Это в том, что настройка градиента не работает так, как мне того надо. Там, где вы не видите шкалу цветов учтите, что она на самом деле есть!

В довершении хочется привести фразу одного из моих друзей, конечно же за вычетом идиоматических выражений: "оно кривое, с ****ным юзабилити и для него фактически нет родных приложений на куте4, а те вменяемые, что есть на куте4, работают и без кде4 на ура и вообще никак к нему не относятся"

21 янв. 2009 г.

Игра на КДЕ. День третий.

Вот и наступил третий день моего пребывания в KDE 4.1.4. Что я могу сказать? В битве с KDE чувство победы плавно переходило от меня к KDE, и от KDE ко мне: как только я зашёл в этот DE, первым делом я обнаружил пропажу звука в музыкальных приложениях, так заботливо запущенного день назад. О звуке я расскажу попозже. Для начала мне стоит сказать, что как только я открыл konqueror на страничке моего блога, мне не понравился цвет шрифта вкладок, который я захотел изменить. Конечно же я полез в systemsettings (теперь уже локализованный в "Параметры Системы"). "Завоеватель" этого перепугался и выдал мне последовательных два окна:

Ну ничего, эта проблема всего-навсего с konquer'ом у меня бывала всего два раза за два дня, так, что я думаю это не страшно. Теперь вернёмся к звуку. Основная проблема была в том, что у меня пропало воспроизведение музыкальных файлов. В моём Gnome для воспроизведения использовался backend Xine, в то время как здесь его не было. Чтобы голову себе не забивать, признаюсь откровенно, я установил метапакет kubuntu-desktop. Что это даёт? Собственно там прилагаются всевозможные попытке по тому, чтобы всё работало. В частности звук. Проблема вроде решилась, но остаются некоторые нюансы. Могу сказать, что звук работает теперь. Но для этого приходится сперва закрыть все приложения его использующие (в том числе и GTK+), потом на всякий случай перегрузить alsa-utils и pulseaudio. Собственно после этих преобразований, у меня получилось всё перенаправить через PulseAudio. Запустив pavucontrol, вы можете это проверить:

Если вы заметили, здесь видно, что сейчас воспроизводится Skype, Amarok, Gajim (paplay). То есть, я позволяю себе использование Звукового Сервера PulseAudio, который разрешает мне одновременное использование звуковой карточки приложениями разных типов.

Теперь, Удивительная вещь №4. Даже после установки метапакета kubuntu-desktop у меня с предыдущего сайта про PulseAudio произошла загрузка вот такого SVG-файла. Да-да, именно, почему-то KDE пока не умеет отображать SVG-файлы ни в konqueror'e, ни в firefox'e:

Хорошо, хоть есть inkscape, он помог мне исправить ситуацию. Я качал картинку и открыл её руками. А также, немного погуглив, обнаружил интересный проект KSVG. Очень интересно, но к сожалению мне не хочется его компилировать, так как в репозиториях его нет. Равно как и версии для KDE4 пока тоже видимо нет. А ещё хочу снова сказать, что konqueror у меня опять закрылся. Видимо он не выдерживает более 4-ёх вкладок при открытии 5-ой Google. Ниже приводится правильный оригинал верхнего изображения:

Напоследок покажу вам текущий рабочий стол, который я решил допилить себе именно так, чтобы мне стало удобно. Но, хочу сказать... Удивительная вещь №5: те, кто столкнётся с установкой тем под KDE4 обнаружат "приятную" новость, оказывается, так просто скачать и поставить тему или plasmoid под DE не так уж и просто. "Почему?" - спросите вы. Потому что, их так просто не установить. Здесь я нашёл одну статью, которая "обещает" быструю установку тем под Plasma, а вот здесь "чуть медленнее". По итогам проделанной работы я поломал внешний вид KDE полностью, и посетовал, что не существует более простого способа установки тем как в Gnome из tar архивов. Но зато, я нашёл у KDE встроенный менеджер по управлению внешним видом, виджетами и прочим. Назвать его точно не могу, одно из предположений это superkaramba, он позволяет скачивать апплеты с KDE-look.org, но почему-то количество доступных в этом приложении апплетов, несравнимо меньше чем имеется оных на сайте. Решение проблемы снова просто - нужно либо скомпилировать всё, что вам понравится, либо попробовать поискать скомпилированный кем-нибудь пакет. Я, к сожалению ничего подходящего не нашёл, возможно вам повезёт больше, так как я решил не тратить на это время свыше 10 минут. Потому смотрите на то, что у меня получилось хотя бы так:

Комментарий по этой картинке было тоже много, как и по первой, которая, по мнению "неназвавшихся" порочит славное имя KDE. Однако здесь было недовольство по поводу синеватости рабочего стола. Ну что ж, пусть, мне так удобно, благодаря таким нежным цветам и яркостью моего монитора, я постарался снизить риск развития заболевания "Красноглазия", которое могу в скором будущем подхватить, если конечно не потру KDE раньше. Хотя с музыкой и Firefox'ом KDE не так страшно (konqueror меня разочаровал своими аварийными завершениями и постоянным беспокойством о том, что я отправляю гнусные скриншоты в этот блог, волнуясь либо за мою, либо за его безопасность).

Но всё равно, несмотря на всяческие ухищрения оно всё ещё имеет популярность у пользователей

19 янв. 2009 г.

Игра на КДЕ. Предисловие

Это и последующие сообщения появились в результате одного или нескольких событий. Да, к сожалению, я хотел описывать в своём блоге только то, что может быть полезно людям, столкнувшимся с Ubuntu, программированием, то есть всем тем, что связано с компьютером.
В один, прекрасный день, один из друзей по переписке отыскал в интернете флеш-игру под названием Globulos. Рассказывать про эту игру можно долго, но это не являлось темой текущего сообщения. Единственное, что можно выделить, что при соответствующей небольшой тренировке вполне можно устраивать соревнования. Главное, чтобы была причина...

... И вот причина появилась. Моими друзьями в количестве 2 "штук" (дабы их не деанонимизировать, не буду приводить их имена и ники), была разработана и предложена, а потом принята причина игры на "что-то". И как вы поняли из темы поста, это что-то было — установка проигравшим менеджера рабочего стола KDE 4, по возможности, последней версией (на время написания статьи, у меня в локальном репозитарии Бунты была версия 4.1.4).

Игра была напряжённой, сперва побеждал я со счётом 2:1. Кстати сказать, по комментариям моих друзей и по статистике, у меня были неплохие шансы на победу, всем казалось, что у меня есть транспортир. Так как игра шла до 3 очков, мне достаточно было забить один гол, но...

... но судьба-злодейка не позволила мне забить этот мячик ни разу, и потому, методично проигрывая, сперва 2:2, потом 3:2, я, можно сказать, стал счастливым обладателем пакета kde, а потом уже и kdebase. Первый пакет это установка базового KDE, а второй — его основных приложений (ведь это было бы не по правилам уговора, поставить KDE и продолжать пользоваться Nautilus'ом).

Если учесть то, что я никогда в жизни не сидел и не ставил KDE с нуля, мне пришлось это сделать. Ставятся пакеты относительно быстро, если локальный репозиторий, и занимают где-то 700-800 мб свободного пространства. Первое, что бросается в глаза, это интерфейс чем-то сравнимый с Windows Vista. Вы уведите его чёрные рамочки до тех пор, пока я не найду как это всё можно сменить. На рисунке ниже, вы видите "коробочный" интерфейс, где одновременно помещены разные приложения, без предварительной настройки их внешнего вида:

Знакомство с КДЕ

Вообще, внешний вид, это всего лишь мелочь, подумал я, как оказалось не совсем, мало того, что мои Gnome-приложения, потеряли свой первоначальный вид, так оказалось, что KDE со своим декоратором тормозит у меня так сильно, что я начал жалеть об этой игре вообще.

Пока я решал проблемы с увеличением производительности моей, я столкнулся с Удивительными вещами. Они могут быть неудивительны для вас, но я, ни разу не видевший KDE больше 10 минут, после использования Gnome в течении полутора лет, начал удивляться.

Итак Удивительная вещь №1: в Gnome, когда происходит выбор темы или цветов рабочего окружения, окна изменяют свой окрас мгновенно. В KDE для этого нужно смотреть в маленький прямоугольник наверху, что на мой взгляд очень неудобно. Ведь, получается, что мне нужно вообразить как будет выглядеть моё окно, после применения параметров. Конечно, можно сохранить промежуточный профиль с цветами, чтобы попробовать подбирать дальше, но это решение не для меня.

Вот и цвета

Удивительная вещь №2 заключается в том, что оказывается чтобы применить сглаживание к шрифтам (а я скажу вам, что оно по-умолчанию ужасно) мне нужно перезапустить приложения, если только не само KDE. Ах да, ещё можно ввести дополнение к этой удивительной вещи. Взгляните, оказывается в KDE не хватает места для сообщений в маленьких диалоговых окнах. Поэтому там существует полоса прокрутки. Жаль, конечно, что создатели не предусмотрели этого и не вставили перевод строки (ведь Gnome сам переносит и всё умещает. Такая вот у них политика):

Удивительная вещь №3: KDE поражает своими настройками графического интерфейса (это первое, с чем я столкнулся). Вы можете менять тут ВСЁ, вплоть до бесполезных, на мой взгляд, вещей. Можно взять красивую тему, и испортить её настройками KDE, либо взять плохую тему, и настройки KDE, думаю, вам не помогут. Можно убирать кнопки управления экраном, можно их добавить, удалить, переместить, можно изменить даже толщину бордюра окон, причем безо всяких мыслимых ограничений. Такое ощущение, что скрипту, где содержится команда 'rm -rf /' дали права root'а:

Напоследок, мне понравилось не только то, что Wine после завершения полноэкранного OpenGl приложения "упорядочил" мне окна:

но и то, что пока я писал эту статью я получил вот это:

Я думаю, на сегодня пока всё. У меня на тот день, осталось много неразрешённых проблем, таких как отсутствие звука в системе (похоже это связано с использованием мной PulseAudio, отключение декораций, увеличение производительности всего, что тормозит). А ещё, мне хочется закончить эту статью мыслью: "Мне стыдно, что я поставил KDE". Но неделя ещё длинная, я успею исправить все эти проблемы.

Мне кажется, или мои глаза становятся красными...

16 нояб. 2008 г.

Создаём пакет для Ubuntu. Часть 6. Использование Autotools

Итак, небольшое вступление... После многочисленных поисков, был найден небольшой, первый, я бы сказал, шаг к тому, чтобы осознать как же все-таки создаются распространяемые дистрибутивы. Для меня, основной сложностью в усвоении этой методики - это была проблема в познании языка M4, равно как и сама концепция файла configure.in. Видите ли, чтобы создать пакет требуется всего немного: написать вручную файл configure.in, в каждом используемом каталоге создать свой файл Makefile.am, потом выполнить ряд скриптов, сконфигурировать пакет и, если все прошло удачно, собрать его командой make.

Возможно, в этом нет ничего сложного, но многие конфигурационные шаблоны отличаются друг от друга, и для меня оказалось сложным просмотреть некоторую идею языка m4. Ведь, условно, нужно описать пакет, проверить зависимости, указать цели назначения и т.д... Ниже, я опишу простой способ создания пакета, который можно собрать, скомпилировать и даже установить. Если честно, этот способ прост, но во всяком случае позволил мне сдвинуться с, почти, мертвой точки.

Продолжим. Для следующего метода вам понадобятся так называемые autotools или autotoolset. Найти их можно по этому адресу http://autotoolset.sourceforge.net/. Здесь пакет доступен в качестве либо исходных кодов, либо в виде rpm пакета. Я думаю вам не составит труда воспользоваться утилитой alien для преобразования rpm пакета в deb.

После того, как вы установите его, вам следует изменить некоторые скрипты с помощью текстового редактора. А именно, исправить первую строку, где встречается использование sh на bash:

Вместо
#!/bin/sh
...

Записать
#!/bin/bash
...

Если так не сделать, то возможна работа с ошибками таких скриптов, как acmkdir и gpl, генерирующих необходимые файлы и директории.

Далее, когда вы все сделали, и имеете систему подготовленной к использованию, давайте попробуем создать наш первый распространяемый пакет, который так и назовем Hello. Кстати сказать, если вам нужен первоисточник, где я почерпнул необходимую информацию, то советую вам ознакомится с документом Developing software with GNU раздел Hello world with acmkdir.

Перейдите в любой каталог, где бы вы хотели начать создание своего приложения. В моем примере, я решил использовать каталог /tmp и выполните в нем команду acmkdir hello. В качестве аргумента я указал название моего пакета hello. Далее, оно задаст вам ряд вопросов, касающихся разработчика, и, в итоге, вам нужно согласиться с тем, что вы ввели. Вы должны получить на экране следующее:

$ acmkdir hello
Ready to create a new distribution skeleton directory.
The current working directory is:
--> /tmp
If you make a mistake and need to abort, press ctrl-C.

Name of distribution: hello
Your full name: Vest
Your email address: just@ask.me

Do you want to proceed? (y/n) y
+ Mode is default
+ Making directory hello
+ Making src directory
+ Making doc directory
+ Making m4 directory
+ Making config directory
+ Making default text files
+ Making INSTALL file link
+ Running reconf
- aclocal.
/usr/share/aclocal/lf_x11.m4:33: warning: underquoted definition of LF_PATH_XLIB
/usr/share/aclocal/lf_x11.m4:33: run info '(automake)Extending aclocal'
/usr/share/aclocal/lf_x11.m4:33: or see http://sources.redhat.com/automake/automake.html#Extending-aclocal
- autoconf.
- autoheader.
autoheader: warning: missing template: CXX_HAS_BUGGY_FOR_LOOPS
autoheader: Use AC_DEFINE([CXX_HAS_BUGGY_FOR_LOOPS], [], [Description])
autoheader: warning: missing template: CXX_HAS_NO_BOOL
autoheader: warning: missing template: NDEBUG
autoheader: warning: missing template: YOUR_OS
- automake.
configure.ac:21: installing `config/config.guess'
configure.ac:21: installing `config/config.sub'
configure.ac:17: installing `config/install-sh'
configure.ac:17: installing `config/missing'
Makefile.am: installing `./INSTALL'
Makefile.am: installing `./COPYING'
configure.ac:16: required file `config.h.in' not found

Distribution directory is ready.
Please make sure to keep the files AUTHORS, NEWS, README, THANKS up to
date before cutting a distribution.

В 4-ой строке снизу (или 5-ой, если считать по символам /n :) ), видно, что в автоматически созданном файле configure.ac в строке 16 отсутствует шаблон config.h.in. Нам он, собственно не нужен, потому эту строку можно смело комментировать командой dnl, или совсем удалить её.

После каждого изменения файла configure.ac всегда следует выполнять скрипт reconf

$ ./reconf
- aclocal.
/usr/share/aclocal/lf_x11.m4:33: warning: underquoted definition of LF_PATH_XLIB
/usr/share/aclocal/lf_x11.m4:33: run info '(automake)Extending aclocal'
/usr/share/aclocal/lf_x11.m4:33: or see http://sources.redhat.com/automake/automake.html#Extending-aclocal
- autoconf.
- autoheader.
autoheader: error: AC_CONFIG_HEADERS not found in configure.ac
- automake.

Для того, чтобы пересобрать все зависящие от него скрипты. Потом можно выполнить сам скрипт ./configure и make. В результате этого должно пройти конфигурирование и компиляция/сборка несуществующих исходных кодов. Теперь давайте создадим некоторый файл в каталоге src, с которого будет выполняться запуск нашего "Привет Мира".

/tmp/hello$ gedit src/main.cxx
// Vest (c) 2008
// Hello World
// main.cxx

#include

int main()
{
std::cout << "Hello World!" << std::endl;
return 0;
}

А потом, подправим шаблон Makefile.am, который по-умолчанию пуст. Приведем некоторые возможные опции файла Makefile.am:

ПеременнаяОписание
bin_PROGRAMS = prog1 prog2 ...Список исполняемых файлов, которые будут скомпилированы с помощью 'make', и установлены с помощью 'make install' в каталог '/prefix/bin', где 'prefix', обычно, это '/usr/local'.
lib_LIBRARIES = libfoo1.a libfoo2.a ...Список всех библиотек, которые будут скомпилированы с помощью 'make', и установлены с помощью 'make install' в каталог '/prefix/lib'.
prog_SOURCES = foo1.c foo2.c ... header1.h header2.h ...Список всех файлов, которые образовывают исходный код программы, включая заголовочные файлы. Присутствие заголовочных файлов не подразумевает того, что они будут установлены в '/prefix/include', но означает то, что они будут добавлены в дистрибутив ('make dist'). Если вы хотите установки публичных заголовочных файлов, вы должны упомянуть их в 'include_HEADERS'. Automake генерирует абстрактные правила для файлов C, C++ и Fortran. Для других языков, Вы должны предоставлять свои собственные правила.
prog_LDADD = $(top_builddir)/dir1/libfoo.a -lbar1 -lbar2 ...Список библиотек, которые должны быть подлинкованы с вашим исходным кодом. Установленные библиотеки должны использоваться с флагами '-l'. Удаляемые библиотеки должны упоминаться с использованием абсолютных имён (пример указан в предыдущем столбце).
prog_LDFLAGS = -L/dir1 -L/dir2 -L/dir3 ...Добавляет флаги '-L', которые нужны для поиска установленных библиотек, которые вы хотите подлинковать в 'prog_LDADD'.

Файл Makefile.am будет иметь вид:

/tmp/hello$ gedit src/Makefile.am
# Copyright (C) 2008 Vest <ваш@почтовый.ящик>
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

bin_PROGRAMS = hello
hello_SOURCES = main.cxx

Теперь пакет можно реконфигурировать, и собирать (далее я приведу только последнюю, нужную информацию о том, что компиляция прошла успешно)

$ ./reconf
$ ./configure
$ make
...
Making all in src
make[1]: Вход в каталог `/tmp/hello/src'
g++ -DPACKAGE_NAME=\"hello\" -DPACKAGE_TARNAME=\"hello\" -DPACKAGE_VERSION=\"0.0.1\" -DPACKAGE_STRING=\"hello\ 0.0.1\" -DPACKAGE_BUGREPORT=\"Vest\ just@ask.me\" -DPACKAGE=\"hello\" -DVERSION=\"0.0.1\" -DCXX_HAS_BUGGY_FOR_LOOPS=1 -DYOUR_OS=\"i686-pc-linux-gnu\" -I. -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.cxx
mv -f .deps/main.Tpo .deps/main.Po
g++ -g -O2 -o hello main.o
make[1]: Выход из каталога `/tmp/hello/src'
...
$ make distcheck
...
=============================================
hello-0.0.1 archives ready for distribution:
hello-0.0.1.tar.gz
hello-0.0.1.tar.bz2
=============================================

Как вы видите, было создано два архива. Внутри каждого из них лежат наши исходные файлы, доступные для распространения. Кстати сказать, внутри архивов наша программа будет лежать в каталоге 'hello-0.0.1'. Это пригодится нам при создании распространяемого пакета скомпилированного приложения. Проверить то, что наше приложение установится и запустится в системе можно следующим образом:

$ sudo make install
...
$ hello
Hello World!
$ whereis hello
hello: /usr/local/bin/hello
$ sudo make uninstall
...
$ hello
bash: /usr/local/bin/hello: No such file or directory

Вот собственно и все. В дальнейшем, я постараюсь описать более сложный пример, равно как и понять, почему после удаления приложения, присутствовала неизвестная ссылка, при повторном его запуске :) Похоже, что она где-то успела прописаться в системе или профиле пользователя.

20 авг. 2008 г.

Создаём пакет для Ubuntu. Часть 5a. Пример из helloworld.

Как вы, возможно, видели, некоторых каталогов, описанных в предыдущем разделе у вас в Ubuntu не существует. Это связано с тем, что структура файловой системы различается от дистрибутива к дистрибутиву, сохраняя, конечно, определённую концепцию описанную в Filesystem Hierarchy Standard.

На сайте FTP консорциума GNU лежит программа Hello world основное назначение её в том, чтобы просто посмотреть продукт полностью удовлетворяющий GNU стандарту. Но мы его попробуем использовать для того, чтобы просто узнать значения некоторых переменных.

Скачайте и распакуйте эту программу куда-нибудь в /tmp. Для того, чтобы нам не жалко было её стереть. Зайдите туда из-под консоли и выполните команду:

$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
configure: creating ./config.status
config.status: creating Makefile -- вот это нам понадобится
...

Eсли у вас возникнет ошибка, что не возможно создать "executable file", поставьте из репозитария пакет build-essential.

Итак, вы возможно обратили внимание на то, что вместо отсутствующего Makefile скрипт configure создал нам новый. Если вы его просмотрите то увидите следующее (нам отсюда нужна только верхняя часть:

$ cat Makefile
... (тут лежат комментарии)
SHELL = /bin/bash

srcdir = .
top_srcdir = .

prefix = /usr/local
exec_prefix = ${prefix}
... (а здесь остальной автоматически сгенерированный код)

Как вы видите префикс равен 'prefix = /usr/local'. В документе Filesystem Hierarchy Standard об этом сказано, что (4.8.2.1): "Иерархия /usr/local используется системным администратором при локальной установки программного обеспечения. Она не должна перезаписываться при обновлении системного программного обеспечения. Она может быть использована для программ и данных, которые совместно используются среди групп хостов, но которые не найдены в /usr. Локально установленное ПО должно быть помещено, предпочтительнее, в /usr/local, чем в /usr, если конечно оно не было установлено для замены или обновления ПО в /usr."

Так как я на своей памяти не встречал пакеты, которые записывались бы в /usr/local (тем более мы с вами будем делать наш собственный пакет, который в дальнейшем будет обновляться). Для этого выполним конфигурационный скрипт следующим образом, и просмотрим наш Makefile:

$ ./configure --prefix=/usr
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
...
$ cat Makefile
... (тут лежат комментарии)
SHELL = /bin/bash

srcdir = .
top_srcdir = .

prefix = /usr
exec_prefix = ${prefix}

bindir = ${exec_prefix}/bin
sbindir = ${exec_prefix}/sbin
libexecdir = ${exec_prefix}/libexec
datadir = ${prefix}/share
sysconfdir = ${prefix}/etc
sharedstatedir = ${prefix}/com
localstatedir = ${prefix}/var
libdir = ${exec_prefix}/lib
infodir = ${prefix}/info
mandir = ${prefix}/man
includedir = ${prefix}/include
oldincludedir = /usr/include
pkgdatadir = $(datadir)/hello
pkglibdir = $(libdir)/hello
pkgincludedir = $(includedir)/hello
top_builddir = .
... (а здесь остальной автоматически сгенерированный код)

Теперь уже всё можно свести в таблицу, чтобы было проще воспринять:


ПеременнаяПутьОписание
srcdir.Исходные коды
top_srcdir.Родительский каталог с исходными кодами (во вложенных директориях его значение равно '..'
prefix/usrКаталог, содержащий данные, совместно используемые несколькими машинами. Любая информация, меняющаяся со временем должна располагаться в другом каталоге
bindir/usr/binПервичная директория для исполняемых файлов
sbindir/usr/sbinДиректория содержащая незначительные файлы, обычно используемые системным администратором: восстановление системы, монтирование /usr раздела и т.д.
libexecdir/usr/libexecДиректория для установки исполняемых программ, которые чаще запускаются другими программами, чем пользователями
datadir/usr/shareИерархия для всех архитектурно-независимых данных, используемых совместно различными хостами
sysconfdir/usr/etcКаталог с файлами для конфигурирования хоста. Предпочтительно использование /etc
sharedstatedir/usr/comДиректория для установки файлов с архитектурно независимыми данными, которые могут быть изменены программой
localstatedir/usr/varДиректория для установки файлов с данными, которые могут быть изменены программами в процессе работы, и которые принадлежат одной конкретной машине
libdir/usr/libСодержит объектные файлы, библиотеки, внутренние бинарные файлы. Подразумевается, что они не используются напрямую пользователем или скриптами шелл
infodir/usr/infoДиректория для установки Info-файлов для этого пакета
mandir/usr/manКаталог верхнего уровня для установки страниц man для текущего пакета
includedir
oldincludedir
/usr/includeСюда помещаются все заголовочные файлы языка C
pkgdatadir/usr/share/helloЗдесь хранятся данные приложения hello. Например, Glade формы
pkglibdir/usr/lib/helloЗдесь хранятся данные библиотеки hello. Например, вспомогательные библиотеки
pkgincludedir/usr/include/helloЗдесь хранятся заголовочные файлы библиотеки hello

Здесь ещё можно добавить следующее, в каталоге /usr/include/pixmaps лежат различные картинки, используемые программой в процессе её жизнедеятельности. Про другие каталоги, такие как /usr/include/doc я ничего верно сказать не могу, так как не видел обобщённой информации по этому поводу. Скорее всего структура файловой системы основана на FHS, а потом идёт собственно набивка различными пакетами.

6 авг. 2008 г.

Создаём пакет для Ubuntu. Часть 5. Переменные директорий для установки

Директории для установки должны всегда именоваться с помощью переменных, для того чтобы облегчить установку программы в нестандартное место. Стандартные имена этих переменных описаны ниже. Они основаны на стандартном расположении файловой системы; эти варианты используются в SVR4, 4.4BSD, Linux, Ultrix v4 и других современных операционных системах.

Эти две переменные устанавливаются суперпользователем для установки. Все другие инсталляционные директории должны быть подкаталогами одного из этих двух и ничего не должно устанавливаться напрямую в эти два каталога.

'prefix'
Префикс используется в построении значений переменных указаных ниже по умолчанию. По умолчанию, 'prefix' должен быть равен '/usr/local'. Когда происходит сборка полной GNU системы, префикс должен быть пустым и '/usr' должна быть символической ссылкой в '/'. (Если вы используете Autoconf, записывайте его как '@prefix@'.)
'exec_prefix'
Префикс также используется в построении значений переменных указанных ниже по умолчанию. По умолчанию, 'exec_prefix' должен быть равен $(prefix). (Если вы используете Autoconf, записывайте его как '@exec_prefix@'.) Как правило, $(exec_prefix) используется для каталогов, которые содержат машинно-специфичные файлы (такие как исполняемые или библиотеки подпрограмм), в то время как $(prefix) напрямую используется для других директорий.

Исполняемые программы устанавливаются в одну из следующих директорий (обратите внимание, это важно для решения нашей с вами задачи):

'bindir'
Директория для установки исполняемых программ, которые пользователь может запускать. Обычно это '/usr/local/bin', но записывается как '$(exec_prefix)/bin'.
(Если вы используете Autoconf, записывайте его как '@bindir@'.)
'sbindir'
Директория для установки исполняемых программ, которые пользователь может запускать из шелла, они обычно полезны системным администраторам. Обычно это '/usr/local/sbin', но записывается как '$(exec_prefix)/sbin'.
(Если вы используете Autoconf, записывайте его как '@sbindir@'.)
'libexecdir'
Директория для установки исполняемых программ, которые чаще запускаются другими программами, чем пользователями. Обычно это '/usr/local/libexec', но записывается как '$(exec_prefix)/libexec'.
(Если вы используете Autoconf, записывайте его как '@libexecdir@'.)

Файлы с данными, используемые программами на протяжении своей работы подразделяются на категории по двум направлениям:

  • Файлы, которые обычно изменяются программами; другие никогда обычно не изменяются (хотя пользователи могут редактировать некоторые из них).
  • Архитектурно-независимые файлы и могут использоваться всеми машинами участка; некоторые архитектурно-зависимые и могут использоваться только машинами с таким же типом операционной системы; другие которые никогда не могут быть "расшарены" между двумя машинами.

Всё это создаёт 6 различных возможностей. Однако, мы хотим предостеречь вас от использования архитектурно-зависимых файлов, в отношении от объектных файлов и библиотек. Будет гораздо чище делать другие файлы с данными архитектурно-независимыми, и это, в общем, не так сложно.

Вот почему, здесь предлагаются переменные, которые должны использовать мейкфайлы для указания каталогов:

'datadir'
Директория для установки файлов с архитектурно независимыми данными, доступными только для чтения. Обычно это '/usr/local/share', но записывается как '$(prefix)/share'.В качестве особого исключения смотрите ниже'$(infodir)' и '$(includedir)'.
(Если вы используете Autoconf, записывайте его как '@datadir@'.)
'sysconfdir'
Директория для установки файлов с данными, имеющими отношение к одной машине, доступными только для чтения. В общем это файлы для конфигурирования хоста. Файлы конфигурации почтовой программы и сети, '/etc/passwd' и всё подобное этому. Все файлы в этой директории должны быть обычными текстовыми файлами с кодировкой ASCII. Обычно это '/usr/local/etc', но записывается как '$(prefix)/etc'.
(Если вы используете Autoconf, записывайте его как '@sysconfdir@'.)

Не устанавливайте исполняемые файлы в этот каталог (они возможно принадлежат '$(libexecdir)' или '$(sbindir)'). Также не устанавливайте файлы, которые могут изменяться в процессе работы (здесь исключаются программы предназначенные для изменения конфигурации системы). Они возможно пренадлежат '$(localstatedir)'.
'sharedstatedir'
Директория для установки файлов с архитектурно независимыми данными, которые могут быть изменены программой. Обычно это '/usr/local/com', но записывается как '$(prefix)/com'.
(Если вы используете Autoconf, записывайте его как '@sharedstatedir@'.)
'localstatedir'
Директория для установки файлов с данными, которые могут быть изменены программами в процессе работы, и которые принадлежат одной конкретной машине. Пользователи не должны никогда их изменять в этом каталоге, чтобы конфигурировать действия пакета; помещайте такую настраиваемую информацию в отдельные файлы, в '$(datadir)' или '$(sysconfdir)'. Обычно '$(localstatedir)' это '$(/usr/local/var)', но записывается как '$(prefix)/var'.
(Если вы используете Autoconf, записывайте его как '@localstatedir@'.)
'libdir'
Директория для объектных файлов и библиотек. Не устанавливайте исполняемые файлы сюда, они возможно должны лежать в '$(libexecdir)'. Обычно это '/usr/local/lib', но записывается как '$(exec_prefix)/lib'.
(Если вы используете Autoconf, записывайте его как '@libdir@'.)
'infodir'
Директория для установки Info-файлов для этого пакета. Обычно это '/usr/local/info', но записывается как '$(prefix)/info'.
(Если вы используете Autoconf, записывайте его как '@infodir@'.)
'lispdir'
Директория для установки любых Emacs Lisp-файлов для этого пакета. Обычно это '/usr/local/share/emacs/site-lisp', но записывается как '$(prefix)/share/emacs/site-lisp'.
(Если вы используете Autoconf, записывайте его как '@lispdir@'.) В добавок, чтобы '@lispdir@' работало, вам нужно добавить следующие файлы в ваш 'configure.in' файл:
lispdir='${datadir}/emacs/site-lisp'
AC_SUBST(lispdir)
'includedir'
Директория для установки заголовочных файлов, которые включаются в пользовательские программы с помощью директивы препроцессора C '#include'. Обычно это '/usr/local/include', но записывается как '$(prefix)/include'.
(Если вы используете Autoconf, записывайте его как '@includedir@'.)
Большинство компиляторов, отличных от GCC не просматирвают заголовочные файлы в '/usr/local/include'. Поэтому установка заголовочных файлов этим путём полезна только для GCC. Иногда, это не является проблемой, потому что некоторые библиотеки действительно предназначены работать с GCC, но некоторые могут работать с другими компиляторами. Они должны устанавилвать свои заголовочные файлы в два места: includedir и oldincludedir.
'oldincludedir'
Директория для установки заголовочных файлов, которые включаются в пользовательские программы с помощью директивы препроцессора C '#include'. Обычно это '/usr/include'.
(Если вы используете Autoconf, записывайте его как '@oldincludedir@'.)
Команды Makefile должны проверять пустое ли значение '@oldincludedir@'. Если да, то они не должны использовать его и прервать вторичную установку заголовочных файлов.
Пакет не должен заменять существующие заголовочные файлы в этой директории, если он не из этого пакета (установленного ранее). Таким образом, если ваш пакет (например, Foo) предоставляет файл 'foo.h', то он должен устанавливать заголовочный файл в каталог oldincludedir, если, первое, здесь нет 'foo.h' файла, или, второе, существующий файл принадлежит пакету Foo.
Для определения того, что файл 'foo.h' "пришёл" из пакета Foo, поместите "магическую строку" (просто, некоторую уникальную) в файл, как часть комментария, и выполните для неё grep.

man-страницы в стиле Unix устанавливаются в следующие каталоги:

'mandir'
Каталог верхнего уровня для установки страниц man (если имеется) для текущего пакета. Обычно это '/usr/local/man', но записывается как '$(prefix)/man'.
(Если вы используете Autoconf, записывайте его как '@mandir@'.)
'man1dir'
Каталог верхнего уровня для установки страниц man секции 1. Записывайте как '$(mandir)/man1'.
'man2dir'
Каталог верхнего уровня для установки страниц man секции 2. Записывайте как '$(mandir)/man2'.
'...'
Не делайте первичную документацию любого GNU программного обеспечения в качестве man страницы. Вместо этого, записывайте руководство (мануал) в Texinfo. Страницы man предназначены для людей, запускающих ПО под Unix.
'manext'
Расширение файла для установленной страницы man. Оно должно содержать точку и следующую за ней соответствующую цифру: '.1'.
'man1ext'
Расширение файла для установленных страниц man секции 1.
'man2ext'
Расширение файла для установленных страниц man секции 2.
'...'
Используйте эти имена вместо 'manext', если пакету требуется установить страницы man в более, чем одной секции мануала.

И, в конце, вы должны установить следующую переменную:

'srcdir'
Каталог исходных файлов, которые следует компилировать. Значение этой переменно обычно вставляется скриптом configure.
(Если вы используете Autoconf, используйте 'srcdir = @srcdir@'.)

Например:

# Общий префикс для директорий пути установки.
# NOTE: Эта директория должна существовать к моменту начала установки.
prefix = /usr/local
exec_prefix = $(prefix)
# Куда помещать исполняемые файлы для команды 'gcc'.
bindir = $(exec_prefix)/bin
# Куда помещать директории используемые компилятором.
libexecdir = $(exec_prefix)/libexec
# Куда помещать Info-файлы.
infodir = $(prefix)/info

Если ваша программа устанавливает большое число файлов в одну из стандартных пользовательских директорий, будет полезным разгруппировать их в подкаталог, относящийся к этой программе. Если вы поступаете так, то должны записать в правило install создание этих подкаталогов.

Не ожидайте, что пользователь включит название подкаталога в значение любой из перечисленных выше переменных. Идея наличия унифицированного набора имён переменных для директорий установки существует для того, чтобы пользователь указывал одинаковые значения для разных GNU пакетов. В общем, это полезно, чтобы пакеты были спроектированы способными работать разумно.

В довершении, я бы от себя добавил, что унификация во всём была важна, чтобы не было путаницы, чтобы всё работало слаженно и если вы знаете, что все (условно все) бинарники лежат в /usr/bin, вы всегда сможете их легко найти. Спасибо за внимание...

Создаём пакет для Ubuntu. Часть 4. Переменные для указанных команд

Мейкфайлы должны предоставлять переменные для переопределения определённых команд, опций и так далее. В частности, вы должны запускать большинство утилит через переменные. Так, например, если вы используете Bison, имеете переменную BISON, чьё значение по умолчанию устанавливается в 'BISON = bison', и вы должны ссылаться на неё с помощью $(BISON), когда используете.

Утилиты для управления файлами, такие как ln, rm, mv и так далее не нуждаются в ссылке через переменные, так как пользователи обычно не заменяют их другими программами.

Каждая переменная с именем программы должна сопровождаться переменной с опциями, которые используются с ней. Добавьте в конце 'FLAGS' к имени переменной, например, BISONFLAGS. Исключением является CFLAGS (из-за стандарта). Используйте CPPFLAGS в любой другой команде компиляции, использующей препроцессор, равно как LDFLAGS, которая используется в компоновщике (linker), например ld.

Если есть какие-нибудь опции, особенные для того или иного файла, не используйте их в CFLAGS, так как пользователи могут подумать, что её можно свободно менять. Старайтесь записывать эти опции непосредственно в само правило:

CFLAGS = -g
ALL_CFLAGS = -I. $(CFLAGS)
.c.o:
        $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<

Не включайте опцию '-g' в CFLAGS, потому что она не является необходимой для правильной компиляции (это ведь опция о включении отладочной информации). Если пакет настроен для сборки GCC по умолчанию, то вы можете включить опцию '-O' CFLAGS по умолчанию (правильно, почему бы не поставлять пакет готовым к оптимизации).

Помещайте опциию CFLAGS последней в команде компиляции, после других переменных, содержащих опции компилятора, так, чтобы пользователь мог использовать CFLAGS для перегрузки других опций (ну, например, отменить ту же самую оптимизацию, которая была добавлена ранее другой переменной).

Каждый Makefile должен определять переменную INSTALL, являющуюся базовой командой для установки файла в систему. Также каждый Makefile должен определять переменную INSTALL_PROGRAM и INSTALL_DATA (значение по умолчанию у них должно быть равно $(INSTALL)). Затем, он должен использовать эти переменные в качестве команд установки исполняемых и не исполняемых файлов отдельно. Используйте их следующим образом:

$(INSTALL_PROGRAM) foo $(bindir)/foo
$(INSTALL_DATA) libfoo.a $(libdir)/libfoo.a

Всегда используйте имя файла, а не название каталога, в качестве второго аргумента команды инсталляции. Используйте отдельную команду для каждого файла для установки.

5 авг. 2008 г.

Создаём пакет для Ubuntu. Часть 3. Утилиты в Makefile'ах

В своих мейкфайлах вы можете использовать всевозможные команды для выполнения тех или иных задач. Ниже приводится информация о том, какие именно утилиты и когда вам рекомендуется их использовать.

Записывайте комманды Makefile (и любые шелл скрипты, такие как configure), чтобы они работали в sh шелле, а не csh. Не используйте любые специальные возможности ksh или bash.

Скрипт configure, правила от мейкфайла, и команды установки не должны использовать утилиты за исключением следующих:

cat cmp cp diff echo egrep expr false grep install-info ln ls mkdir mv pwd rm rmdir sed sleep sort tar test touch true

Архиватор gzip может использоваться в правиле dist.

Привыкайте к использованию общих опций у этих программ. Например, не используйте 'mkdir -p', даже если это удобно, так как большинство систем этого не поддерживают. Также избегайте создания символических ссылок, по понятным причинам.

Правила мейкфайлов для сборки и установки также могут использовать компиляторы или похожие программы, но должны делать это через переменные make, которые пользователь может заменять на альтернативные. Вот несколько программ:

ar bison cc flex install ld ldconfig lex make makeinfo ranlib texi2dvi yacc

Используйте следующие переменные make для запуска этих программ:

$(AR) $(BISON) $(CC) $(FLEX) $(INSTALL) $(LD) $(LDCONFIG) $(LEX) $(MAKE) $(MAKEINFO) $(RANLIB) $(TEXI2DVI) $(YACC)

При использовании ranlib или ldconfig, убедитесь, что ничего плохого не случится если система не имеет программу, о которой идёт речь. Игнорируйте ошибку от этой комманды и выводите сообщение перед вызовом комманды, чтобы сообщить пользователю, что ошибка этой комманды не считается проблемной. (Макрос Autoconf'а 'AC_PROG_RANLIB' может помочь с этим.)

Если вы используете символические ссылки, вы должны реализовать альтернативный путь для систем, этого не имеющих.

Дополнительные утилиты, которые могут быть использованы через переменные Make следующие:

chgrp chmod chown mknod

Это нормально использовать другие утилиты в частях мейкфайла (или скриптах) предназначенных только для конкретных систем, где заведомо известно о существовании этих утилит

Создаём пакет для Ubuntu. Часть 2. Общие соглашения о Makefile'ах

Вы, я думаю, поняли основную идею configure файла. Здесь я постараюсь раскрыть структуру Makefile, воспользовавшись тем же документом что и раньше, GNU Coding Standards.

Вы, если увлекаетесь программированием, или компилируя чужие исходные коды, в процессе своей компьютерной жизнедеятельности должны были столкнуться с "мейкфайлами" (Makefile). В чем заключается их смысл? Их назначение состоит в том, чтобы автоматизировать процесс сборки вашего проекта. Как вы знаете простая программа может быть скомпилирована с помощью одной лишь строчки gcc main.cpp. На выходе вы получите файл a.out который потом можете запустить или переименовать.

А что делать, если ваш проект содержит несколько исходных файлов, и вы хотите имя отличное от стандартного? Можно конечно написать некий скрипт, который будет за вас вызывать, копировать и устанавливать ваши файлы. Вот таким стандартизованным методом и является Makefile, обычно располагающийся в корне вашего проекта.

Каждый Makefile должен содержать эту строку:

SHELL = /bin/sh

Для того, чтобы избежать проблем связанных с использованием переменной среды SHELL по умолчанию.

Различные make программы имеют несовместимые списки суффиксов и неявных правил, что порой создаёт некоторые неудобства и неправильное поведение. Поэтому будет неплохо, если вы укажите этот набор суффиксов явным образом, например:

.SUFFIXES:
.SUFFIXES: .c .o

Первая линия очищает существующий список суффиксов, вторая показывает все суффиксы, которые могут являться предметом для неявных правил (я счтиаю, что здесь разговор идёт в первую очередь о том, что множество промежуточных объектов, файлов и прочего оканчиваются по-разному: *.c, *.cpp, *.cc, *.o, *.obj Поэтому чтобы компилятор не путался мы ограничиваем этот список)

Не делайте предположения о том, что '.' является путём для вызова команды. Когда вам требуется запустить программы, являющиеся частью вашего пакета в процессе работы make, убедитесь, что она использует путь './' (если программа собирается как часть make), или '$(srcdir)/' (если файл - не изменяющаяся часть исходного кода). Без этих префиксов используется текущий путь поиска (ну то, есть по всем /usr/bin и прочим пробежится, а не там где надо).

Различие между './' (директория, где собирается программа) и '$(srcdir)/' (директория с иходными файлами) важно, так как пользователи могут собирать программу в отдельный каталог, используя '--srcdir' опцию configure скрипта. Следующее правило:

foo.1 : foo.man sedscript
        sed -e sedscript foo.man > foo.1

будет ошибочным если директория сборки будет отличаться от директории с исходными файлами, так как 'foo.man' и 'sedscript' располагаются в каталоге с исходниками (то есть видите что перед ними нет никаких приставок с абсолютными значениями пути?).

При использовании GNU make, полагаясь на то, что 'VPATH' укажет на исходный файл и компиляция будет работать, только в случае единичного файла. Для этого существует автоматическая переменная '$<', представляющая сам исходный файл (что-то вроде псевдонима). Много версий make устанавливают '$<' только в неявных правилах. Цель Makefile вида

foo.o : bar.c
        $(CC) -I. -I$(srcdir) $(CFLAGS) -c bar.c -o foo.o

должна быть переписана как

foo.o : bar.c
        $(CC) -I. -I$(srcdir) $(CFLAGS) -c $< -o $@

чтобы позволить переменной 'VPATH' корректно работать. Когда цель имеет несколько зависимостей, используйте явное '$(srcdir)/' в качестве легчайшего пути, чтобы ваше правило работало. Например, для цели выше 'foo.1' напишите следующее:

foo.1 : foo.man sedscript
        sed -e $(srcdir)/sedscript $(srcdir)/foo.man > $@

Дистрибутивы GNU обычно содержат некоторые файлы, которые не являются исходными файлами: info файлы, вывод из Autoconf, Automake, Bision или Flex. Эти файлы обычно появляются в директории с исходными файлами, и потому они должны всегда появляться там, а не в каталоге сборки. Поэтому правила Makfile обновляющие их должны класть их в исходный каталог.

Однако, если файл не появляется в дистрибутиве, то Makfile не должен помещать его в каталог с исходными файлами, потому что процесс сборки программы при обычных условиях не должен ни при каких обстоятельствах модифицировать исходный каталог (Мне это кажется правильным, иначе либо пришлось бы очищать все изменения перед повторной сборкой, либо всегда хранить копию исходнков. Запомните, ваши исходные файлы должны быть неизменимы, лучше деалйте копии и работайте с ними, чем с оригиналом).

Постарайтесь сделать цели сборки и установки, по меньшей мере (и все их подцели) так, чтобы они работали с параллельным make (скорее всего разговор идёт о том, чтобы ваши файлы не конфликтовали в случае параллельной компиляции и сборки).

3 авг. 2008 г.

Создаём пакет для Ubuntu. Часть 1. Что такое конфигурирование

Введение

Столкнувшись с темой программирования под ОС Linux, передо мной возник вопрос о публикации исходных файлов таким образом, чтобы из них можно было скомпилировать и создать пакет, в частности deb пакет для операционной системы Ubuntu.

Программирования под ОС Windows, мне как-то не приходилось сталкиваться с программами типа make, а потому знания в области создания Makefile'ов у меня пока ещё нет. На руках имеется всего лишь набор исходных файлов моего небольшого проекта Gnome Quod.

Поискав в интернете некоторую информацию об этом процессе, я наткнулся на статью GNU Coding Standards. Возможно вы подумаете: "Вот! Ещё один перевод". Хорошо, пусть так и будет, но это лучше чем ничего, тем более, я не собираюсь переводить всю статью, так как она очень большая, и не всё мне оттуда пригодится для решения поставленной задачи. Здесь я постараюсь по пунктам перевести и описать всё, что следует делать, чтобы ваши программы смогли в конце-концов быть "инсталлируемыми".

Процесс создания релиза

Создание релиза отличается от простого сжатия ваших исходных файлов в tar и размещение их на FTP. Вам следует настроить ваш софт таким образом, чтобы он мог быть сконфигурирован для различных систем. Ваш Makefile должен соответствовать GNU стандартам, описанным ниже, и расположение директорий также должно соответствовать стандартам. Сделав это, ваш пакет сможет быть легко встроен в большую инфраструктуру всего программного обеспечения GNU.

Как должно работать конфигурирование

Каждый дистрибутив GNU должен снабжаться скриптом configure. Этому скрипту предоставляются аргументы, каждый из которых описывает ту или иную машину, для которой вы хотите скомпилировать программу (вы наверное часто встречали файлы ./configure.sh, так вот разговор идёт о них).

Скрипт configure должен записывать конфигурационные опции так, чтобы они затрагивали процесс компиляции.

Один путь сделать это - это создать ссылку от стандартного имени, такого как config.h к нужному конфигурационному файлу, для выбранной системы. Если вы используете эту технику, то дистрибутив не должен содержать файла названного 'config.h'. Это сделано для того, чтобы не смогли создать программу без предварительного её конфигурирования.

Другой путь, который может быть выполнен с помощью configure это редактировать файл Makefile. То есть, он должен включать файл 'Makefile.in', который содержит входящий шаблон, используемый для редактирования, и не содержать Makefile. Снова, это сделано для того, чтобы люди не смогли создать программу без предварительного конфигурирования.

Если configure выполняет запись 'Makefile', то 'Makefile' должен иметь цель, которая называется 'Makefile'. Это заставит configure перезапуститься, установить ту же конфигурацию, которая была установлена в прошлый раз. Файлы, которые читает скрипт configure должны быть прописаны в качестве зависимостей 'Makefile'

Все файлы, которые получаются от скрипта configure должны иметь в начале комментарии, поясняющие то, что они были созданы автоматически с использованием скрипта. Это избавит пользователей от заблуждения и попытки редактирования этих файлов вручную.

Скрипт configure должен записывать файл с названием 'config.status', который описывает какие опции конфигурирования были указаны с последнего запуска скрипта. Этот файл должен быть скриптом shell, при запуске которого воссоздастся такая же конфигурация.

Скрипт configure должен принимать опцию вида '--srcdir=dirname' чтобы указать каталог, где находятся исходные файлы (если это не текущая директория). Это делает возможным сборку программы в отдельный каталог, поэтому текущая директория с исходными файлами не изменяется.

Если пользователь не указывает '--srcdir', то configure должен просмотреть оба каталога '.' и '..' в поисках исходных файлов. Если он находит исходники в одном из этих мест, то он должен использовать их отсюда, иначе - сообщить, что не может найти исходные файлы, и выйти с ненулевым статусом.

Обычно, легчайший путь для предоставления '--srcdir' - это редактировать директиву VPATH в Makefile. Некоторые правила могут нуждаться в явном указании исходной директории. Чтобы сделать это возможным, configure может добавить переменную с именем srcdir в Makefile, чьё значение точно указывает директорию.

Скрипт configure должен также принимать аргумент, указывающий тип ОС для которой собирается программа. Этот аргумент выглядет как cpu-company-system. Например, для Sun 3 - это 'm68k-sun-sunos4.1'

Когда я выполнил конфигурирование любого готового пакета, то на моей Ubuntu-машине я увидел следующие строки:

$ ./configure.sh
...
checking build system type... i686-pc-linux
checking host system type... i686-pc-linux
...

Покопавшись в файле config.sub можно найти большой перечень систем и процессоров.

Другие опции, предназначены для детального указания наличия программного или аппаратного обеспечения на машине, и включения (или исключения) отдельных частей пакета (например, поддержка шифрования или нет).

'--enable-feature[=parameter]'
Конфигурирует пакет для сборки и установки пользовательской возможности, называемой функцией (feature). Это позволяет пользователям выбрать какие функции следует включать. Передавая необязательный параметр 'no', должно отключать возможность, если она встроена по-умолчанию. Опция '--enable' не должна быть причиной замены одной возможности на другую. Также опция '--enable' даже не должна заменять одно полезное поведение на другое. Единственное корректное использование для '--enable' это опрос того, какая часть программы должна включаться, а какая исключаться.
'--with-package'
Пакет package будет установлен, поэтому сконфигурируйте вашу сборку для работы с package. Возможные значения 'x', 'x-toolkit', 'gnu-as' (или 'gas'), 'gnu-ld', 'gnu-libc' и 'gdb'. Не используйте опцию '--with', чтобы указывать имя файла для использования некоторых файлов, так как это выходит за пределы области видимости.
'--nfp'
Машина назначения не имеет процессора для вычислений с плавующей точкой.
'--gas'
Ассемблер машины назначения - GAS (GNU assembler). Эта опция устарела, пользователи вместо неё должны использовать '--with-gnu-as'
'--x'
На машине назначение имеется установленная система X Window. Эта опция устарела, пользователи вместо неё должны использовать '--with-x'.

Все скрипты configure должны принимать опции "детально", так или иначе они осуществляют любое различие пакета. В частности, они должны принимать любую опцию начинающуюся с '--with-' или '--enable-'. Это позволит пользователям конфигурировать всё дерево исходников GNU одним набором опций.

Вы заметите, что категории '--with-' или '--enable-' узки: они не предоставляют места для любого другого вида опций, о которых вы можете подумать. Это неслучайно. Мы (я о группе GNU) хотим ограничить возможное число опций конфигурирования в программном обеспечении GNU. Мы не хотим, чтобы GNU программы имели уникальные конфигурационные опции.

Пакеты, которые выполняют часть процесса компиляции могут поддерживать кросс-платформенность. В таком случае, исходная (host) и машина назначения (target) для программы могут быть различными. Конфигурационный скрипт должен нормально обрабатывать указанные типы систем как первой, так и второй, таким образом создавая программу, которая работает на машине того же типа, откуда он и был запущен.

Способ для сборки кросс-компилятора, кросс-ассемблера или того, что есть у вас, это указать опцию '--host=hosttype' при запуске configure. Это указывает исходную систему, без изменеия системы назначения. Синтаксис для hosttype такой же как было описано выше.

Улучшение кросс-компилятора требует компилирование его на машине отличной от той, на которой он будет работать. Пакеты компиляции принимают опцию '--host=hosttype' для назначения конфигурации, что вы будете собирать их на машине, отличной от хоста (другими словами, как я понимаю, если вы будете использовать компилятор на Sun машине, а на руках у вас другая *nix машина, то вам нужно собрать компилятор для Sun сперва, а потом его уже использовать там.)

Программы, для которых кросс-операции не являются значащими, не нуждаются в опции '--host', потому что конфигурирование целой операционной системы для межплатформенных операций не является значительным.

Некоторые программы имеют способы автоматического конфигурирования себя. Если ваша программа настроена, чтобы выполнять это, ваш configure скрипт может просто игнорировать большинство своих аргументов.

28 июл. 2008 г.

Epson Perfection 1270 и Ubuntu

Когда я перешёл на Ubuntu 7.04, у меня возникла потребность установки сканера Epson Perfection 1270. Но на тот момент у меня опыта в линксе было немного, потому лишь спустя продолжительное время, я решил написать этот туториал для тех, кто испытывает затруднения со своими сканнерами.

То, что я опишу ниже, было произведено на Ubuntu версиях 7.10 и 8.04. Насчёт других моделей, не знаю, пробуйте и описывайте по шагам, как это делали Вы.


Этот сканер, будучи подключённым к интерфейсу, определяется следующим образом:

$ lsusb
Bus 005 Device 005: ID 04b8:0120 Seiko Epson Corp.

Далее следует установить пакеты sane и sane-utils, если они уже не стоят у вас:

$ sudo aptitude install sane sane-utils

После этого следует выполнить команду для предварительного обнаружения вашего сканера:

$ sane-find-scanner
found USB scanner (vendor=0x04b8 [EPSON], product=0x0120 [EPSON Scanner]) at libusb:005:005

Окончание, в каком месте был найден сканер, может отличаться от приведённого примера. Оно меняется, стоит Вам вытащить, и снова вставить интерфейс в компьютер.

После того, как вы установили пакеты от sane, отредактируйте файл /etc/sane.d/snapscan.conf:

$ sudo nano /etc/sane.d/snapscan.conf

В самом начале вы увидете следующую строку (комментарий переводить не буду, но не будет лишним ознакомится со смыслом сказанного):

firmware /usr/share/sane/snapscan/your-firmwarefile.bin

Основная идея прошивки (firmware) состоит в том, что она закачивается в ваш сканер в момент сканирования, для того, чтобы это сканирование непосредственно выполнять. Firmware у Epson Perfection 1270 имеет имя ESFW3E.BIN

Для его получения следует распаковать и установить драйвера для сканера из установочного диска. Я, например, это сделал с помощью Wine, хотя вы можете использовать рабочую версию OS Windows или же попытаться распаковать их вручную.

Каталог, который содержит драйвера лежит в корне компакт диска с названием escan. После установки, в каталоге windows/system Вы должны обнаружить файл ESFW3E.BIN

Приведу его контрольную сумму, для чего, скажу ниже:

$ ls -l ESFW3E.BIN
-rw-r--r-- 1 vest vest 64000 2003-09-14 18:00 ESFW3E.BIN

$ md5sum ESFW3E.BIN
486fe0266b3f11c9bad14ccbf5ce87bf ESFW3E.BIN

Если использовать прошивку, написанную именно маленькими буквами (она содержится в новых драйверах для сканера с оффициального сайта), то сканер может не запуститься, это выглядит так, что сканирующая головка дёрнется и не поедет дальше. В общем, выходом является только использование стандартных драйверов, поставляемых со сканером.

Я, прежде чем это осознать, перепробовал версии три-четыре.

После этого, следует скопировать firmware в любой каталог, я, например, решил скопировать его туда, где производился первоначальный поиск, в /usr/share/sane/snapscan/ и после исправить путь на следующий:

firmware /usr/share/sane/snapscan/ESFW3E.BIN

Для дальнейшего определения сканера, следует запустить команду:

$ scanimage -L

No scanners were identified. If you were expecting something different,
check that the scanner is plugged in, turned on and detected by the
sane-find-scanner tool (if appropriate). Please read the documentation
which came with this software (README, FAQ, manpages).

Вы видите, что сканер не определился. Это связано с тем, что в файле snapscan.conf (который исправляли выше) следует добавить строки идентифицирующие наш сканер. Похожие строки имеются по всему файлу. Информация должна вводится та, которую получили после ввода lsusb:

# Epson Perfection 1270
usb 0x04b8 0x0120

Далее проверим ещё раз:

$ scanimage -L
device `snapscan:libusb:005:005' is a EPSON EPSON Scanner flatbed scanner

Сканер определился. Теперь попробуем произвести тестовое сканирование:

$ scanimage -d snapscan > /tmp/test.pnm
[snapscan] Scanner warming up - waiting 9 seconds.
[snapscan] Scanner warming up - waiting 35 seconds.

Несколько раз сканер попробует прогреться, потом двинется на несколько миллиметров и остановится. Снова возникла "какая-то" неизвестная ошибка. Связана она с тем, что как кто-то писал на форуме, у производителей Sane не дошли руки, чтобы исправить ошибку, связанную с калибровкой качества. Поэтому нам следует сперва её найти, а потом отключить:

$ scanimage —help
List of available devices:
snapscan:libusb:005:005

--quality-cal[=(yes|no)] [yes]
Do a quality white-calibration

Видите, по умолчанию она включена, [yes]. потому её следует отключать:

$ scanimage -d snapscan --quality-cal=no > /tmp/test.pnm

И всё, пожалуйста, в каталоге /tmp ищите свой файл test.pnm

В том же самом gimp'e можно сканировать с помощью xsane, но главное не забыть, чтобы была отключена автоматическая калибровка качества.


Удачи.

p.s. для отладочных целей можете использовать комманду

$ export SANE_DEBUG_DLL=255
$ scanimage -d snapscan --quality-cal=no > /tmp/test.pnm