0.3.2 |
|
---|---|
0.3.1 |
|
0.2.1 |
|
0.1.6 |
|
0.1.4 |
|
#63 in #resolution
52 个月下载量
用于 120 个crate (8 直接)
140KB
3K SLoC
id: move-package title: Move Package custom_edit_url: https://github.com/move-language/move/edit/main/language/tools/move-package/README.md
摘要
Move包crate包含了解析、解析和构建Move包的逻辑。它旨在作为库使用,既可以用于构建包(例如,通过Move CLI),也可以用于其他可能处理Move包的应用程序。包系统分为三个主要阶段:解析、解析和编译。
解析和清单布局
解析和清单布局逻辑定义在 ./src/source_package
目录中。这定义了Move包在 ./src/source_package/layout.rs
中的布局和所需以及可选目录集,在 ./src/source_package/parsed_manifest.rs
中定义了解析的Move包清单的格式("Move.toml
"),在 ./src/source_package/manifest_parser.rs
中定义了Move包清单的解析器。请注意,我们没有分词器/词法分析器,因为我们使用了TOML词法分析器。这也将git依赖项解析到它们将在本地文件系统中存在的位置(但不会克隆它们)。
解析
解析阶段负责解析所有包并构建包图,该图表示包之间的依赖关系。它还负责确保所有命名地址都有值分配,并且没有冲突的分配。包图以正在构建的包为根,是一个有向无环图(DAG)。
在构建包图时,我们执行以下概念性操作:验证依赖项是否存在于声明的位置,它们的包名称和源摘要是否匹配(如果适用),如果它们尚未存在于本地,则克隆git依赖项,构建Move包的依赖项图并确保它形成一个DAG,计算包图中每个Move包中每个命名地址的分配,并确保结果命名地址分配是有效的。
以上步骤相当直接,唯一可能例外的是命名地址:每个包将有一组作用域内的命名地址。包 P
的作用域内命名地址集合定义为 P
依赖中所有命名地址的传递闭包。此外,只要最终将值赋给命名地址集合的过程可以统一,包就可以重命名作用域内的命名地址。为了确保在重命名后命名地址的可统一性,解析过程会使用 Rc<RefCell<Opton<Address>>>
对命名地址进行统一:当命名地址首次进入包图的作用域时,会为其创建一个 Rc<RefCell<..>>
。然后,这个 refcell 被共享给所有使用该命名地址的地方,即使是跨重命名。当向其赋值时,值必须(1)与 Option
当前包含的值匹配,或者(2)Option
是 None
,然后将值放入 refcell 中。
编译
包系统的最终阶段是编译。与最终构建工件或全局环境创建相关的所有逻辑都包含在 ./src/compilation
目录中。编译后的 Move 包的布局定义在 ./src/compilation/package_layout.rs
。
./src/compilation/build_plan.rs
包含了驱动包编译以及给定有效解析图时编译所有包依赖项的逻辑。在 ./src/compilation/compiled_package.rs
中的逻辑包含了编译后的 Move 包的内存表示定义,以及其他与编译后的 Move 包相关的数据结构和 API,以及假设所有依赖项都已编译并保存到磁盘上,编译单个 Move 包的逻辑。这是由 ./src/compilation/build_plan.rs
中的逻辑驱动的。编译过程还负责生成文档、ABIs 等内容,以及确定要构建的包的缓存版本是否已存在,如果存在,则确定缓存版本是否可以使用,或者缓存副本是否无效需要重新编译。
这里需要注意的一个重要事项是,根据编译标志,可能需要更新缓存策略,并且传递给编译过程的 compiler_driver
函数可能会改变。然而,该函数应该是什么,由 Move 包库的客户端决定。特别是,当进行测试,即使我们使用相同的标志重新编译,我们也不能缓存根包,因为我们需要编译它以生成单元测试运行器稍后将要使用的测试计划。此测试计划的收集通过客户端传递的 compiler_driver
函数插入到编译过程中。在这种情况下,../move-cli/src/package
是客户端,它负责提供正确的函数作为编译驱动程序以收集测试计划,并将其传递给单元测试运行器。
依赖项
~19–36MB
~600K SLoC