Раскладка содержимого#

По умолчанию содержимое deb раскладывается по обычному правилу: usr/bin в bin, usr/lib в lib и так далее. Для расширений, которые монтируются в определённый каталог хоста (например, тулчейны SDK), часто нужно переразложить дерево пакета и доложить свои файлы. Этим управляют секции layout и files манифеста, а для tar-архива - правила --tar-layout.

Правила раскладки#

Секция layout - это список пар источник и назначение. Источник (каталог или файл в извлечённом дереве, например usr/lib/llvm-19) копируется в назначение относительно корня содержимого; пустое назначение означает корень. Правила применяются для источников deb, ссылки и репозитория вместо стандартной раскладки.

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

source:
  type: repository
  repository: { package: clang-19 }
layout:
  - { from: usr/lib/llvm-19,          to: "" }
  - { from: usr/lib/x86_64-linux-gnu, to: lib }
  - { from: usr/lib/clang/19,         to: lib/clang/19 }

Для tar-архива раскладка задаётся правилами --tar-layout вида шаблон=каталог: файлы, подходящие под шаблон, копируются в указанный каталог.

Символьные ссылки при раскладке#

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

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

Удаление битых символьных ссылок#

После уплощения дерева часто остаются символьные ссылки, цель которых не была скопирована. Поле build.pruneBrokenSymlinks (по умолчанию выключено) убирает такие ссылки из содержимого.

build:
  pruneBrokenSymlinks: true

Очистка выполняется сразу после раскладки и до того, как добавляются файлы секции files. Ссылка, цель которой появляется только на шаге files, к моменту очистки ещё битая и будет удалена. Если такие ссылки нужны в расширении, очистку не включают либо приносят ссылку вместе с целью, копируя каталог целиком.

Дополнительные файлы#

Помимо содержимого пакета, в расширение можно доложить свои файлы. Это секция files манифеста.

Записать файл из заданного содержимого - список files.write. У каждой записи поля:

  • path - путь относительно корня содержимого (например, enable.sh).

  • content - содержимое файла.

  • executable - выставить бит исполнения. По умолчанию false.

Скопировать файл или каталог с хоста - список files.copy. У каждой записи поля src (путь на хосте) и dest (путь относительно корня содержимого). Оба поля обязательны.

Каталог и одиночный файл копируются по-разному. Каталог копируется рекурсивно с сохранением символьных ссылок: содержимое src раскладывается внутрь dest, ссылки остаются ссылками. Одиночный файл копируется как файл, и если исходный путь был символьной ссылкой, в расширение попадёт копия её цели под именем ссылки.

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

Существование src проверяется: отсутствующий путь прерывает сборку.

files:
  write:
    - path: enable.sh
      executable: true
      content: |
        export PATH="/usr/lib/sdk/llvm-19/bin${PATH:+:${PATH}}"
        export CC=/usr/lib/sdk/llvm-19/bin/clang
  copy:
    - src: ~/patches/fix.patch
      dest: patches/fix.patch