× К оглавлению На главную Об авторе

Дата и время публикации:

Организация и использование


1. Что такое статическая библиотека

Для использования одних и тех же примитивов, обеспечивающих различные функциональные абстракции в рамках одного проекта одновременно нескольким несвязанных между собой модулям, программисту не всегда удобно использовать динамически подгружаемую библиотеку. Это связано с тем что, после изменения её содержимого, постоянно требуется обновлять LD-кэш (файл /etc/ld.so.cache) и размещать (или замещать) сам файл библиотеки с расширением .so на жестком диске компьютера в том месте, где предполагается её использовать. Поэтому для небольших программ такие сложности не нужны и использование статически собранной библиотеки вполне оправдано.

Таким примером использования может служить программа ugtkmainwindow, которая использует статическую библиотеку libugtk-widgets, содержащая виджеты UGtkMenubar, UGtkToolbar, UGtkMainwindow и UGtkStatusbar.

2. Использование в проекте ugtkmainwindow

Дерево проекта программы ugtkmainwindow было создано по рецепту, предлагаемого в статье "Как использовать Automake". Статическая библиотека, как увидим ниже, была включена в него в двух местах – отдельно файлы исходного кода с расширением , в директории libugtk-widgets, и так же отдельно заголовочные файлы, имеющие расширение .h, в директории include/gtk-widgets.

3. Создание директории include/ugtk-widgets

Все заголовочные файлы, имеющие расширение .h, статической библиотеки libugtk-widgets разумно хранить в отдельной директории от исходных текстов, потому что рано или поздно нам захочется сделать статическую библиотеку инсталлируемой. Следовательно, её заголовочные файлы могут быть устанавлены как минимум в одну из двух директорий дерева ОС – /usr/include или /usr/local/include. Поэтому, чтобы в потом файлы не затерялись во-множестве себе подобных, мы будем их складывать в отдельной директории $(top_srcdir)/include/ugtk-widgets.

Примечание Переменная ‘top_srcdir’ указавает на корень проекта текстов исходного кода (в данном случае на корневую директорию нашего проекта ugtkmainwindow). Данная переменная является переменной Automake, доступ к которой обеспечиваетcя скриптом config.status, установленного в свою очередь в корне дереве проекта ugtkmainwindow.

В директории $(top_srcdir)/include создадим Makefile.am и определим правило сборки для заголовочных файлов исходного кода статической бибилиотеки ugtk-widgets:

$ mkdir -p include/ugtk-widgets

В директории $(top_srcdir)/include создадим Makefile.am и определим правило сборки для заголовочных файлов исходного кода статической бибилиотеки ugtk-widgets:

noinst_include_includedir = @includedir@/"ugtk-widgets"
noinst_include_HEADERS =                      \
                ugtk-widgets/ugtkmenubar.h    \
                ugtk-widgets/ugtktoolbar.h    \
                ugtk-widgets/ugtkstatusbar.h  \
                ugtk-widgets/ugtkmainwindow.h
Примечание Переменная ‘includedir’ предназначена для определение файлов, которые будут подключаться во время сборки перепроцессорной дерективой языка Си ‘#include’. При использование с Autoconf, её необходимо трактовать как ‘@includedir@’. В переменной заголовочных файлов исходных текстов noinst_include_HEADERS перечислены те подключаемые файлы, которые не планируется инсталлировать в систему. Поэтому в переменной include_HEADERS используется префикс ‘nodist_’ . В тоже время, так как заголовочные файлы исходного кода используются во время сборки необходимо позоботится, чтобы они были доступны компилятору GCC в директории $(top_srcdir)/include/ugtk-widgets.

4. Создание директории libugtk-widgets

Теперь можно создать в корне проекта $(top_srcdir) директорию, в которой будут собираться файлы исходного кода в объектные и упаковываться в статическую библиотеку:

$ mkdir  -p  libugtk-widgets

В директории $(top_srcdir)/libugtk-widgets создадим Makefile.am и определим правило сборки для статической библиотека libugtk-widgets.a. При этом будем учитывать, что каждая переменная _LIBRARIES перечисляет встроенные библиотеки без права установки в систему.

 noinst_LIBRARIES = libugtk-widgets.a
 libugtk_widgets_a_CFLAGS = -I$(top_srcdir)/include
 libugtk_widgets_a_SOURCES = ugtkmenubar.c   \
                            ugtktoolbar.c   \
                            ugtkstatusbar.c \
                            ugtkmainwindow.c

Перечень исходного кода, компилируемый в объектные файлы и упаковываемый (вернее архивируемый посредством утилиты ar[1]) в библиотеку libugtk_widgets.a, определяется так же как это делается для программ через переменную _SOURCES. Помните, что имя библиотеки является канонизированным, так перемененная _SOURCES соответствует ‘libugtk_widgets_a_SOURCES’, но никак ‘libugtk-widgets .a_SOURCES’.

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

В переменной _CFLAGS указываем путь, где находятся заголовочные файлы исходного кода собираемой статической библиотеки libugtk-widgets.

5. Включение библиотеки libugtk-widgets в дерево проекта ugtkmainwindow

После фактического включение в проект ugtkmainwindow файлов исходного кода статической библиотеки libugtk-widgets.a, для её сборки необходимо в корне проекта $(top_srcdir) прописать в файлах Makefile.am и Сonfigure.ac следующее:

В файле configure.ac нужно включить макросы AC_PROG_RANLIB, AC_PROG_LIBTOOL и AC_CONFIG_MACRO_DIR([m4]):

. . .
AC_CONFIG_MACRO_DIR([m4])
. . .
AC_PROG_RANLIB
AC_PROG_LIBTOOL
. . .
Примечание Макрос AC_PROG_RANLIB должен быть определен при встраивании любых библиотек в дерево проекта. Макрос AC_PROG_LIBTOOL включает обработку для libtool, который упрощает создание статической или динамической библиотеки. Макрос AC_CONFIG_MACRO_DIR([m4]) указывает на директорию $(top_srcdir)/m4 для определения дополнительных локальных макросов Autoconf. Данные макросы предполагается использовать в будущем командами, подобными autoreconf, которые отслеживают использование макро-вызовов. Макрос AC_CONFIG_MACRO_DIR([m4]) должен быть вызван непосредственно из файла configure.ac, так чтобы утилиты, которые устанавливают макросы для alclocal могли найти его декларацию.

В файле Makefile.am добавляем в переменную SUBDIRS директории include и libugtk-widgets:

. . .
ACLOCAL_AMFLAGS = -I m4
. . .
SUBDIRS src include libugtk-widgets 
. . .
Примечание В переменной SUBDIRS перечисляются директории в которых осуществляются различные виды сборок. В генерируемом Makefile правила для большинства целей (например, для цели: All) выполняются как локально, так и во всех указанных директориях. После выполнения ./configure в перечисленных директориях, в переменной SUBDIRS будут созданы Makefile’ы в соответствие с правилами, прописанными у них в Makefile.am.

Кроме того, перед выполнением autoreconf с ключами ‘-v --make’ нужно в корне проекта $(top_srcdir) создать директорию m4 и уже потом выполнить autoreconf.

После чего, можно выполнить ./confgure и make для пробной сборки проекта без подключения библиотеки libugtk-widgets.a к программе ugtkmainwindow.

6. Подключение библиотеки libugtk-widgets к программе ugtkmainwindow.

Для подключения статической библиотеки libugtk-widgets.a во время сборки программы ugtkmainwindow необходимо добавить переменные _LDADD и _CFLAGS, как показано ниже:

. . .
ugtkmainwindow_CFLAGS = -I$(top_srcdir)/include 
ugtkmainwindow_LDADD  = $(top_srcdir)/libugtk-widgets/libugtk-widgets.a
. . .

7. Подключение библиотеки графического пользовательского интерфейса GTK+

Проект ugtkmainwindow построен на использование библиотеки Gtk+, требующая удовлетворения некоторых зависимостей во время её сборки. Вместо долгого и нудного перечисление их в переменных _LDADD и _CFLAGS, воспользуемся утилитой pkg-config, которая предоставляет общий интерфейс для получения информации об установленных программных библиотеках с целью компиляции программ из исходного кода.

Главным интерфейсом между autoconf (скрипт ./configure) и утилитой pkg-config является макрос PKG_CHECK_MODULES, обеспечивающий достаточно простой и легкий способ проверить наличие запрашиваемого пакета в системе.

Доступ к pkg-config обеспечивается отдельным макросом PKG_PROG_PKG_CONFIG, который вызывается через макрос AC_REQUIRE, но такие сложности нам не потребуются, так как в конечном случае все сводится к использованию PKG_CHECK_MODULES.

В отличии от других бибилотек, при использование Gtk+ необходимо проверять условие возможности сборки проекта с макросом AC_ARG_WITH в связке с AS_IF, используемых для включения поддержки Gtk+-3.0(прим. от автора. Статья была написана в период перехода от Gtk+-2.0 к Gtk+-3.0). Кроме того, как показано ниже, нам потребуется еще проверять установлена glib или нет. Хотя, наверное это излишне, потому что современные дистрибутивы автоматически доставляют необходимые файлы для библиотеки glib, так в дистрибутиве Debian ОС GNU/Linux при установке пакета libgtk2.0-dev автоматически будет установлен пакет libglib2.0-dev.

Поэтому, в конечном итоге, файл configure.ac будет выглядеть следующим образом:

. . .
AC_ARG_WITH([gtk], AS_HELP_STRING([--with-gtk3], [Build with the GTK+ interface])) 
AS_IF([test "x$with_gtk3" = "xyes"],[
PKG_CHECK_MODULES([GTK], [gtk+-3.0]) 
],[
PKG_CHECK_MODULES([GTK], [gtk+-2.0])
]) 
AC_CONFIG_HEADERS([config.h]) 
AC_CONFIG_FILES([
. . .
]) 
. . .

После модификации файла configure.ac, нам остается добавить в файлы Makefile.am соответствующих дирикеторий $(top_srcdir)/libugtk-widgets/ и $(top_srcdir)/src в переменные _CFLAGS и _LDADD, а именно переменные GTK_CFLAGS и GTK_LIBS, как показано ниже:

В $(top_srcdir)/libugtk-widgets/Makefile.am правим:

. . .
noinst_LIBRARIES = libugtk-widgets.a 

libugtk_widgets_a_CFLAGS  = $(GTK_CFLAGS) -I$(top_srcdir)/include 
libugtk_widgets_a_SOURCES = ugtkmenubar.c  \
                            ugtktoolbar.c  \ 
                            ugtkstatusbar.c\ 
                            ugtkmainwindow.c

В $(top_srcdir)/src/Makefile.am правим:

. . .
bin_PROGRAMS = ugtkmainwindow 
. . .
ugtkmainwindow_CFLAGS  =  $(GTK_CFLAGS) \ 
                          -I$(top_srcdir)/include 
ugtkmainwindow_LDADD   = $(GTK_LIBS)    \ 
                         $(top_srcdir)/libugtk-widgets/libugtk-widgets.a 
. . .

8. Библиография

1) Automake

2) With autoconf/automake, how do I specify include file paths?

3) Building C/C++ libraries with Automake and Autoconf

4) Bug #901333

5) Autotools Mythbuster. Pkgconfig

6) CONFIGURING PACKAGES TO WORK WITH GTK