资讯详情

Sway 项目清单(Manifest)完整指南:深入解析 Forc.toml 的 `[project]`、依赖、构建配置、补丁与合约依赖

📅 2026/9/12 11:23:50 | 华诺云谱 👁 阅读
Sway 项目清单(Manifest)完整指南:深入解析 Forc.toml 的 `[project]`、依赖、构建配置、补丁与合约依赖
Sway 项目清单Manifest完整指南深入解析 Forc.toml 的[project]、依赖、构建配置、补丁与合约依赖【免费下载链接】sway Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/swayForc.toml是每个 Sway 包package强制要求的清单文件manifest file以 [TOML] 格式编写是 forc 构建工具与 Sway 编译器协作的枢纽它既声明了项目元数据也决定了依赖解析、构建配置、补丁策略与合约间调用关系。本文以 manifest_reference.md 为骨架结合 forc-pkg/src/manifest/mod.rs 与 forc-pkg/src/manifest/build_profile.rs 的源码实现逐节拆解Forc.toml的全部字段、默认值、写法约束与底层行为帮助读者在 Sway 智能合约项目中准确书写和调优自己的清单文件。一、Forc.toml概览一个文件六类配置每个 Sway 包都必须在包根目录下提供Forc.toml清单文件名常量定义于 sway-utils/src/constants.rs。整个文件由以下六个部分构成[project]—— 定义 Sway 项目本身及其元信息[dependencies]—— 声明包依赖[network]—— 指定 forc 交互所连接的网络节点[build-profile.*]—— 自定义编译参数如调试输出选项[patch]—— 用其他副本覆盖依赖来源[contract-dependencies]—— 声明合约依赖供合约/脚本引用其合约 ID。在源码层面这一结构被精确映射为 PackageManifest 结构体除project为必填外network、dependencies、patch、build_profile、contract_dependencies以及build_target、proxy均为可选字段。其中字段通过#[serde(rename_all kebab-case)]统一使用连字符命名风格如implicit-std、build-profile、contract-dependencies这与 TOML 键的书写方式一一对应。值得注意的实现细节解析时 PackageManifest::from_string 使用serde_ignored反序列化任何清单中未被识别的键都会以unused manifest key: path的形式输出警告因此拼写错误的字段名会在编译早期就被提示而非静默忽略。二、[project]段项目元数据与编译入口[project]是清单文件唯一必填的段。一个完整的示例取自文档并对照 sway-lib-std/Forc.toml 的真实写法如下[project] authors [user] entry main.sw description Wallet contract version 1.0.0 homepage https://example.com/ repository https://example.com/ documentation https://example.com/ organization Fuel_Labs license Apache-2.0 name wallet_contract categories [example] keywords [example] experimental { some_feature true, some_other_feature false } [project.metadata] indexing { namespace counter-contract, schema_path out/release/counter-contract-abi.json }2.1 字段清单与可选性字段说明是否可选默认值name项目名称必须通过项目名校验禁止连字符等非法字符必填无license项目许可证必填无entry编译器开始解析的入口文件可选main.swimplicit-std是否隐式把与当前 forc 版本配套的std作为依赖加入可选trueversion项目版本SemVer可选无description项目描述可选无authors作者列表可选无organization所属组织可选无homepage/repository/documentation主页、源码仓库、文档的 URL可选无categories/keywords分类与关键词供索引可选无forc-version项目正常工作所需的最低 forc 版本可选无metadata供外部工具存储配置的元数据见下文可选无experimental编译期间启用/禁用的实验特性开关可选按各特性默认值force-dbg-in-release是否在 release 配置下仍强制生成调试信息可选无对照 Project 结构体 可以看到name字段通过validate_package_name反序列化器校验非法名称会直接导致解析失败entry使用#[serde(default default_entry)]注入main.swforc-version存储为semver::Version。2.2entry入口文件与大型库的推荐写法entry默认指向src/main.sw。源码中 entry_path 与 entry_string 会把清单所在目录与src/目录、entry字段拼接成规范路径并读取内容PackageManifestFile::validate 会校验该文件必须真实存在否则报错。对于大型库文档推荐参考 sway-program-types/libraries.md 中选取入口点的推荐做法例如库通常以lib.sw作为入口并在其中pub mod各子模块而不是把所有内容塞进单个main.sw。仓库中的 sway-lib-std/Forc.toml 即以entry lib.sw作为标准库入口。2.3implicit-std隐式标准库依赖implicit-std控制 forc 是否隐式注入与当前 forc 版本配套的std依赖默认true。源码 implicitly_include_std_if_missing 的逻辑是仅当项目名不是std、且[dependencies]中尚无名为std的条目、且implicit-std不为false时才自动插入一个std依赖。这个隐式依赖的形态可被环境变量定制见 implicit_std_depFORC_IMPLICIT_STD_PATH—— 用本地路径覆盖stdFORC_IMPLICIT_STD_GIT、FORC_IMPLICIT_STD_GIT_TAG、FORC_IMPLICIT_STD_GIT_BRANCH—— 用 Git 源覆盖std默认指向 fuellabs/sway 仓库并以当前forc-pkgcrate 版本vversion作为 tag 固定提交若都不设置则使用与 forc 相同的版本号从注册表拉取std。文档特别强调除非你知道自己在做什么否则请保持默认值。仓库中 examples/counter/Forc.toml 等大多数示例项目都显式写了std { path ../../sway-lib-std }在真实依赖网络中这一机制让“开箱即用”成为可能。2.4experimental实验特性开关experimental是一个键为特性 flag、值为布尔型的表用于在编译期控制 Sway 编译器的实验特性详见 reference/experimental_features.md。三种配置渠道的优先级为环境变量 forc CLI 参数 Forc.toml配置。例如[project] experimental { some_feature true, some_other_feature false }# CLI 方式开启 some_feature关闭 some_other_feature forc build --experimental some_feature --no-experimental some_other_feature # 环境变量方式 FORC_EXPERIMENTALsome_feature,other_feature forc build实验特性还支持在 Sway 源码中通过#[cfg(experimental_feature_flag true/false)]进行条件编译。三、[project.metadata]外部工具与插件的配置空间[project.metadata]为外部工具和插件在Forc.toml中存放各自配置提供了专属空间。元数据键名是任意的不必与工具名一致forc 本身不会解析元数据内容解析工作由各插件自行完成。3.1 工作区级与项目级元数据元数据可定义在两个层级工作区级定义在工作区根Forc.toml[workspace.metadata] my_tool { shared_setting value }项目级定义在单个项目的Forc.toml[project.metadata.any_name_here] option1 value option2 value [project.metadata.my_custom_config] setting1 value setting2 value一个面向索引工具的真实示例[project.metadata.indexing] namespace counter-contract schema_path out/release/counter-contract-abi.json3.2 插件开发者最佳实践与实现说明文档给出的插件开发建议包括选择清晰、描述性的元数据键名并在工具文档中写明其期望的确切键名若工具没有Forc.toml也能工作则不要强制要求它存在可考虑使用独立的 TOML 配置文件承载复杂配置明确工具如何处理工作区级与项目级元数据的关系。实现层面的要点元数据段完全可选forc 不解析其内容当工作区与项目同时存在元数据时项目级应优先于工作区级工具可选择合并两者并应文档化自身的继承行为。从源码看Project.metadata的类型是Optiontoml::Valuemanifest/mod.rsWorkspace.metadata同理印证了“forc 只负责承载、不负责解释”的设计。四、[dependencies]段四种来源与三种引用方式[dependencies]声明包依赖。forc 的依赖管理系统支持path、git、ipfs与社区registryforc.pub四种来源详见 forc/dependencies.md。每个依赖项可提供的字段如下字段说明version期望的依赖版本namespace与指定注册表源关联的命名空间可选path本地依赖路径git托管依赖的 Git 仓库 URLbranch从 Git 仓库拉取的期望分支tag从 Git 仓库拉取的期望标签rev期望的提交哈希引用依赖可写成两种形式简单形式foo 0.1.0等价于详细形式foo { version 0.1.0 }。源码中的 Dependency 枚举 用#[serde(untagged)]同时接纳这两种写法。4.1 依赖字段的合法性校验源码级DependencyDetails::validate 对依赖声明做了严格的组合校验违反会直接报错branch、tag或rev必须在git存在时才能使用“Details reserved for git sources used without a git field”同一 Git 依赖不能同时指定branch、tag、rev中的任意两项version不能与git、ipfs、path同时出现namespace只能用于带version的源。仓库测试 manifest/mod.rs 的测试模块 逐项验证了这些非法组合例如version_and_git_same_dep、version_and_ipfs_same_dep、namespace_without_version等测试用例目录均位于 forc-pkg/tests/invalid。4.2 使用forc add/forc remove管理依赖除了手写Forc.toml还可以用 CLI 管理依赖命令文档见 forc/commands/forc_add.md 与 forc/commands/forc_remove.md# Git 分支依赖 forc add custom_lib --git https://github.com/FuelLabs/custom_lib --branch master # 本地路径依赖 forc add custom_lib --path ../custom_lib # IPFS 依赖 forc add custom_lib --ipfs QmYwAPJzv5CZsnA... # 注册表依赖forc.pub forc add custom_lib0.0.1 # 合约依赖 forc add my_contract --git https://github.com/example/contract --contract-dep # 移除依赖 forc remove custom_lib forc remove my_contract --contract-dep注意目前尚不支持注册表源的离线模式也暂不支持通配符custom_lib *与 caretcustom_lib ^0.1版本声明。五、[network]段forc 交互的网络节点[network]段只有一个可选字段url—— 网络节点 URL默认http://127.0.0.1:4000。源码中该默认值由 default_url 提供实际取sway_utils::constants::DEFAULT_NODE_URL。对本地开发而言直接省略该段即可。六、[build-profile.*]段自定义编译输出选项[build-profile]表用于定制编译器设置如各类调试输出。每个清单文件内置两个默认 profiledebug默认与release可通过在清单中显式书写同名 profile 覆盖默认行为。6.1 全部可用字段字段说明默认值print-ast是否打印生成的 ASTfalseprint-dca-graph是否打印计算出的死代码分析DCA图GraphViz DOT 格式为空字符串时输出到 stdoutfalseprint-dca-graph-url-format生成的 DOT 文件中使用的 URL 格式如 VS Code 的vscode://file/{path}:{line}:{col}无print-ir是否打印生成的 Sway IRfalseprint-asm是否打印生成的汇编falseterse精简模式限制警告与错误输出falsetime_phases是否输出编译各阶段耗时falseinclude_tests是否在解析、类型检查与代码生成中包含测试函数forc test会置为truefalseerror_on_warnings是否将警告视为错误falsebacktracepanic 回溯中包含的 panic 函数范围取值all、all_except_never、only_always、noneall_except_neverdebug/only_alwaysrelease从 BuildProfile 结构体 可以看到除文档列出的字段外还包含print-bytecode、print-bytecode-spans、profile、metrics-outfile、reverse-results、optimization-level、dump等字段其中print-ir与print-asm的类型分别是IrCli与PrintAsm结构支持细粒度控制详见下文示例。print-asm的可选值组合virtual含虚拟寄存器与抽象控制流的初始汇编、allocated完成寄存器分配但仍是抽象控制流的汇编、final最终序列化为目标 VM 字节码的汇编。print-ir的可选值组合initial优化前的初始 IR、final所有优化 pass 之后的最终 IR、pass name打印指定优化 pass 之后的 IR 状态、modified仅当 pass 修改了 IR 时才打印、print-md同时打印 IR 元数据。backtrace的详细语义可参见 basics/error_handling.md 的 Irrecoverable Errors 一节。6.2 覆盖默认 profile 的完整示例[project] authors [user] entry main.sw organization Fuel_Labs license Apache-2.0 name wallet_contract [build-profile.debug] print-asm { virtual false, allocated false, final true } print-ir { initial false, final true, modified false, passes []} terse false [build-profile.release] print-asm { virtual true, allocated false, final true } print-ir { initial true, final false, modified true, passes [dce, sroa]} terse true源码 implicitly_include_default_build_profiles_if_missing 保证即使清单里没有写[build-profile]debug与release也会被自动补全默认实现见 BuildProfile::debug 与 BuildProfile::releasedebug 默认Opt0优化级别、AllExceptNever回溯release 默认Opt1优化级别、OnlyAlways回溯。6.3 如何选择 profileforc build默认使用debugforc build --release使用release自定义 profile 通过forc build --build-profile profile name选择。CLI 定义位于 forc/src/cli/shared.rs--build-profile与--release互斥conflicts_with--release只是将 profile 名设为release的快捷方式。相关命令文档可参考 forc/commands/forc_build.md。6.4 CLI 选项覆盖 profile 的优先级给定时应的 CLI 选项如--asm、--ir会覆盖所选 build profile 的对应设置。例如同时传--release与--asm all则release被覆盖实际生效的 profile 结构如下print-ast false print-ir { initial false, final false, modified false, passes []} print-asm { virtual true, allocated true, final true } terse false time-phases false include-tests false error-on-warnings false experimental-private-modules false七、[patch]段覆盖依赖来源[patch]用于将依赖覆盖为其他副本适合测试本地改动、使用未发布特性或调试依赖。每个[patch]之后的键必须加引号如[patch.forc.pub]因为其中包含点号等特殊字符不加引号 TOML 会把点解释为嵌套表。7.1 覆盖 Git 依赖用同一仓库的test分支覆盖std[project] authors [user] entry main.sw organization Fuel_Labs license Apache-2.0 name wallet_contract [dependencies] [patch.https://github.com/fuellabs/sway] std { git https://github.com/fuellabs/sway, branch test }也可用本地路径版本覆盖 Git 依赖[patch.https://github.com/fuellabs/sway] std { path /path/to/local_std_version }还可以覆盖以 Git 仓库声明的普通依赖[project] authors [user] entry main.sw organization Fuel_Labs license Apache-2.0 name wallet_contract [dependencies] foo { git https://github.com/foo/foo, branch master } [patch.https://github.com/foo] foo { git https://github.com/foo/foo, branch test }7.2 覆盖注册表forc.pub依赖以本地路径覆盖注册表依赖适合测试对std或其他注册表包的本地改动[project] authors [user] entry main.sw license Apache-2.0 name my_contract [dependencies] std 0.70.1 [patch.forc.pub] std { path ../sway/sway-lib-std }上例中虽然std0.70.1 原本应从注册表拉取但实际会使用本地路径版本。也可以用 Git 仓库覆盖注册表依赖[dependencies] std 0.70.1 [patch.forc.pub] std { git https://github.com/fuellabs/sway, branch my-feature }7.3 两个重要注意事项引号是必须的[patch.forc.pub]这类键必须加引号否则 TOML 会把点号当作嵌套表分隔符。来源匹配Git 补丁匹配 Git 依赖注册表补丁匹配注册表依赖。从源码看patch 以PatchMap BTreeMapString, Dependency形式存储manifest/mod.rs当包属于某个工作区时resolve_patches 会忽略包自身的[patch]并打印 “Patch for the non root package will be ignored.” 警告改用工作区根清单中的补丁工作区 patch 用法详见 forc/workspaces.md。八、[contract-dependencies]段以合约 ID 为依赖[contract-dependencies]表用于声明 Sway 合约或脚本的合约依赖——即我们的合约/脚本可能交互的那些合约。声明后无需在每次新版本部署时手动更新合约 IDforc 会像处理普通库依赖一样固定pin并更新合约依赖。8.1 工作原理[contract-dependencies]下的合约与普通[dependencies]一样会被构建并固定版本区别在于不会导入每个合约依赖的完整公共命名空间而是把各自的合约 ID 作为CONTRACT_ID常量通过该合约依赖包的命名空间根暴露。这意味着可以在 Sway 代码中像使用该合约依赖包根部的pub const一样引用其 ID。声明方式与[dependencies]相同可指向path或git来源但条目必须指向合约否则报错。示例清单[project] authors [user] entry main.sw organization Fuel_Labs license Apache-2.0 name wallet_contract [contract-dependencies] foo { path ../foo }示例用法script; fn main() { let foo_id foo::CONTRACT_ID; }8.2salt确定性合约 ID 下的碰撞规避合约 ID 是确定性地计算出来的重新构建同一合约总会得到相同 ID而链上不允许两个相同 ID 的合约同时部署因此需要salt因子来修改合约 ID[contract-dependencies] foo { path ../foo, salt 0x1000000000000000000000000000000000000000000000000000000000000000 }未指定salt的合约依赖会隐式使用全零salt。源码中的 ContractDependency 结构体 通过default_hex_salt注入Salt::default()并通过 HexSalt 的 FromStr 要求salt值必须以0x开头。在编译管线中合约依赖的 ID 由 dependency_namespace 结合编译出的字节码、存储槽与 salt 计算得到DepKind::Contract { salt }分支随后通过package_with_contract_id把CONTRACT_ID常量注入命名空间forc check场景下则使用占位值。仓库中的 multi_contract_calls 与 upgradeable_proxy 示例展示了多合约调用的实际工程形态。九、与工作区、锁文件的协同理解Forc.toml还需要知道它与工作区的关系详见 forc/workspaces.md工作区由根Forc.toml中的[workspace]段声明members列出各成员包的相对路径工作区成员共享根目录的Forc.lock见 lock_path 对工作区锁文件位置的解析工作区级也可定义[patch]用于统一覆盖所有成员依赖图ManifestFile在解析时会自动区分包清单与工作区清单from_dir。支持工作区的常用命令包括forc build、forc deploy、forc run、forc check、forc update、forc clean、forc fmt等。十、从零开始的参考实践forc new/forc init生成的默认清单模板forc/src/utils/defaults.rs是一个很好的起点[project] authors [你的用户名] entry main.sw license Apache-2.0 name project_name [dependencies]作者名取自系统用户名可通过环境变量FORC_INIT_MANIFEST_AUTHOR覆盖仓库根 examples 下的大量示例项目如 counter/Forc.toml、wallet_smart_contract都是这种最小化结构的真实写照。构建时forc build会读取清单、解析依赖、依据[build-profile]配置执行编译并把锁文件写入Forc.lock。综上Forc.toml看似只是一个 TOML 文件实际承载了 Sway 工程化的大部分核心决策元数据、依赖来源与固定、编译输出控制、依赖覆盖以及跨合约集成。把握住本文梳理的字段语义、默认值与源码级校验规则即可写出既符合规范又贴合工程需求的清单配置。【免费下载链接】sway Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。