Интернет, компьютеры, софт и прочий Hi-Tech

Подписаться через RSS2Email.ru

Система конфигурирования и сборки GNU

Система конфигурирования и сборки GNU

Иан Ланс Тейлор

Начало работы

Пример

Давайте рассмотрим тривиальный пример.

Допустим, вы хотите написать простую версию `touch'. Ваша программа, которую мы будем называть `poke', будет принимать в качестве аргумента единственное имя файла и использует систему `utime', чтобы установить время модификации и доступа к данному файлу на текущее время. Мы хотим, чтобы эта программа была максимально портируемой.

Сначала давайте посмотрим, как это выглядит без использования autoconf и automake, а потом посмотрим что получится при их использовании.

Первая попытка

Произведем наш первый опыт над `poke.c'. Заметьте, что мы написали его без прототипов ANSI/ISO C, поскольку мы хотим повысить его портируемость.

#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <utime.h>

int
main (argc, argv)
     int argc;
     char **argv;
{
  if (argc != 2)
    {
      fprintf (stderr, "Usage: poke file\n");
      exit (1);
    }

  if (utime (argv[1], NULL) < 0)
    {
      perror ("utime");
      exit (1);
    }

  exit (0);
}

Кроме того мы напишем простой `Makefile':

CC = gcc
CFLAGS = -g -O2

all: poke

poke: poke.o
    $(CC) -o poke $(CFLAGS) $(LDFLAGS) poke.o

Пока все хорошо.

Однако, здесь есть несколько проблем.

В старых системах Unix из ветки BSD 4.3 система `utime' при вызове не принимает `NULL' в качестве второго аргумента. В этих системах нам нужно задавать указатель на структуру `struct utimbuf'. К несчастью, в тех же старых системах эта структура не определена. В качестве нее нам придется задавать массив из двух значений `long'.

Заголовочный файл `stdlib.h' был придуман в ANSI C, и старые системы не имеют его копий. Мы включили его выше для получения декларации функции `exit'.

Мы можем обнаружить некоторые из этих проблем при запуске `autoscan', который создаст файл `configure.scan'. Этот последний мы можем использовать в качестве прототипа нашего файла `configure.in'. Я не хочу приводить здесь вывод, но в нем достаточно замечаний о потенциальных проблемах с `utime' и `stdlib.h'.

В нашем `Makefile' мы не предоставляем каких либо способов инсталляции программы. Это не имеет значения для нашего простого примера, но для реальной программы может понадобиться цель `install'. В этом случае нам также захочется иметь и цель `clean'.

Вторая попытка

Теперь второй раз попытаемся сделать нашу программу.

Мы модифицируем `poke.c' с использованием макросов препроцессора для контроля того, какие возможности нам доступны. (Я немного жульничаю используя те же макро-имена, которые будут использованы в autoconf).

#include <stdio.h>

#ifdef STDC_HEADERS
#include <stdlib.h>
#endif

#include <sys/types.h>

#ifdef HAVE_UTIME_H
#include <utime.h>
#endif

#ifndef HAVE_UTIME_NULL

#include <time.h>

#ifndef HAVE_STRUCT_UTIMBUF

struct utimbuf
{
  long actime;
  long modtime;
};

#endif

static int
utime_now (file)
     char *file;
{
  struct utimbuf now;

  now.actime = now.modtime = time (NULL);
  return utime (file, &now);
}

#define utime(f, p) utime_now (f)

#endif /* HAVE_UTIME_NULL  */

int
main (argc, argv)
     int argc;
     char **argv;
{
  if (argc != 2)
    {
      fprintf (stderr, "Usage: poke file\n");
      exit (1);
    }

  if (utime (argv[1], NULL) < 0)
    {
      perror ("utime");
      exit (1);
    }

  exit (0);
}

Ниже приведен соответствующий `Makefile'. Мы добавили в него поддержку используемых нами флагов препроцессора. Кроме того мы добавили цели `install' и `clean':

# Укажите здесь свою инсталляционную директорию.
bindir = /usr/local/bin

# Раскоментируйте это, если имеете стандартные заголовочные файлы ANSI/ISO C.
# STDC_HDRS = -DSTDC_HEADERS

# Раскомментируйте это, если имеете utime.h.
# UTIME_H = -DHAVE_UTIME_H

# Раскомментируйте это, если в вашей системе работает utime (FILE, NULL).
# UTIME_NULL = -DHAVE_UTIME_NULL

# Раскомментируйте это, если в utime.h объявлен struct utimbuf.
# UTIMBUF = -DHAVE_STRUCT_UTIMBUF

CC = gcc
CFLAGS = -g -O2

ALL_CFLAGS = $(STDC_HDRS) $(UTIME_H) $(UTIME_NULL) $(UTIMBUF) $(CFLAGS)

all: poke

poke: poke.o
    $(CC) -o poke $(ALL_CFLAGS) $(LDFLAGS) poke.o

.c.o:
    $(CC) -c $(ALL_CFLAGS) poke.c

install: poke
    cp poke $(bindir)/poke

clean:
    rm poke poke.o

Таким способом можно решить некоторые проблемы.

Пользователи, которые захотят скомпилировать программу poke, должны знать, как работает `utime' в их системах, чтобы правильно раскомментировать строки в `Makefile'.

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

Использование таких переменных `Makefile' как `CC', `CFLAGS' и `LDFLAGS' требуется стандартами GNU. Это — соглашения для всех пакетов, которые предохраняют пользователей от сюрпризов. Впрочем, все эти детали не застраховывают от получения посредственного нестандартного дистрибутива.

Третья попытка

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

Единственное изменение, которое сделаем в `poke.c', — это добавление следующей строки в начало файла:

#include "config.h"

Новый файл `configure.in' будет следующим:

AC_INIT(poke.c)
AM_INIT_AUTOMAKE(poke, 1.0)
AM_CONFIG_HEADER(config.h:config.in)
AC_PROG_CC
AC_HEADER_STDC
AC_CHECK_HEADERS(utime.h)
AC_EGREP_HEADER(utimbuf, utime.h, AC_DEFINE(HAVE_STRUCT_UTIMBUF))
AC_FUNC_UTIME_NULL
AC_OUTPUT(Makefile)

Первые четыре макроса в этом файле а также один последний были описаны выше, — смотрите параграф Написание configure.in. Если мы опустим эти макросы, то при запуске `automake' мы получим сообщение о том, что они нам нужны.

Другие макросы являются стандартными макросами autoconf.

`AC_HEADER_STDC'
Проверка для стандартных C-шных заголовков.
`AC_CHECK_HEADERS'
Проверка, существует ли особый заголовочный файл.
`AC_EGREP_HEADER'
Проверка для специальных строк в специальном заголовочном файле. В данном случае — проверка на `utimbuf' в `utime.h'.
`AC_FUNC_UTIME_NULL'
Проверка, принимает ли `utime' NULL в качестве второго аргумента для установки времени изменения файла в текущее время.

Более подробное описание можно найти в мануале по autoconf.

Новый `Makefile.am' будет следующим (заметьте, насколько он проще по сравнению с нашим предыдущим `Makefile'):

bin_PROGRAMS = poke

poke_SOURCES = poke.c

Это означает, что мы должны собрать единственную программу с именем `poke'. Она должна быть установлена в директорию с бинарниками, которую ранее мы назвали как `bindir'. Программа `poke' собирается из файла с исходным кодом `poke.c'.

Мы должны еще написать файл `acconfig.h'. Кроме `PACKAGE' и `VERSION', которые должны упоминаться во всех пакетах, использующих automake, мы должны включить `HAVE_STRUCT_UTIMBUF' поскольку уже упоминали его в `AC_DEFINE'.

/* Название пакета. */
#undef PACKAGE

/* Версия пакета. */
#undef VERSION

/* В случае, если utime.h объявляет struct utimbuf. */
#undef HAVE_STRUCT_UTIMBUF

Генерация файлов

Теперь мы должны сгенерировать другие файлы с помощью следующих команд.

aclocal
autoconf
autoheader
automake

Когда мы запустим `autoheader', он будет напоминать нам о каждом макросе, который мы забыли добавить в `acconfig.h'.

Когда мы запустим `automake', он захочет добавить некоторые файлы в нашу дистрибуцию. Он будет добавлять их автоматически, если мы используем опцию `--add-missing'.

По умолчанию `automake' будет запускаться в режиме GNU. Это означает, что он может хотеть от нас создания некоторых дополнительных файлов. А именно: `NEWS', `README', `AUTHORS' и `ChangeLog', каждый из которых обязательно присутствует в стандартной дистрибуции GNU. Вы можете добавить каждый из этих файлов, либо запустить `automake' с опцией `--foreign'.

В результате запуска этих утилит будут сгенерированны следующие файлы, каждый из которых будет описан в следующей главе:

  • `aclocal.m4'
  • `configure'
  • `config.in'
  • `Makefile.in'
  • `stamp-h.in'

Назад Вперед
Написание acconfig.h, Генерация файлов Файлы

Перевод: Дмитрий Скоробогатов, 03.12.2011.
Оригинальный текст можно найти по адресу http://www.airs.com/ian/configure/configure_2.html.


Предыдущие публикации:

Биржа долевых инвестиций SIMEX.

Последнее редактирование: 2011-12-03 13:15:04

Метки материала: gnu, система конфигурирования, система конфигурирования и сборки, компиляция, проект gnu, по, бесплатные программы, бесплатное по, софт, разработка по, soft, программное обеспечение, software, спо, документация для программиста, программное обеспечение по

Оставьте, пожалуйста, свой комментарий к публикации

Представиться как     Антибот:
   

Просьба не постить мусор. Если вы хотите потестить xBB, воспользуйтесь кнопкой предварительного просмотра на панели инструментов xBBEditor-а.


© 2007-2017, Дмитрий Скоробогатов.
Разрешается воспроизводить, распространять и/или изменять материалы сайта
в соответствии с условиями GNU Free Documentation License,
версии 1.2 или любой более поздней версии, опубликованной FSF,
если только иное не указано в самих материалах.