Показаны сообщения с ярлыком Programming. Показать все сообщения
Показаны сообщения с ярлыком Programming. Показать все сообщения

2 нояб. 2013 г.

Ubuntu 13.10, Optimus, NVIDIA и т.д.

Такое ощущение, что мои блоги больше посвящены борьбе человека с Линуксом, нежели чем его использованием. Ну да ладно, этот пост не обещает быть длинным, так как написал я его исключительно в помощь самому себе.
Итак, какие же приключения принесла новая версия для моего лептопа? Для начала, Ubuntu во время установки скачивала обновления. После перезагрузки компьютера, загрузки операционной системы не произошло - выскакивала ошибка Kernel panic - not syncing: No init found. Интернет пишет, что, возможно, образ был битый (хотя контрольная сумма совпала). Одним словом, мне помог следующий workaround - установка Ubuntu была с выключенным wi-fi для того, чтобы не было обновлений во это время. А потом уже, операционная система загрузилась без проблем, где после и была обновлена.
Теперь насчёт драйверов для NVIDIA: для установки использовались следующие пакеты (за собой они подтянули с десяток других) - nvidia-319-updates, nvidia-319-updates-dev (мне нужен для разработки), nvidia-settings-319-updates и bumblebee-nvidia. К сожалению, загрузка Unity сопровождалась наличием обоев и больше ничем. Спасибо ресурсу askubuntu.com, где подсказали, что для работы Unity необходимо включить соответствующий плагин в ccsm. Для простоты, скажу - вы ставите compizconfig-settings-manager и запускаете ccsm. Далее, включаете Ubuntu Unity Plugin, как показано у меня на картинке ниже:

Может получится так, что вы не сможете запустить ccsm, потому что у вас не будет консоли в Unity. Что я сделал: я создал пустую папку на рабочем столе, открыл её, через неё нашёл /usr/bin/gnome-terminal, и оттудра запустил менеджер Compiz. Ах да! Если будут предупреждения о каких-то конфликтах, прочтите их и выберите что хотите сами.
Последнее. Для CUDA достаточно скачать .run пакет для x64 дистрибутива линукс (я брал для Ubuntu 12.10) и поставить его с флагом sudo ./cuda_5.5.22_linux_64.run --override. Скорей всего, gcc 4.7 у вас не стоит, и вам придётся его поставить.
Update: кстати, изменённый и немного универсальный файл .bashrc теперь следующий (к сожалению каталога nvidia-current не существует, а все скрипты NVIDIA ищут библиотеки в нём):
export PATH=$PATH:/usr/local/cuda/bin
export LPATH=/usr/lib/nvidia-319-updates:$LPATH
export LIBRARY_PATH=/usr/lib/nvidia-319-updates:$LIBRARY_PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib:/usr/local/cuda/lib64:/usr/lib/nvidia-319-updates
Всего хорошего, и пока!

6 нояб. 2012 г.

CUDA куда-куда? А! В Ubuntu 12.10 - CUDA Part

Круто - но стрёмно! Вот пришла пора описать как я ставил саму CUDA, и какие сложности попались мне на пути. Версия, которую мне захотелось поставить - CUDA 5.0. Четвертая версия сама по себе уже старовата, да и меня прельщала возможность использования Nsight for Linux, нежели чем какие-нибудь собственные make файлы.

Проще говоря, скачать и поставить не проблема, всяких док полно в интернете. Главное есть некоторые нюансы, которые я бы упомянул:

  • Не ставьте драйвера NVIDIA, входящие в комплект SDK;
  • Не ставьте поддержку Optimus - я не знаю, в чем её смысл, но думаю ничего хорошего она вам не принесёт. Во всяком случае интернет молчит по этому поводу;
  • Скорей всего инсталлятор попросит у вас GCC 4.6 - качайте отдельный метапакет для этого. У CUDA заголовков внутри прописана версия компилятора. Поэтому, если попытаетесь всё поднять на 4.7, то у вас отвалится. Любые попытки исправить (особенно, если вы новичок как я) оставьте на потом;

Когда всё поставите (соглашайтесь с дефолтными путями), то первым делом надо собрать каталог ~/NVIDIA_CUDA-5.0_Samples. При сборка каталога командой make вы получите около пяти ошибок, которые легко решаются. И так, понеслось...

g++ -m64 -o vectorAddDrv vectorAddDrv.o -L/usr/local/cuda-5.0/lib64 -lcuda
/usr/bin/ld: error: cannot find -lcuda
vectorAddDrv.o:vectorAddDrv.cpp:function main: error: undefined reference to 'cuInit'
vectorAddDrv.o:vectorAddDrv.cpp:function main: error: undefined reference to 'cuDeviceGetCount'
vectorAddDrv.o:vectorAddDrv.cpp:function main: error: undefined reference to 'cuDeviceComputeCapability'
vectorAddDrv.o:vectorAddDrv.cpp:function main: error: undefined reference to 'cuDeviceGetName'
vectorAddDrv.o:vectorAddDrv.cpp:function main: error: undefined reference to 'cuDeviceGet'
vectorAddDrv.o:vectorAddDrv.cpp:function main: error: undefined reference to 'cuCtxCreate_v2'
vectorAddDrv.o:vectorAddDrv.cpp:function main: error: undefined reference to 'cuModuleLoadDataEx'
...
vectorAddDrv.o:vectorAddDrv.cpp:function main: error: undefined reference to 'cuMemcpyDtoH_v2'
vectorAddDrv.o:vectorAddDrv.cpp:function CleanupNoFailure(): error: undefined reference to 'cuMemFree_v2'
vectorAddDrv.o:vectorAddDrv.cpp:function CleanupNoFailure(): error: undefined reference to 'cuMemFree_v2'
vectorAddDrv.o:vectorAddDrv.cpp:function CleanupNoFailure(): error: undefined reference to 'cuMemFree_v2'
vectorAddDrv.o:vectorAddDrv.cpp:function CleanupNoFailure(): error: undefined reference to 'cuCtxDetach'
collect2: error: ld returned 1 exit status
make[1]: *** [vectorAddDrv] Error 1

Лечится такая ошибка вот этим. Почему именно в .bashrc, а не в .bash_profile? Потому что из под иксов, при запуске gnome-terminal, вызывается именно первый файл, а не второй. Второй будет использоваться только в голой консоли. На всякий случай, вот мой файл:

export PATH=$PATH:/usr/local/cuda-5.0/bin
export LPATH=/usr/lib/nvidia-current:$LPATH
export LIBRARY_PATH=/usr/lib/nvidia-current:$LIBRARY_PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda-5.0/lib:/usr/local/cuda-5.0/lib64:/usr/lib/nvidia-current

Когда возникнет ошибка вида MPI not found (simpleMPI), то советую посмотреть сюда для наглядности и поставить ещё один пакет:

sudo apt-get install libopenmpi-dev

Потом у вас должна возникнуть ошибка с libcublas, которая лечится добавлением опции -ldl к компилятору:

cdpLUDecomposition: dlaswp.o dgetf2.o dgetrf.o cdp_lu.o cdp_lu_main.o
    $(NVCC) $(CCFLAGS) $(GENCODE_FLAGS) -o $@ $+ $(LDFLAGS) $(EXTRA_LDFLAGS) -ldl

Собственно это всё, после этого все демки должны будут скомпилиться и работать. Кстати, к сожалению позднее появление этой статьи в моём браузере является причиной написания этого блог-поста. Прочтите и не пожалеете.

Я не буду, наверное, описывать как программировать под CUDA, потому что сам не умею, но точно прошу вас запомнить следующие команды. Они вам помогут:

optirun nsight    # запускает Eclipse, чтобы программы работали с CUDA
optirun cuda-gdb yourCudaProgram    # запускает отладчик через CUDA

Погуглив в интернете более интенсивно, я понял, что nvcc почему-то не генерит отладочные символы (Debug Symbols) для устройства. В общем, если знаете ответ на этот вопрос, будьте добры, напишите мне где-нибудь...

4 нояб. 2012 г.

CUDA куда-куда? А! В Ubuntu 12.10 - Optimus Part

Линуксу - нет! Так получилось, что во время написания этого поста, я являюсь счастливым обладателем ноутбука фирмы ASUS, модель X7BS. Если захочется погуглить, то в нем Intel Core i7 - 2630QM, 2.0GHz, что даёт мне 8 гипертрединговых ядер, ну и два жёстких по 500 Gb. Однако не это в нём примечательное, а то, что он является обладателем технологии NVIDIA Optimus. Другими словами, его видеокарта GeForce GT 540M (2 Gb) умеет распоряжаться интегрированной Intel'овской картой.

Ну раз моя видеокарта может пользоваться CUDA технологией, то я решил поковырять параллельное программирование на ней на досуге. Проблема в том, что официально NVIDIA поддерживает MS Visual Studio 2008/2010 своим плагином Nsight для разработки приложений под CUDA. Начиная с 5.0 версии, они разродились самостоятельной средой разработки на основе Eclipse. Но минус в том, что эта IDE доступна для Linux'a и Мака (кажется).

Попробовав поставить старые .deb пакеты под обновившуюся недавно Убунту, я наткнулся на несколько, для меня, новостей: Optimus под линуксом идёт плохо, CUDA поддерживает старый компилятор GCC-4.6. Всё это меня расстроило в конец, потому что с OpenSuse дела тоже идут не гладко со старыми компиляторами, поэтому я решил написать статью о том как запустить CUDU с моей видеокартой под линукс.

Для начала нам надо запустить Оптимус. Под ОпенЗюзе есть хорошая статья (на немецком и русском языках), которая дала мне понять, что с Оптимусом под линуксом жить можно. Хочу сразу же обратить внимание на небольшую и простую переписку в форуме, которая мне помогла установить поддержку Оптимуса. Кстати да, я там отличился. У вас, скорей всего, как и у меня x-swat репозитории для 12.10 окажутся пустыми. Но это и не важно, ибо он не нужен вроде как :) В лучшем случае, если не полетит, то в файле /etc/bumblebee/bumblebee.conf должно быть так:

...
Driver=
...
[driver-nvidia]
# Module name to load, defaults to Driver if empty or unset
KernelDriver=nvidia-current
Module=nvidia
...

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

$ groups
user adm cdrom sudo dip plugdev lpadmin sambashare bumblebee

Если у вас всё взлетит, то вы увидите следующие или похожие результаты:


$glxgears
Running synchronized to the vertical refresh. The framerate should be approximately the same as the monitor refresh rate.
304 frames in 5.0 seconds = 60.613 FPS
... Intel
$ optirun glxgears
4439 frames in 5.0 seconds = 887.763 FPS
... NVIDIA
$ glxspheres
Polygons in scene: 62464
Visual ID of window: 0xa3
Context is Direct
OpenGL Renderer: Mesa DRI Intel(R) Sandybridge Mobile
60.271004 frames/sec - 67.262440 Mpixels/sec
... Intel
$ optirun glxspheres
Polygons in scene: 62464
Visual ID of window: 0x21
Context is Direct
OpenGL Renderer: GeForce GT 540M/PCIe/SSE2
110.310679 frames/sec - 123.106717 Mpixels/sec
... NVIDIA

Вот собственно и всё для этой части. Что-то поздно и я подумываю над тем, чтобы пойти спать. К сожалению, я не закончил статью, а посему про CUDA напишу позже... Ку!

4 мар. 2009 г.

Gnome Internationalization или интернационализация средствами Glib и intltool

Теперь пришло время, добавить в наш шаблон «Интернационализацию». Основное отличие от «Локализации» заключается в том, что приложение, поддерживающее интернационализацию физически представляет собой один исполняемый файл (с сопутствующими ему файлами с данными), которое равно запускается в операционной системе и отображает локализованную информацию в зависимости от настроек ОС. Локализованное приложение отображает только тот язык, для которого оно было создано. Так, например, в Windows часто вы встречали фразы «Скачать русскую версию». Так вот, это были локализованные приложения.

Наше приложение пока отображает только английскую локаль. Попробуем встроить в него интернационализацию управляемую библиотекой GLib. Для начала нам понадобятся пара пакетов: intltool и gettext. Они помогут нам, избавив от некоторой рутинной работы.

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

Здесь и далее хочу сказать, что в исходных кодах можно использовать как TAB символы, так и пробелы, в шаблонах configure.ac также, НО в Makefile.am только TAB.

#include <config.h>
#include <stdio.h>
#include <glib/gi18n.h> -- поддержка макросов gettext

int main(int argc, char** argv)
{
    setlocale (LC_ALL, ""); -- устанавливаем текущую локаль, информацию берём с переменных окружения (это можно опустить в GUI программировании)
    bindtextdomain (GETTEXT_PACKAGE, QUOD_LOCALEDIR); -- устанавливаем каталог, где лежат файлы для разных языков
    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); -- устанавливаем кодировку для вывода символов (благо Linux легко поддерживает Unicode)
    textdomain (GETTEXT_PACKAGE); -- установка домена по умолчанию

    printf(_("Hello World!\n")); -- отмечаем текст, который надо перевести с помощью макроса _()

    return 0;
}

Почитав повнимательнее, я выяснил, что оказывается сам GLib локализован с помощью механизма gettext, поэтому он принят стандартом де-факто. Существуют разные макросы, выделяющие наш текст, требующий интернационализации. Например, для строк, к которым не может быть применён вызов gettext (например глобальные переменные переменные принимающие строки в массивах), то к ним применяется макрос N_(). Дополнительную информацию можете поискать в самом Glib'e, либо Internationalising GNOME applications, ещё как вариант скачать intltool, и там прочесть HOW-TO. Вообще, информации много, но вот собранной воедино и с нуля — мало.

Следующим этапом идёт создание каталога po, где будут находиться наши переводы. Заодно, подправим наши шаблоны:

~/gnome-quod$ mkdir po

configure.ac
# ======================== initialization ===============================
AC_INIT([Gnome Quod],
        [0.4.0],
        [vest@mail.com],
        [gnome-quod])

AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([-Wall -Werror dist-bzip2])
AC_DEFINE([NDEBUG], [], [Disable debugging information])

# ==================== basic compiler settings ==========================
AC_PROG_CC
AM_PROG_CC_C_O
AC_HEADER_STDC

# ==================== internationalization i18n ========================
IT_PROG_INTLTOOL([0.40.4]) -- требование библиотеки intltool не ниже 0.40.4
GETTEXT_PACKAGE=gnome-quod -- название пакета выносим в отдельную переменную
AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"], -- которую делаем в качестве
                   [The domain to use with gettext]) -- директивы для препроцессора (см. config.h)
AM_GLIB_GNU_GETTEXT -- не знаю до конца, но скорей всего включает поддержку GETTEXT у Glib (или через)
AC_SUBST(GETTEXT_PACKAGE) -- добавляет опции в компилятор для включения gettext

QUOD_LOCALEDIR=[${datadir}/locale] --указываем, где будут находиться локализации
AC_SUBST(QUOD_LOCALEDIR) -- запоминаем этот путь и добавляем его в опции компилятора

PKG_CHECK_MODULES([GLIB],[glib-2.0 >= 2.18]) -- проверяем, что у нас стоит Glib нужной версии

# ==================== generate files ===================================
AC_CONFIG_FILES([
  Makefile
  src/Makefile
  po/Makefile.in -- выводим ещё один шаблон Makefile'a в новом каталоге po
])
AC_OUTPUT

В HOW-TO, я прочитал следующее, что вместо AM_GLIB_GNU_GETTEXT можно использовать AM_GNU_GETTEXT([external]), а сам autoreconf предложил мне воспользоваться AM_GNU_GETTEXT_VERSION. С одним предупреждением у меня получился следующий вариант:

...
AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"],
                   [The domain to use with gettext])
AM_GNU_GETTEXT_VERSION
...

$ autoreconf
...
autoreconf: configure.ac: AM_GNU_GETTEXT_VERSION is used, but not AM_GNU_GETTEXT

с другим вариантом:

autoreconf: configure.ac: AM_GNU_GETTEXT is used, but not AM_GNU_GETTEXT_VERSION
configure.ac:23: required file `./config.guess' not found
configure.ac:23: `automake --add-missing' can install `config.guess'
configure.ac:23: required file `./config.rpath' not found
configure.ac:23: required file `./config.sub' not found
configure.ac:23: `automake --add-missing' can install `config.sub'
configure.ac:23: required file `./ABOUT-NLS' not found

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

// Makefile.am
SUBDIRS = src po -- добавляем лишний каталог

@INTLTOOL_DESKTOP_RULE@ -- этот макрос позволяет intltool определить, где какие файлы требуют перевода (в частности, в корневой директории может находиться будущий ярлык программы)

INTLTOOL_FILES = \
        intltool-extract.in \
        intltool-merge.in \
        intltool-update.in

EXTRA_DIST = $(INTLTOOL_FILES)

DISTCLEANFILES = \
        intltool-extract \
        intltool-merge \
        intltool-update


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

# эти строки я встречал не всегда. Они отвечают за очистку кеша, создаваемого intltool
clean-local:
        rm -f po/.intltool-merge-cache


// src/Makefile.am
quod_CFLAGS = \ -- задаём флаги для конкретного исполняемого файла (quod)
        -DQUOD_LOCALEDIR=\"${QUOD_LOCALEDIR}\" \ -- где лежат наши локали
        $(GLIB_CFLAGS) \ -- флаги для компиляции с Glib
        -I$(top_srcdir) -- путь, с заголовками уровнем выше (обычно для config.h)

quod_LDADD = \ -- тоже самое, но для линковщика
        $(INTLLIBS) \ -- библиотеки intltool
        $(GLIB_LIBS) -- библиотеки Glib

bin_PROGRAMS = quod
quod_SOURCES = main.c

В предыдущем посте я описывал, почему я использовал макрос AM_PROG_CC_C_O. Именно благодаря ему, я указал для конкретного бинарного файла нужные флаги для компилятора. Теперь следует дописать небольшие файлы в po каталог, и затем приступить к запуску скриптов. Процедура создания файлов немного автоматизирована:

~/gnome-quod$ intltoolize -- этот скрипт создаст файл po/Makefile.in.in

// вручную создаём po/LINGUAS
# please keep this list sorted alphabetically
#
ru -- по алфавиту указываем какие языки у нас будут присутствовать

// вручную создаём po/POTFILES.in
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
src/main.c -- здесь описываем все файлы, где нужен перевод (даже файлы с ярлыками для рабочего стола)

// Проверяем:
~/gnome-quod/po$ ls -l
итого 8
-rwxr-xr-x 1 vest vest 51 2008-12-10 10:50 LINGUAS
lrwxrwxrwx 1 vest vest 34 2009-03-04 18:52 Makefile.in.in -> /usr/share/intltool/Makefile.in.in
-rwxr-xr-x 1 vest vest 68 2009-03-04 19:04 POTFILES.in

На самом деле видите, что Makefile.in.in это всего-навсего ссылка. Далее попытаемся создать pot-файл, содержащий строки, нуждающиеся в переводе:

~/gnome-quod/po$ intltool-update --pot -- выполнять это надо внутри каталога po

~/gnome-quod/po$ cat gnome-quod.pot
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-03-04 19:08+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"

#: ../src/main.c:13
#, c-format
msgid "Hello World!\n"
msgstr ""

Вот так выглядит шаблон, созданный скриптом. Сам pot-файл не нужен, так как генерируется автоматически. То, что требуется от вас, это сделать копию файла с именем того языка, на который вы будете создавать свою локализацию (в нашем случае ru.po). Сам файл хорошо документирован, вам следует обратить внимание на то, что CHARSET следует исправить в UTF-8. Есть другой способ создать шаблон нужной локализации средствами gettext (но про UTF-8 строки следует не забывать. Помните наши изменения в исходном файле main.c):

~/gnome-quod/po$ msginit --locale=ru
Новый каталог сообщений должен содержать ваш адрес электронной почты,
чтобы пользователи могли присылать свои замечания по поводу ваших
передов, а также чтобы сопроводители программ могли связаться с вами в
том случае, если возникнут непредвиденные технические проблемы.

Which is your email address?
1 Vest@home.tula.net
...
9 vest@vest-desktop

Please choose the number, or enter your email address.
9 -- я ввёл это чисто (просто так, на самом деле введите либо номер либо свой реальный адрес)
A translation team for your language (ru) does not exist yet.
If you want to create a new translation team for ru, please visit
 http://www.iro.umontreal.ca/contrib/po/HTML/teams.html
 http://www.iro.umontreal.ca/contrib/po/HTML/leaders.html
 http://www.iro.umontreal.ca/contrib/po/HTML/index.html

Создано ru.po. -- вот это самое главное.

~/gnome-quod/po$ cat ru.po
# Russian translations for Gnome Quod package.
# Copyright (C) 2009 THE Gnome Quod'S COPYRIGHT HOLDER
# This file is distributed under the same license as the Gnome Quod package.
# Vladislav Volodin <vest@vest-desktop>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: Gnome Quod 0.4.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-03-04 19:08+0300\n"
"PO-Revision-Date: 2009-03-04 19:18+0300\n"
"Last-Translator: Vladislav Volodin <vest@vest-desktop>\n"
"Language-Team: Russian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ASCII\n" -- как видите, это надо поменять на UTF-8
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"

#: ../src/main.c:13
#, c-format
msgid "Hello World!\n"
msgstr ""

Далее переводим строку следующим образом. Оставляем оригинал вверху, нужный перевод внизу, и всё сохраняем в формате UTF-8:

...
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"

#: ../src/main.c:13
#, c-format
msgid "Hello World!\n"
msgstr "Привет Мир!\n"

И пробуем реконфигурировать наш проект, собирать, и устанавливать. Остаётся проверить:

vest@vest-desktop:~/gnome-quod$ autoreconf && ./configure && make
...
checking whether NLS is requested... yes
checking for intltool >= 0.40.4... 0.40.5 found
checking for intltool-update... /usr/bin/intltool-update
checking for intltool-merge... /usr/bin/intltool-merge
checking for intltool-extract... /usr/bin/intltool-extract
checking for xgettext... /usr/bin/xgettext
checking for msgmerge... /usr/bin/msgmerge
checking for msgfmt... /usr/bin/msgfmt
checking for gmsgfmt... /usr/bin/msgfmt
...
checking for GLIB... yes
...
# INTLTOOL_MAKEFILE
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.. -DQUOD_LOCALEDIR=\"/usr/local/share/locale\" -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I.. -g -O2 -MT quod-main.o -MD -MP -MF .deps/quod-main.Tpo -c -o quod-main.o `test -f 'main.c' || echo './'`main.c
mv -f .deps/quod-main.Tpo .deps/quod-main.Po
gcc -DQUOD_LOCALEDIR=\"/usr/local/share/locale\" -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I.. -g -O2 -o quod quod-main.o -lglib-2.0
...
~/gnome-quod$ quod
Привет Мир!
$

Теперь можно вас поздравить с тем, что у вас «интернационализовано» ваше приложение. Далее попробуйте уже сами создать пакет с помощью make dist, и просмотреть какие файлы распространяются с пакетом, а какие нет.

И ещё, не забывайте каждый раз обновлять файл POTFILES.in, когда добавляете новые исходные файлы в src каталог. И затем выполняйте intltool-update ru. Она также обновляет файлы с переводом, если у вас добавляются новые строки, указывая вам на число переведённых или не переведённых строк. Смотрите, что будет если подправить исходный код следующим образом:

// main.c
printf(_("Hello World!!\n")); -- лишний восклицательный знак

:~/gnome-quod$ cd po
~/gnome-quod/po$ intltool-update ru
... завершено.
0 переведенных сообщений, 1 неточный перевод.
~/gnome-quod/po$ cat ru.po

#: ../src/main.c:13
#, fuzzy, c-format -- здесь он подправил, что наше исходной сообщение теперь другое. После исправления это слово можно стереть
msgid "Hello World!!\n" -- ведь появился восклицательный знак
msgstr "Привет Мир!!\n" -- добавим его здесь

Вот собственно и всё, жду Ваших комментариев и дополнений.

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). Советую с ней ознакомиться.

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 скрипт может просто игнорировать большинство своих аргументов.