Sway 依赖管理实战:forc add 命令详解与 Forc.toml 写入机制
2026/9/12 7:52:02 网站建设 项目流程

Sway 依赖管理实战:forc add 命令详解与 Forc.toml 写入机制

【免费下载链接】sway🌴 Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway

在 Sway 项目(基于 Forc 工具链)中,管理Forc.toml清单文件里的依赖最标准的方式就是forc add命令:它一次性把版本依赖、本地路径依赖、Git 依赖或 IPFS 依赖写入清单的[dependencies][contract-dependencies]区段,并同步更新Forc.lock。读完后你能掌握forc add的完整参数用法、依赖来源的合法性校验规则,以及从源码层面理解它如何安全地修改清单文件(包括 dry-run 与失败回滚机制),从而在真实项目中可靠地完成依赖管理。

命令用法与参数

forc add的官方用法为:

forc add [OPTIONS] <DEP_SPEC>...

其中位置参数<DEP_SPEC>支持同时添加多个依赖,每个依赖的格式为name[@version],例如custom_lib@0.1.0custom_contract。源码中该参数被定义为可接受 1 到多个值的字符串向量(见 add.rs 中dependencies: Vec<String>的声明),版本部分在解析阶段会做 semver 校验,非法版本(如foo@not-a-version)会直接报错invalid version requirement

完整选项如下:

选项说明
--path <PATH>添加本地路径依赖
--git <URI>添加 Git 来源依赖
--branch <branch>Git 分支(须与--git组合)
--tag <tag>Git 标签(须与--git组合)
--rev <rev>Git 修订号(须与--git组合)
--ipfs <CID>添加 IPFS 来源依赖
--contract-dep写入[contract-dependencies]区段而非[dependencies]
--salt <SALT>合约部署用盐值(仅对合约依赖生效)
--package <SPEC>在 workspace 中指定要修改的具体包
--manifest-path <PATH>指定Forc.toml的路径
--dry-run只展示将发生的变更,不写入文件
--offline不获取任何远程依赖
--ipfs-node <FUEL\|PUBLIC\|LOCAL\|URL>拉取 IPFS 来源依赖时使用的 IPFS 节点

从 CLI 参数定义看(shared.rs),这些选项被组织成四个共享参数组,且带有严格的互斥约束:

  • Source 组SourceArgs):pathgitipfs三者构成一个 clap 互斥组,即同一条命令里三种来源只能选其一;
  • Git 引号组GitRef):branchtagrev三者互斥(multiple(false)),并且必须要求同时给出git.requires("git"))。这意味着forc add mylib --branch main(缺少--git)在命令行解析阶段就会被拒绝。

官方帮助信息中给出的典型示例(同样定义在 add.rs 的cli_examples宏里):

# 添加一个版本依赖 forc add <DEP>[@<VERSION>] # 添加一个合约依赖 forc add <DEP>[@<VERSION>] --contract-dep # 预演(不实际写入) forc add <DEP>[@<VERSION>] --dry-run

依赖来源的解析规则

forc add接收参数后,会将其转换为内部结构ModifyOpts(dep_modifier.rs),并调用dep_modifier::modify_dependencies执行实际修改。每个<DEP_SPEC>先被解析为DepSpec { name, version_req }:按第一个@切分,名称在前、版本要求在后;空字符串会被拒绝(Dependency spec cannot be empty)。

随后,resolve_dependency依据“命令行来源参数 + 版本要求”的组合决定最终写入清单的依赖形态,核心逻辑如下:

  1. 只给了版本号(如mylib@1.0.0):写入简单的Dependency::Simple(version),在清单中表现为mylib = "1.0.0"
  2. 给了来源参数--path/--git/--ipfs):写入Dependency::Detailed(details),清单中表现为内联表(inline table);
  3. 两者都没给:如果该包名恰好是当前 workspace 的同级成员(sibling),则自动推导相对路径写成路径依赖(例如../pkg1);否则报错dependency ... source not specified. Please specify a source (e.g., git, path) or version。源码中此处还留有注释,表明 registry(如 forc.pub)的集成是后续计划。

写入前,DependencyDetails::validate()(manifest/mod.rs)会执行合法性校验,以下是实际会触发的错误规则:

非法组合报错信息
branch/tag/rev但没有gitDetails reserved for git sources used without a git field
branchtagrev三者同时给出Cannot specifybranch,tag, andrevtogether for dependency with a Git source
branchtag同时给出Cannot specify bothbranchandtagfor dependency with a Git source
revtag同时给出Cannot specify bothrevandtagfor dependency with a Git source
branchrev同时给出Cannot specify bothbranchandrevfor dependency with a Git source
versiongit同时存在Both version and git details provided for same dependency
versionipfs同时存在Both version and ipfs details provided for same dependency
versionpath同时存在Both version and path details provided for same dependency
namespace存在但无versionNamespace can only be specified for sources with version

这些规则在 dep_modifier.rs 的测试模块(test_resolve_dependency_detailed_variant_failure等)中都有对应的单元测试覆盖,是验证上述行为的直接依据。

值得注意的一个细节:Git 来源的字段会按原样写入清单内联表,其中 IPFS CID 写入的键名是cid(见generate_table函数:inline.insert("cid", ...)),而 CLI 参数名是--ipfs,两者不要混淆。

合约依赖:--contract-dep 与 --salt

当依赖的是合约(contract)时,需要用--contract-dep将依赖写入[contract-dependencies]区段而不是[dependencies]。该命令的实现会额外处理salt(盐值)

  • salt 用于合约部署时计算确定性的合约 ID;
  • 提供--salt时,值必须以0x开头的十六进制字符串(HexSalt::from_str会先剥离0x前缀再解析,见 manifest/mod.rs 中HexSaltFromStr实现),非法格式会报Invalid salt format
  • 未提供 salt 时,使用fuel_tx::Salt::default()作为默认盐值。

写入清单后,合约依赖的条目形如:

[contract-dependencies] some_contract = { version = "1.0.0", salt = "0x2222222222222222222222222222222222222222222222222222222222222222" }

仓库中的真实示例可以参考 multi_contract_calls/caller/Forc.toml,其中就包含[contract-dependencies]区段,演示了调用方合约依赖被调用方合约的写法。关于 salt 与合约 ID 的对应关系,可结合 forc contract-id 命令文档 进一步查看。

workspace 支持:--package 与同级包自动推导

当在 workspace 根目录(Forc.toml[workspace]清单)执行forc add时,resolve_package_path无法确定要修改哪个成员,因此必须提供--package <SPEC>,否则会报错并列出所有可用成员:

`forc add` could not determine which package to modify. Use --package. Available: pkg1, pkg2

如果--package指定的包名不存在,则报package(s) <name> not found in workspace <root>。这些行为在 dep_modifier.rs 的测试(test_resolve_package_path_workspace_package_not_settest_resolve_package_path_workspace_package_not_found)中被逐条验证。

另一个实用能力是workspace 同级包自动推导:当依赖名与某个 workspace 成员同名、且未显式指定来源和版本时,forc add会自动将其解析为相对路径依赖。例如 workspace 下有pkg1pkg2,执行forc add pkg1 --package pkg2会写入:

[dependencies] pkg1 = { path = "../pkg1" }

(相对路径以两个包的共同父目录为基准计算,见resolve_dependencystrip_prefix的处理;对应测试为test_resolve_dependency_from_workspace_sibling。)同时,命令会阻止包依赖自身——若目标包与当前包同名同目录,报错cannot add ... as a dependency to itself

--manifest-path、--dry-run 与 --offline

--manifest-path:直接指定Forc.toml路径。若未提供,则从当前工作目录向上定位清单文件(ManifestFile::from_dir(cwd))。

--dry-run:实现上分两步。首先正常完成清单修改与构建计划(build plan)计算,确认依赖解析无误后,把清单内容回写为修改前的备份,并输出Dry run enabled. toml file not modified.日志(dep_modifier.rs 中modify_dependenciesopts.dry_run分支)。因此在 dry-run 模式下,清单文件最终保持原样,其价值在于先验证依赖能否被成功解析,再执行正式写入。

--offline:禁止在依赖管理过程中访问网络,只使用已下载的依赖缓存。该标志会透传给构建计划生成(BuildPlan::from_lock_and_manifests),在离线环境或 CI 场景中保证行为可复现。

清单写入与失败回滚机制

forc addForc.toml的修改并非简单的字符串拼接,而是基于toml_editDocumentMut解析-修改-序列化流程(dep_modifier.rs 中modify_dependencies函数),这样能保留原有注释与格式。其完整流程为:

  1. 读取目标包的Forc.toml,解析为 TOML 文档,并保存一份备份(backup_doc);
  2. 加载旧Forc.lock
  3. 按区段(dependenciescontract-dependencies)逐条插入新依赖——Section::add_deps_manifest_table会先确保区段表存在,简单版本依赖写成字符串值,详细依赖写成内联表;
  4. 写回文件后,基于新清单重建构建计划并刷新 lock 文件;
  5. 若构建计划重建失败(例如远程依赖拉不下来),自动将清单恢复为备份内容,并以失败退出——保证不会留下一个无法构建的Forc.toml

这套“写入-校验-回滚”机制意味着:只要你执行forc add后看到命令成功返回,清单与 lock 文件就是自洽可用的;反之任何解析或获取失败都不会污染你的清单文件。

相关命令与延伸阅读

  • forc remove:与forc add共享同一套dep_modifier实现(Action::Remove),负责从[dependencies][contract-dependencies]移除依赖,参数风格一致,参见 forc remove 文档;
  • forc build:添加依赖后用于编译验证,参见 forc build 文档;
  • forc update:刷新 lock 文件中的依赖版本,参见 forc update 文档;
  • 更底层的清单结构与来源获取逻辑,可查看 forc-pkg/src/manifest/mod.rs(DependencyDependencyDetailsContractDependency定义)与 forc-pkg/src/source/mod.rs(IPFSNodeFUEL/PUBLIC/LOCAL/自定义 URL 解析)。

小结

forc add以“位置参数 + 来源选项”的组合覆盖了版本、本地路径、Git、IPFS 四类依赖来源,并通过--contract-dep/--salt支持合约依赖、通过--package精确操作 workspace 成员。理解其背后的解析校验规则(版本与来源互斥、Git 引用互斥)和“写入-校验-回滚”的清单处理流程,能帮助你在自动化脚本与 CI 中安全地管理 Sway 项目依赖;配合--dry-run预演与--offline离线模式,可在不触碰现有工程文件的前提下验证依赖变更的正确性。

【免费下载链接】sway🌴 Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询