Дата и время публикации:
Организация и использование
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)/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
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’.
В переменной _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 . . .
В файле Makefile.am добавляем в переменную SUBDIRS директории include и libugtk-widgets:
. . . ACLOCAL_AMFLAGS = -I m4 . . . SUBDIRS src include libugtk-widgets . . .
Кроме того, перед выполнением 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