Директории: Что, где и как

Большая часть работы над рецептом связана с описанием того, где располагаются необходимые файлы и куда должны быть установлены собираемые. Например, программы, предназначенные для целевой машины, ни в коем случае не должны использовать файлы из директорий, подобных /usr/include или /usr/lib. Аналогично вряд ли будет хорошим решением установка в каталог /usr/bin на машине сборки, так как будут исполняемые файлы будут перезаписаны нерабочими версиями, собранными под целевое устройство.

Далее перечисляются директории, наиболее часто используемые в рецептах, и более подробное описание которых приведено в оставшейся части главы:

Рабочая директория: WORKDIR

В эту директории распаковываются архивы с исходным кодом, копируются дополнительные файлы, в ней создаются поддиректории для логов, устанавливаемых файлов и т.д.

Директория с распакованным исходным кодом: S

Здесь применяются указанные патчи и происходит сборка программы.

Директория назначения: D

Сюда происходит установка пакета. Пакетная система на основе файлов из этой директории создает новые пакеты уже для установки на целевую машину.

Директории установки: bindir, docdir, ...

Этот набор переменных доступен для описания всех путей на целевом устройстве, которые могут понадобится. Рецепты должны использовать эти переменные вместо того, чтобы жестко прописывать пути.

"Staging" директории: STAGING_LIBDIR, STAGING_INCDIR, ...

В эти каталоги устанавливаются заголовочные файлы, библиотеки и прочие файлы, которые были сгенерированы одним рецептом, но могут понадобиться для других. Например, пакет с библиотекой должен сделать заголовочные файлы и файлы библиотек доступными для остальных рецептов чтобы они могли быть связаны.

Пути файлам: FILE, FILE_DIRNAME, FILESDIR, FILESPATH

Эти переменные указывают, где находятся нужные файлы. Используя их, можно отдельно хранить патчи для разных версий или релизов рецепта, и/или использовать один и тот же патч для разных версий и так далее.

WORKDIR: Рабочая директория

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

Если посмотреть на рецепт программы quagga, то можно обнаружить простые файлы (не патчи), служащие для настройки и инициализации:

SRC_URI = "http://www.quagga.net/download/quagga-${PV}.tar.gz \
           file://fix-for-lib-inpath.patch;patch=1 \
           file://quagga.init \
           file://quagga.default \
           file://watchquagga.init \
           file://watchquagga.default"

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

do_install () {
    # Install init script and default settings
    install -m 0755 -d ${D}${sysconfdir}/default ${D}${sysconfdir}/init.d ${D}${sysconfdir}/quagga
    install -m 0644 ${WORKDIR}/quagga.default ${D}${sysconfdir}/default/quagga
    install -m 0644 ${WORKDIR}/watchquagga.default ${D}${sysconfdir}/default/watchquagga
    install -m 0755 ${WORKDIR}/quagga.init ${D}${sysconfdir}/init.d/quagga
    install -m 0755 ${WORKDIR}/watchquagga.init ${D}${sysconfdir}/init.d/watchquagga
    ...

S: Распакованный исходный код

Bitbake считает, что распакованный исходный код пакета находится в директории <packagename>-<version> в WORKDIR. Именно в ней будут применяться патчи, проводится компиляция и из нее будут браться файлы для установки.

Например, есть пакет widgets_1.2.bb, который извлекается из файла widgets-1.2.tar.gz. Bitbake будет искать исходный код в директории widgets-1.2 рабочего каталога. Если директория отличается, то это явно должно быть указано установкой переменной S.

Если widgets-1.2.tar.gz на самом деле извлекается в директорию widgets, без номера версии, вместо widgets-1.2, то переменная S будет указывать на несуществующий путь, а значит применение патчей и компиляция не будут выполнены. Поэтому стандартное значение S должно быть изменено на действительное, в нашем примере это:

S = "${WORKDIR}/widgets"

D: Директория назначения

Сюда копируются все файлы собранного приложения для подготовки к упаковке. Обычно при установке файлы размещаются в такие директории, как /etc или /usr/bin, но они используются хостом и поэтому не подходят для установки. Вместо этого, должны быть использованы поддиректории внутри директории назначения.

Таким образом, файлы, предназначенные для установки в /usr/bin, будут размещены в ${D}/usr/bin.

Следующий пример из пакета arpwatch показывает команду make install, которой переменная ${D} была передана как параметр DESTDIR для указания того, куда должна проводиться установка:

do_install() {
        ...
        oe_runmake install DESTDIR=${D}

Следующий пример из пакета quagga показывает использования директории назначения для установки конфигурационных файлов и скриптов инициализации:

do_install () {
        # Установка скриптов инициализации и настроек по умолчанию
        install -m 0755 -d ${D}${sysconfdir}/default ${D}${sysconfdir}/init.d ${D}${sysconfdir}/quagga
        install -m 0644 ${WORKDIR}/quagga.default ${D}${sysconfdir}/default/quagga
        install -m 0755 ${WORKDIR}/quagga.init ${D}${sysconfdir}/init.d/quagga

Замечание

Такие директории, как /etc и /usr/bin не должны использоваться напрямую в рецептах. Вместо этого должны быть использованы переменные, указывающие на эти места. Полный список таких переменных можно найти в разделе Installation directories справочника.

"Staging" директории

Используются для того, чтобы библиотеки, заголовочные и бинарные файлы, созданные по одному рецепту, могли быть использованы другими. Например, сборка библиотеки требует не только того, чтобы были созданы библиотеки и заголовочные файлы, но и чтобы они были доступны для других пакетов.

Реализация доступности библиотек, заголовочных и бинарных файлов для других рецептов называется "staging" и производится задачей stage рецепта. Любые рецепты, содержащие элементы, необходимые для сборки других пакетов, должны реализовывать задачу stage и корректно размещать нужные файлы в "staging" директориях. В следующем примере из рецепта clamav показывается, как библиотеки и заголовочные файлы устанавливаются в нужные директории:

do_stage () {
        oe_libinstall -a -so libclamav ${STAGING_LIBDIR}
        install -m 0644 libclamav/clamav.h ${STAGING_INCDIR}
      }

Далее приводится пример из p3scan рецепта, в котором путь к библиотеке clamav передается скрипту configure. Без этого указания, скрипт не сможет найти библиотеку, либо, что еще хуже, будет искать ее в системных каталогах хоста. После "staging" директории поиск будет вестись в нужныз каталогах и для сборки будут использоваться корректные библиотеки и заголовочные файлы clamav:

EXTRA_OECONF = "--with-clamav=${STAGING_LIBDIR}/.. \
                --with-openssl=${STAGING_LIBDIR}/.. \
                --disable-ripmime"

Хотя "staging" директории автоматически добавляются к командам компиляции и линковки, иногда, как в примере с p3scan, возникает необходимость явно указывать пути. Обычно это бывает нужно для autoconf скриптов, которые ведут поиск библиотек и заголовков по нескольким местам.

Замечание

Многие вспомогательные классы, такие как pkgconfig и autotools добавляют нужные команды к задаче stage за вас. В главе справочник (Глава 9, Справочник) по описаниям классов можно узнать, какие функции дополняет каждый из них.

Полный список "staging" директорий можно найти в разделе Staging directories справочника.

FILESPATH/FILESDIR: Поиск локальных файлов

Относящиеся к файлам переменные используются bitbake для того, чтобы определить места поиска патчей и прочих локальных файлов.

Обычно нет необходимости изменять их, но бывает полезно знать значения по умолчанию. Чаще всего при поиске патчей и/или других файлов (file:// URI's), поиск ведется по следующим путям:

${FILE_DIRNAME}/${PF}

Имя пакета, версия и релиз, например "strace-4.5.14-r1". Этот путь достаточно редко используется, так как патчи в этом случае можно будет найти только для конкретного релиза рецепта.

${FILE_DIRNAME}/${P}

Имя пакета и версия, например "strace-4.5.14". Именно в этом каталоге чаще всего расположены патчи, относящиеся к этой версии.

${FILE_DIRNAME}/${PN}

Только имя пакета, например "strace". Редко используется.

${FILE_DIRNAME}/files

Директория "files". В ней чаще всего расположены патчи и файлы, которые подходят для всех версий пакета.

${FILE_DIRNAME}/

Просто базовая директория для рецептов. Используется для очень редко, так иначе была бы просто захламлена кучей файлов.

Каждый из этих путей относителен директории ${FILE_DIRNAME}, в которой расположены рецепты.

Ниже приведен полный полный список переменных, управляющих расположением файлов:

FILE

Путь к .bb файлу, обрабатываемому в данный момент.

FILE_DIRNAME

Путь к директории, содержащей обрабатываемый в данный момент FILE.

            FILE_DIRNAME = "${@os.path.dirname(bb.data.getVar('FILE', d))}"
            

FILESPATH

Базовый набор директорий, доступных для URI file://. Поиск файлов, обозначенного URI file://, ведется в каждой директории в указанном порядке:

FILESPATH = "${FILE_DIRNAME}/${PF}:${FILE_DIRNAME}/${P}:\
${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/files:${FILE_DIRNAME}"
            
FILESDIR

Директория по умолчанию для поиска file:// URI. Используется только когда файл не был найден в FILESPATH. Может быть использована для простого добавления одной дополнительной директории к пути поиска без необходимости изменять стандартный FILESPATH. По умолчанию эта переменная равна первой директории из FILESPATH.

            FILESDIR = "${@bb.which(bb.data.getVar('FILESPATH', d, 1), '.')}" 
            

Иногда рецепты устанавливают свои значения переменных FILESPATH или FILESDIR для изменения стандартного пути поиска патчей и файлов. Чаще всего это делается в том случае, когда один рецепт включает другой, в котором значения по умолчанию будут основаны на имени включающего пакета, а не включаемого, в то время как чаще всего пакеты ожидают, что файлы находятся в директориях с их собственными именами.

Например, m4-native включает рецепт m4. Все настраивается корректно, за исключением того, что m4 рецепт использует файлы и патчи из директории m4, в то время как из-за имени пакета с суффиксом native они будут искаться в m4-native. Поэтому m4-native рецепт устанавливает переменную FILESDIR в значение, ожидаемое m4 (то есть записывается имя той директории, в которой m4 хранит свои файлы):

        include m4_${PV}.bb
        inherit native
        FILESDIR = "${@os.path.dirname(bb.data.getVar('FILE',d,1))}/m4"