вторник, 1 мая 2012 г.

Использование autotools для сборки grabinput

Сегодня дописал grabinput - утилиту, которая может быть полезна для блокировки клавиатуры/мыши от посягательств маленьких детей (а возможно и любого другого, кто не знаком со способом снятия блокировки).

Grabinput поддерживает три режима работы:
  • перехват событий клавиатуры (действие по-умолчанию);
  • перехват событий клавиатуры и мыши (при использовании ключа -l);
  • блокирование дисплея посредством запуска заставки (при использовании ключа -s).
Для себя я подключил комбинацию Ctrl+Win+Scroll Lock для блокировки клавиатуры и Alt+Win+Scroll Lock для блокировки клавиатуры и мыши. Чтобы отменить блокировку нужно последовательно нажать Scroll Lock, Print Screen и Pause (последовательность задается в заголовочном файле src/grab.h).

Исходники состоят из двух файлов:
  • src/grab.c
  • src/grab.h
 И первоначально для сборки использовался простой Makefile:

grabinput: src/grab.c src/grab.h
    gcc -o grabinput -Wall -lX11 src/grab.c

clean:
    rm -f grabinput

И этого было достаточно, чтобы собрать бинарник. Позже пришла идея попробовать использовать для сборки autotools.

Для начала почитал пару примеров и заглянул в исходники пары opensource проектов. Основная сложноть была в том, что часть мануалов была ориентирована на устаревшие версии autoconf/automake, но с горем пополам родилась более-менее рабочая последовательность внедрения autotools:
  • в директории, где лежит src/ запускаем autoscan. При этом создается файл configure.scan, который нужно переименовать в configure.ac.
  • в configure.ac правим параметры макроса AC_INIT, чтобы соответствовать названию и версии исходников. В итоге у меня получилось так:
    #                                               -*- Autoconf -*-
    # Process this file with autoconf to produce a configure script.
    
    AC_PREREQ([2.67])
    AC_INIT([grabinput], [0.3], [tataranovich@gmail.com])
    AM_INIT_AUTOMAKE(grabinput, 0.3)
    AC_CONFIG_SRCDIR([src])
    AC_CONFIG_HEADERS([config.h])
    
    # Checks for programs.
    AC_PROG_CC
    AC_CHECK_PROG([PKGCONFIG], [pkg-config], [yes], [no])
            if test "x$PKGCONFIG" == "xno"; then
                    AC_MSG_ERROR([pkg-config not found])
            fi
    
    # Checks for libraries.
    PKG_CHECK_MODULES([X11], [x11], [], AC_MSG_ERROR([X11 libraries not found]))
    
    # Checks for header files.
    AC_CHECK_HEADERS([stdio.h stdlib.h unistd.h string.h signal.h errno.h])
    
    # Checks for typedefs, structures, and compiler characteristics.
    
    # Checks for library functions.
    
    AC_OUTPUT(Makefile src/Makefile)

    В моем случае инициализируется autoconf/automake и проверяется наличие pkg-config (нужен для поиска libx11-dev), libx11-dev, а также наличие заголовочных файлов: stdio.h stdlib.h unistd.h string.h signal.h errno.h
  • конфигурация automake находится в Makefile.am и src/Makefile.am
    AUTOMAKE_OPTIONS = foreign
    SUBDIRS = src
    EXTRA_DIST = maint
    AUTOMAKE_OPTIONS = foreign выключает жалобы, что исходники разложены не по феншую (не GNU-style), SUBDIRS = src задает директорию с исходниками, а EXTRA_DIST = maint включает в дистрибутив информацию, необходимую для сборки пакета для Debian.
    AM_CFLAGS = -Wall @X11_CFLAGS@
    AM_LDFLAGS = @X11_LIBS@
    
    bin_PROGRAMS = grabinput
    grabinput_SOURCES = grab.c grab.h
    AM_CFLAGS и AM_LDFLAGS задают начальные значения переменных компилятора и линковщика. Обратите внимание на префикс X11_{CFLAGS,LIBS} - эти переменные устанавливаются autoconf при запуске ./configure. bin_PROGRAMS задает расположение бинарника grabinput в $PREFIX/bin, а grabinput_SOURCES - определяет исходники, необходимые для компиляции grabinput
  • чтобы не запускать каждый раз последовательность aclocal, autoheader, automake и autoconf я добавил скрипт autogen.sh, который был содран у какого-то opensource проекта.
    #!/bin/sh
    echo aclocal && aclocal || exit 1
    echo autoheader && autoheader || exit 1
    echo automake && automake --add-missing --copy --force --foreign || exit 1
    echo autoconf && autoconf || exit 1
    
    if test "x$NOCONFIGURE" = "x"; then
      echo configure
      ./configure $*
    fi
Теперь чтобы собрать дистрибутив исходников, я делаю чекаут из репозитория, затем запускаю ./autogen.sh (по-умолчанию скрипт выполняет ./configure). Далее выполняю make dist и в директории появляется архив grabinput-x.x.tar.gz.

Сборка исходников из этого архива знакома многим:

./configure
make
make install

Для Debian-based дистрибутивов в архиве есть директория maint/debian которую нужно скопировать на уровень выше и выполнить

dpkg-buildpackage -rfakeroot -us -uc

В результате будет собран пакет, пригодный для установки.

Ранее я много читал про autotools - мол это говно мамонта, autocrap и т.д. В качестве альтернативы предлагался простой и понятный scons/cmake/qmake/ant/etc - у меня в планах попробовать адаптировать scons для сборки grabinput, чтобы было с чем сравнивать затраты на освоение.

Комментариев нет:

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