
开发工具CLI【免费下载链接】PyOxidizerA modern Python application packaging and distribution tool项目地址https://gitcode.com/gh_mirrors/py/PyOxidizer点击查看免费下载导读本文讲解 TuggerPyOxidizer 项目中的应用打包工具Starlark 方言中面向 Snapcraft 打包的核心类型——Snap。Snap是一个整个snapcraft.yaml文件的对象模型在 Starlark 脚本里创建并填充该类型的实例最终序列化为标准snapcraft.yaml再由配套的SnapcraftBuilder调用snapcraft命令产出.snap安装包。读完本文你将掌握Snap的全部顶层属性及其取值约束、与SnapApp/SnapPart的嵌套组合方式以及如何通过to_builder()串联文件清单、命令调用完成一次真实的 snap 构建。Snap类型在 Tugger 中的定位Tugger 使用 StarlarkPython 子集文件配置运行行为并定义了面向自身领域的类型与函数方言见 tugger/docs/tugger_starlark.rst。其中Snap就是该方言中与 Snapcraft 打包相关的三种类型之一Snap代表整个snapcraft.yaml文件本文章主角SnapApp代表apps.app-name条目见 tugger/docs/tugger_starlark_type_snap_app.rstSnapPart代表parts.part-name条目见 tugger/docs/tugger_starlark_type_snap_part.rst。类型与函数在全局环境中的注册见 tugger/docs/tugger_starlark_globals.rst其底层实现位于 tugger/src/starlark/snapcraft.rs。而支撑这些 Starlark 类型的 Rust 数据模型与构建器来自独立的tugger-snapcraftcratetugger-snapcraft/src/lib.rs、tugger-snapcraft/README.md该 crate 既服务 Tugger也可供其他工具复用。Snap实例暴露的属性与snapcraft.yaml中的键一一对应。需要特别注意的是当前这些属性是只写write only的即只允许赋值不支持读取这与SnapApp、SnapPart一致。创建与初始化Snap(name, version, summary, description)Snap的构造函数要求四个必填参数它们对应snapcraft.yaml中的四个顶层必填键参数对应snapcraft.yaml键说明namenamesnap 名称全局唯一versionversion版本号summarysummary一句话简介descriptiondescription详细描述snap Snap( myapp, 0.1.0, A short summary of myapp, A longer, more detailed description of myapp., )从源码看构造逻辑由SnapValue::new_from_args完成它会调用Snapcraft::new(name, version, summary, description)创建内部数据模型并以ArcMutexSnapcraft包装供后续属性写入tugger/src/starlark/snapcraft.rs。name、version、summary、description这四个字段在底层结构体 tugger-snapcraft/src/yaml.rs 中是必填的Cowstr不会被序列化器跳过。顶层属性完整的snapcraft.yaml键覆盖除四个必填参数外Snap还暴露了如下可选属性每个都对应snapcraft.yaml的一个顶层键。下表综合了 tugger/docs/tugger_starlark_type_snap.rst 的签名与底层结构体定义属性类型对应 YAML 键说明titleOptional[str]title展示用标题baseOptional[str]base基础系统镜像如core18、core20snap_typeOptional[str]typesnap 类型gadget、kernel、baseconfinementOptional[str]confinement沙箱级别strict、devmode、classiciconOptional[str]icon图标文件licenseOptional[str]licenseSPDX 许可证标识gradeOptional[str]grade发布级别devel、stableadopt_infoOptional[str]adopt-info从某部分part收养版本等元信息architecturesOptional[dict]architectures{build_on: [...], run_on: [...]}形式assumesOptional[list[str]]assumes声明依赖的 snapd 特性passthroughOptional[dict[str, str]]透传任意自定义键值对原样写入appsOptional[dict[str, SnapApp]]apps应用条目集合partsOptional[dict[str, SnapPart]]parts构建部分集合plugsOptional[dict]plugs接口声明slotsOptional[dict]slots接口槽位声明说明snapcraft.yaml中type是关键字因此底层结构体使用snap_type字段并通过#[serde(rename type)]在序列化时写回type键tugger-snapcraft/src/yaml.rsStarlark 层同样以snap.type赋值。关键属性的取值约束以源码为准Snap的属性赋值并非任意字符串Starlark 层会把字符串解析为强类型枚举非法值会抛出带TUGGER_SNAPCRAFT错误码的运行时错误。以底层枚举定义tugger-snapcraft/src/yaml.rs为准snap.typegadget、kernel、baseconfinementstrict、devmode、classicgradedevel、stablearchitectures必须是dict且至少给出build_on键可选的run_on省略时不序列化。可用架构枚举all、s390x、ppc64el、arm64、armhf、amd64、i386。该解析逻辑在value_to_optional_architectures中实现tugger/src/starlark/snapcraft.rs。写只读语义与None删除语义Snap当前只支持写入属性TypedValue::set_attr针对每个属性执行类型转换后写入内部Snapcraft结构体tugger/src/starlark/snapcraft.rs。把某个可选属性赋值为None会将该键从序列化结果中整体移除。这一语义在底层由 serde 的#[serde(skip_serializing_if Option::is_none)]保证tugger-snapcraft/src/yaml.rs。因此你可以放心地在配置分支中先设置属性、再视情况清空它。嵌套组合apps与partsapps与parts的值必须是字符串键 → 对象值的 dict且对象值分别必须是SnapApp/SnapPart实例——Starlark 层在value_to_apps/value_to_parts中会做downcast_ref强类型校验传入其他类型会报错tugger/src/starlark/snapcraft.rs。用SnapApp定义应用入口SnapApp()不接受参数创建空实例后通过属性赋值填充apps.name条目见 tugger/docs/tugger_starlark_type_snap_app.rst。其属性与apps.name键对应command、command_chain、autostart、daemonsimple/oneshot/forking/notify、restart_conditionon-failure/on-success/on-abnormal/on-abort/always/never、stop_command、post_stop_command、stop_timeout、timer、adapternone/full、desktop、environment、extensions、plugs、slots、socket、socket_mode、listen_stream、common_id、passthrough。用SnapPart定义构建部分SnapPart()同样无参数、属性只写见 tugger/docs/tugger_starlark_type_snap_part.rst。其属性覆盖parts.name的常见键plugin、source、source_typebzr/deb/git/hg/local/mercurial/rpm/subversion/svn/tar/zip/7z、source_checksum、source_branch、source_commit、source_tag、source_subdir、source_depth、after、build_packages、build_snaps、stage_packages、stage_snaps、stage、prime、organize、filesets、build_environment、build_attributesdebug/keep-execstack/no-patchelf/enable-patchelf/no-install、parse_info、override_pull、override_stage、override_build、override_prime。提示adapter、daemon、restart_condition、source_type、build_attributes等同样经过枚举解析字符串必须与上述取值精确匹配。完整示例# 顶层配置 snap Snap(myapp, 0.1.0, myapp summary, myapp description) snap.base core20 snap.confinement classic snap.grade stable snap.architectures {build_on: [amd64], run_on: [amd64]} # 应用入口 app SnapApp() app.command bin/myapp app.plugs [network, home] snap.apps {myapp: app} # 构建部分 part SnapPart() part.plugin nil part.source . part.build_environment [ {PATH: ${HOME}/.cargo/bin:${PATH}}, ] part.override_build ( cargo install --path . --root ${SNAPCRAFT_PART_INSTALL} --force ) snap.parts {myapp: part}该示例的形态与tugger-snapcraft中集成测试test_build_rust_project构造的 Rust 项目 snap 配置一致tugger-snapcraft/src/builder.rs可作为实战参照。序列化Starlark 对象 →snapcraft.yamlSnap实例本质上是对 tugger-snapcraft/src/yaml.rs 中Snapcraft结构体的可变包装。序列化时结构体统一使用#[serde(rename_all kebab-case)]即 Rust 字段名自动转为snapcraft.yaml习惯的连字符风格adopt_info→adopt-info、post_stop_command→post-stop-command等所有可选字段带skip_serializing_if Option::is_none未设置即不输出列表/字典字段带skip_serializing_if Vec::is_empty/HashMap::is_empty为空即不输出。因此你写入什么snapcraft.yaml里就是什么——这正是属性与snapcraft.yaml键一一对应的底层保证。to_builder()衔接snapcraft命令执行Snap上唯一的方法是builder snap.to_builder()它不接受参数等价于SnapcraftBuilder(snap)返回一个SnapcraftBuilder实例tugger/docs/tugger_starlark_type_snapcraft_builder.rst。源码实现会克隆当前Snap内部状态并包装进构建器tugger/src/starlark/snapcraft.rs因此转换之后对snap的进一步修改不会影响 builder。SnapcraftBuilder提供三个方法方法作用add_invocation(args, purge_build)注册一次snapcraft命令调用。args是传给snapcraft可执行文件的参数列表purge_build为Optional[bool]指定是否在本次调用前清空构建目录。不指定时第一次注册的调用会清空构建目录后续调用不清空add_file_manifest(manifest)注册一个FileManifest构建时其内容会被物化到snapcraft.yaml所在目录旁用于向构建环境投放文件build(target)依次执行所有注册的调用真正运行snapcraft。target是构建目标名返回一个ResolvedTarget且该目标不可运行仅表示构建产物builder snap.to_builder() # 注册文件清单把项目文件放进构建环境 manifest FileManifest() # ... 向 manifest 添加文件 ... builder.add_file_manifest(manifest) # 注册 snapcraft 调用首次调用默认会 purge 构建目录 builder.add_invocation([snap, --destructive-mode, --debug, -o, myapp_0.1.0_amd64.snap]) # 执行构建 builder.build(snap-build)从 tugger-snapcraft/src/builder.rs 的实现看每次调用build_invocation时依次执行四个步骤若purge_build为真且构建目录已存在删除整个构建目录把FileManifest中注册的文件物化到构建目录将内部Snapcraft结构体序列化写入构建目录/snap/snapcraft.yaml在构建目录下以cmd(snapcraft, args)方式调用snapcraft逐行转发其输出根据退出码判断成败。也就是说SnapcraftBuilder是稍有主见的低层snapcraft封装它负责把snapcraft.yaml和伴随文件摆好位置然后原样把命令交给系统snapcraft执行。构建环境需要预先安装snapcraft工具Linux 下可借助--destructive-mode在宿主环境直接构建。源码与测试佐证Starlark 层测试直接验证了Snap、SnapApp、SnapPart的属性写入与to_builder()行为见 tugger/src/starlark/snapcraft.rstest_snap_basic完整演练Snap的全部属性赋值含architectures {build_on: [s390x, arm64], run_on: [i386, amd64]}、confinement classic、grade stable、type kernel等并断言snap.to_builder()返回SnapcraftBuilder类型test_app_basic/test_part_basic逐项验证SnapApp/SnapPart每个属性的解析结果test_snapcraft_builder_add_invocation验证add_invocation的purge_build默认行为——第一条调用默认true显式指定后按给定值记录test_build_rust_project位于 tugger-snapcraft/src/builder.rs在 Linux 上真实调用snapcraft构建一个 Rust 二进制项目并断言产物存在。与其他 Tugger 文档的关系Snap只是 Tugger Starlark 方言中面向 Snapcraft 的一环配套内容还包括SnapApp 类型参考SnapPart 类型参考SnapcraftBuilder 类型参考Tugger Starlark 方言总览Tugger 全局类型与函数Tugger 总览其中介绍了tugger-snapcraft在 Tugger 体系中的职责小结Snap是 Tugger 以代码方式描述snapcraft.yaml的入口对象构造时锁定四个必填字段随后通过只写属性逐键补齐顶层配置用SnapApp/SnapPart组织应用入口与构建部分最后以to_builder()将完整配置与文件清单、snapcraft命令调用绑定一键产出.snap包。理解其属性即 YAML 键、None即删除、字符串经枚举校验三条核心语义即可在 Tugger 的 Starlark 脚本中可靠地驱动 Snapcraft 打包流程。赞分享开发工具CLI【免费下载链接】PyOxidizerA modern Python application packaging and distribution tool项目地址https://gitcode.com/gh_mirrors/py/PyOxidizer点击查看免费下载相关推荐GSYVideoPlayer 外挂字幕快速上手三步跑通SRT 与 WebVTT 通吃任意内核GSYVideoPlayer 外挂字幕快速上手三步跑通SRT 与 WebVTT 通吃任意内核 GSYVideoPlayer 的外挂字幕把加载、解析、渲染都挂开发工具CLISeaweedFS Snap 打包实战基于 snapcraft.yaml 从本地构建到 Snap Store 发布SeaweedFS Snap 打包实战基于 snapcraft.yaml 从本地构建到 Snap Store 发布 导读 本文以仓库中 snap/README分布式文件系统对象存储存储OCaml中的类型驱动代码生成ppx_deriving完全指南OCaml中的类型驱动代码生成ppx_deriving完全指南 1. 项目介绍 ppx_deriving 是一个专为 OCaml 设计的类型驱动代码生成库它上一篇rough-notation注释定位算法如何精准标注页面元素下一篇oomd 监控指标详解如何解读内存压力、交换使用率和IO成本创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考