Создать бинарный пакет без портов?

Вопрос или проблема

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

Это возможно?

Мой код написан на Go. Таким образом, исходный код содержит один бинарный файл, скомпилированный из кода Go, а также файлы конфигурации.

Документацию по формату пакетов можно найти здесь: https://wiki.freebsd.org/pkgng#Package_format

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

Документация по формату пакета (поскольку pkgng стал pkg) теперь находится по адресу https://github.com/freebsd/pkg#pkgfmt.

Файл .pkg по сути является архивом tar, дополнительно сжатым с помощью одного из нескольких стандартных инструментов и с несколькими дополнительными ограничениями.

Во-первых, первые файлы в архиве представляют собой метаданные. Указаны два файла, названные +MANIFEST и +COMPACT_MANIFEST, без пути и без начального /. Эти файлы сопровождаются файлами, которые необходимо установить, каждый из которых имеет полный путь назначения (начиная с /).

Метаданные

+MANIFEST, в соответствии со спецификациями, является файлом в формате UCL, который представляет собой нечто среднее между YAML и JSON. Чистый JSON будет работать (при установке пакета с помощью pkg add blah.pkg) и именно его я обнаружил при изучении пакета из репозитория FreeBSD.

Значения манифеста в значительной степени соответствуют переменным makefile, как описано в https://docs.freebsd.org/en/books/porters-handbook. В частности:

name — это имя, которое вы выбрали для пакета.

version — это версия, соответствующая некоторым конвенциям для определения, какая из двух заданных версий новее.

origin — физическое местоположение пакета в репозитории, в виде category/name, где name идентично значению name. Дополнительные категории могут быть указаны в categories.

comment — это однострочное описание пакета.

arch принимает форму, подобную freebsd:13:x86:64. Шаблонные значения, такие как freebsd:*, работали при установке для пакетов, которые не зависят от конкретной архитектуры и/или версии ОС.

www и maintainer — это URL веб-сайта и адрес электронной почты, соответственно, для проекта.

prefix обычно равен /usr/local, но, похоже, не влияет на время установки, даже если пакет устанавливается в /opt и /etc.

licenselogic: single, если есть только одна лицензия, or, если есть выбор между несколькими.

licenses — это список лицензий, на которые ссылаются такие идентификаторы, как GPLv3+, GPLv2, BSD. См. Руководство портера для подробностей.

flatsize кажется совокупным размером всех установленных файлов. Не на 100% уверен, так как значения немного отличались в пакете, который я изучал, но пакет, который я создал на этом предположении, установился нормально с pkg add.

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

options: не уверен, мой пакет установился нормально без них.

desc — это более длинное (более одного предложения) описание пакета.

categories — это список дополнительных категорий, в которых пакет должен быть указан. Категория из origin кажется повторяется здесь.

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

  • name: {origin: category/name, version: 1.2.3} (обязывающее минимальная версия) или просто
  • name: {origin: category/name} (для любой версии)

directories представляют собой каталоги, созданные пакетом. Записи имеют форму /usr/local/share/foo-1.0: y; не уверен, что значит это значение – должно ли удаляться директория при удалении? Тем не менее, пакет будет установиться нормально (и создать каталоги по мере необходимости) без этой записи.

files: Файлы с их SHA256 контрольной суммой. Не уверен, что происходит, если файл в архиве не имеет записи здесь – устанавливается ли он вообще или устанавливается, но без проверки SHA256?

scripts — это скрипты, которые запускаются до, во время или после установки или удаления.

+COMPACT_MANIFEST — это просто +MANIFEST с опущенными некоторыми значениями. Первое предназначено для перечисления пакета в репозиториях, последнее используется для выполнения самой установки. Установка пакета только с +MANIFEST, но без +COMPACT_MANIFEST, кажется, работает, хотя могут быть побочные эффекты, когда вы пытаетесь добавить пакет в официальный репозиторий.

Сборка пакета

Мне удалось собрать пакет, который устанавливается на FreeBSD всего с помощью простого скрипта оболочки. Это имеет приятный побочный эффект, что мне даже не нужна BSD для его сборки, что удобно, если нет нативного кода.

Легче всего создать скелет манIFEST в формате YAML, генерировать files и flatsize на лету, а затем конвертировать все в JSON.

Образец скрипта оболочки:

FLATSIZE=0

create_files_entry() {
    # TODO если файл является ссылкой, просто вставьте '-'
    sha256sum $1 | sed -E 's,([a-fA-F0-9]*) *(.*),  \2: \1,' | sed $2
}

add_file() {
    [ -d $1 ] && return
    create_files_entry $1 $2 >> $(dirname $0)/cache/files.yaml
    tar -Pr -f $(dirname $0)/cache/data.tar --transform=$2 $1
    case `uname` in
        Linux)
            FLATSIZE=$(( FLATSIZE + $(stat -c %s $1) ))
            ;;
        FreeBSD)
            FLATSIZE=$(( FLATSIZE + $(stat -f %d $1) ))
            ;;
        *)
            echo "ERROR: неподдерживаемая платформа для сборки: `uname`"
            exit 1
            ;;
    esac
}

echo "files:" > cache/files.yaml

# второй параметр - это преобразование, чтобы изменить путь к файлу
add_file path/to/file 's,\./path/to/,/usr/local/foo/,'
# добавьте больше файлов таким образом по мере необходимости

echo "flatsize: $FLATSIZE" >> files.yaml
cat $manifest.yaml $cache/files.yaml | python3 -c 'import sys, yaml, json; print(json.dumps(yaml.safe_load(sys.stdin.read())))' > cache/+MANIFEST
cat cache/+MANIFEST | python3 -c 'import sys, json; manifest = json.loads(sys.stdin.read()); manifest.pop("files", None); manifest.pop("directories", None); manifest.pop("scripts", None); print(json.dumps(manifest))' > cache/+COMPACT_MANIFEST
# создайте новый архив с +MANIFEST и +COMPACT_MANIFEST (без начального /)
tar -c -f cache/full.tar --transform='s,\./cache/,,' cache/+MANIFEST cache/+COMPACT_MANIFEST
tar -A cache/data.tar -f cache/full.tar
# сжать и переместить в конечное место
xz cache/full.tar
mv cache/full.tar.xz out/$PKGNAME-$PKGVER.pkg

Установка

Полученный файл pkg теперь можно установить с помощью:

pkg add /path/to/foo-1.2.3.pkg

Ответ или решение

Создание бинарных пакетов в операционной системе FreeBSD можно осуществить без использования системы портов, что является полезной альтернативой, особенно когда вы разрабатываете программное обеспечение, написанное на языках, таких как Go. В данной статье мы подробно рассмотрим, как можно создать бинарный пакет в формате .pkg, начиная с исходного кода и без установки портов.

Понимание структуры пакета

Бинарный пакет FreeBSD в формате .pkg представляет собой архив tar, который может быть сжат стандартными инструментами. Он включает в себя метаданные и файлы, необходимые для установки. Основные файлы, которые вы должны включить в пакет, это:

  1. +MANIFEST: файл метаданных в формате UCL (похож на YAML или JSON), который содержит информацию о вашем пакете, такую как имя, версия, разрешения и зависимости.
  2. +COMPACT_MANIFEST: сокращенная версия +MANIFEST без некоторых полей, используемая для отображения в репозиториях.

Создание пакета без портов

Для создания пакета без использования системы портов FreeBSD вы можете воспользоваться простым скриптом на Shell. Ниже приведен пример, который поможет вам в этом процессе.

Шаг 1: Определение метаданных

Сначала создадим скелетный файл манифеста. Пример структуры YAML для +MANIFEST может выглядеть следующим образом:

name: my-go-app
version: 1.0.0
origin: mycategory/my-go-app
comment: My Go Application
arch: freebsd:13:x86:64
maintainer: example@example.com
flatsize: 0
files: 

Шаг 2: Сбор файлов

Создайте функцию для генерации записей о файлах и добавления их в архив:

create_files_entry() {
    sha256sum "$1" | sed -E 's,([a-fA-F0-9]*) *(.*),  \2: \1,' | sed "$2"
}

add_file() {
    if [ -d "$1" ]; then return; fi
    create_files_entry "$1" "$2" >> cache/files.yaml
    tar -Pr -f cache/data.tar --transform="$2" "$1"
    FLATSIZE=$(( FLATSIZE + $(stat -f %z "$1") ))
}

Ваша задача – добавить все необходимые файлы с помощью вызова add_file. Пример:

add_file path/to/your/binary 's,./path/to/,/usr/local/bin/,'

Шаг 3: Генерация манифеста

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

cat $manifest.yaml cache/files.yaml | python3 -c 'import sys, yaml, json; print(json.dumps(yaml.safe_load(sys.stdin.read())))' > cache/+MANIFEST
cat cache/+MANIFEST | python3 -c 'import sys, json; manifest = json.loads(sys.stdin.read()); manifest.pop("files", None); print(json.dumps(manifest))' > cache/+COMPACT_MANIFEST

# Создайте новый архив с +MANIFEST и +COMPACT_MANIFEST
tar -c -f cache/full.tar --transform='s,\./cache/,,' cache/+MANIFEST cache/+COMPACT_MANIFEST
tar -A cache/data.tar -f cache/full.tar
xz cache/full.tar
mv cache/full.tar.xz out/my-go-app-1.0.0.pkg

Шаг 4: Установка пакета

Теперь, когда у вас есть пакет my-go-app-1.0.0.pkg, вы можете установить его на любой системе FreeBSD с помощью команды:

pkg add /path/to/my-go-app-1.0.0.pkg

Заключение

Создание бинарного пакета в FreeBSD без использования системы портов совершенно возможно и может быть выполнено с помощью простого скрипта на Shell. Следуя описанным шагам, вы сможете собрать и упаковать ваши приложения, увеличивая гибкость и удобство в развертывании программного обеспечения. Со знанием формата и структуры пакета, вы сможете адаптировать процесс под свои нужды, что позволит вам эффективно управлять своими программными проектами.

Оцените материал
Добавить комментарий

Капча загружается...