我正在尝试在 freebsd 上构建一个二进制包。我找到的所有指南基本上都是说使用端口从已安装的软件构建二进制包。我正在寻找一种无需安装端口即可完成此操作的方法。
这可能吗?
我的代码是golang的。因此源代码包含一个由 go 代码和配置文件编译而成的二进制文件。
答案1
可以在此处找到 Packageformat 的文档: https://wiki.freebsd.org/pkgng#Package_format
您不必安装软件来创建包。在端口中进行打包期间,它被安装到临时目录中,然后打包。
答案2
包格式文档(因为 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
are 分别是该项目的网站 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}
(需要最低版本)或只是- `名称:{来源:类别/名称}(对于任何版本)
directories
似乎是包创建的目录。参赛作品的形式为/usr/local/share/foo-1.0: y
;不确定该值的作用 - 卸载时是否要删除该目录?但是,如果没有此条目,包将正常安装(并根据需要创建目录)。
files
:文件及其 SHA256 校验和。不确定当档案中的文件在此处没有条目时会发生什么 - 它根本没有安装,还是它已安装但没有 SHA256 验证?
scripts
是在安装或卸载之前、期间或之后运行的脚本。
+COMPACT_MANIFEST
只是+MANIFEST
省略了一些值。前者用于列出存储库中的包,后者用于进行实际安装。仅使用 a+MANIFEST
但没有安装软件包+COMPACT_MANIFEST
似乎可行,但在尝试将软件包放入官方存储库时可能会产生副作用。
构建一个包
我已经设法拼凑出一个软件包,只需一个简单的 shell 脚本即可安装在 FreeBSD 上。这有一个很好的副作用,我什至不需要 BSD 来构建它,如果没有本机代码,这会派上用场。
最简单的方法是用 YAML 构建一个骨架清单,动态生成并转换所有内容为 JSON files
。flatsize
shell 脚本示例:
FLATSIZE=0
create_files_entry() {
# TODO if the file is a link, just insert '-'
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: unsupported build platform: `uname`"
exit 1
;;
esac
}
echo "files:" > cache/files.yaml
# the second parameter is a transformation to change the file path
add_file path/to/file 's,\./path/to/,/usr/local/foo/,'
# add more files in this manner as needed
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
# create new archive with +MANIFEST (without leading /)
tar -c -f cache/full.tar --transform='s,\./cache/,,' cache/+MANIFEST
tar -A cache/data.tar -f cache/full.tar
# compress and move to destination
xz cache/full.tar
mv cache/full.tar.xz out/$PKGNAME-$PKGVER.pkg
安装
现在可以使用以下命令安装生成的 pkg 文件:
pkg add /path/to/foo-1.2.3.pkg