10. Project.toml and Manifest.toml
Pkg 的两个核心文件是 Project.toml 和 Manifest.toml。Project.toml 和 Manifest.toml 都是用 TOML(因此是 .toml 扩展名)编写的,包括有关依赖项、版本、包名称、UUID 等的信息。
Project.toml 和 Manifest.toml 文件不仅由包管理器使用;Julia 的代码加载也使用它们,并确定例如 using Example 应该做什么。有关更多详细信息,请参阅 Julia 手册中有关 代码加载 的部分。
Project.toml
项目文件从高层次上描述了项目,例如,项目文件中列出了包/项目的依赖关系和兼容性约束。文件条目如下所述。
authors 字段
对于包,authors 可选字段是描述包作者的字符串列表,格式为 NAME <EMAIL>。例如:
authors = ["Some One <someone@email.com>",
"Foo Bar <foo@bar.com>"]name 字段
包/项目的名称由 name 字段决定,例如:
name = "Example"名称必须是有效标识符(不以数字开头且既不是 true 也不是的 false Unicode 字符序列)。对于包,建议遵循 包命名准则。name 字段对于包是必需的。
uuid 字段
uuid 是包/项目 通用唯一标识符 字符串,例如:
uuid = "7876af07-990d-54b4-ab0e-23690620f79a"uuid 字段对于包是必需的。
建议使用 UUIDs.uuid4() 生成随机 UUID。
version 字段
version 是包/项目版本号的字符串。它应该由三个数字组成:主要版本号、次要版本号和补丁号,用 . 分隔,例如:
version = "1.2.5"Julia 使用语义版本控制(SemVer),该 version 字段应遵循 SemVer。基本规则是:
- 在 1.0.0 之前,一切正常,但是当您进行重大更改时,次要版本应该增加。
- 在 1.0.0 之后,仅在增加主要版本时进行重大更改。
- 在 1.0.0 之后,如果不增加次要版本,则不应添加新的公共 API。这尤其包括来自
Base或其他包的新类型、函数、方法和方法重载 。
另请参阅兼容性部分。
请注意,当涉及到 1.0.0 之前的版本时,Pkg.jl 偏离了 SemVer 规范。有关详细信息,请参阅 pre-1.0 行为 部分。
[deps] 节
该节列出了包/项目的所有依赖项[deps]。每个依赖项都以“名称-uuid”对的形式列出,例如:
[deps]
Example = "7876af07-990d-54b4-ab0e-23690620f79a"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"通常不需要手动向 [deps] 节添加条目;这由 Pkg 操作来处理,例如 add。
[compat] 节
[deps] 下面列出的依赖项的兼容性约束可以在该 [compat] 节中列出。例子:
[deps]
Example = "7876af07-990d-54b4-ab0e-23690620f79a"
[compat]
Example = "1.2"兼容性章节详细描述了不同的可能兼容性约束。也可以列出 julia 自身的约束,尽管 julia 未在 [deps] 节中列为依赖项:
[compat]
julia = "1.1"Manifest.toml
manifest 文件是环境中包状态的绝对记录。它包括有关项目(直接和间接)依赖项的确切信息。给定一对 Project.toml 和 Manifest.toml,可以实例化完全相同的包环境,这对于可复现性非常有用。有关详细信息,请参阅 Pkg.instantiate。
Manifest.toml 文件由 Pkg 生成和维护,一般情况下,不应手动修改此文件。
Manifest.toml 条目
manifest 中有三个顶级条目,如下所示:
julia_version = "1.8.2"
manifest_format = "2.0"
project_hash = "4d9d5b552a1236d3c1171abf88d59da3aaac328a"这显示了创建 manifest 的 Julia 版本、manifest 的“格式”和项目文件的哈希值,这样就可以看到 manifest 与项目文件相比什么时候过时了。
每个依赖项在 manifest 文件中都有自己的节,其内容根据依赖项添加到环境的方式而有所不同。每个依赖项的节都包含以下条目的组合:
uuid: 依赖项的 UUID,例如uuid = "7876af07-990d-54b4-ab0e-23690620f79a"。deps: 一个向量,列出依赖项的依赖项,例如deps = ["Example", "JSON"]。version: 版本号,例如version = "1.2.6"。path: 源代码的文件路径,例如path = /home/user/Example。repo-url: 源代码存储库的 URL ,例如repo-url = "https://github.com/JuliaLang/Example.jl.git"。repo-rev: git 存储库的修订版, 例如一个分支repo-rev = "master"或一个提交repo-rev = "66607a62a83cb07ab18c0b35c038fcd62987c9b1"。git-tree-sha1: git 源码树的哈希, 例如git-tree-sha1 = "ca3820cc4e66f473467d912c4b2b3ae5dc968444"。
已添加的包
当从包注册表添加包时,例如通过调用 pkg> add Example 或使用特定版本 pkg> add Example@1.2,生成的 Manifest.toml 条目如下所示:
[[deps.Example]]
deps = ["DependencyA", "DependencyB"]
git-tree-sha1 = "8eb7b4d4ca487caade9ba3e85932e28ce6d6e1f8"
uuid = "7876af07-990d-54b4-ab0e-23690620f79a"
version = "1.2.3"请特别注意,没有 repo-url 存在,因为该信息包含在能够找到此包的注册表中。
按分支添加的包
添加由分支指定的包时生成的 [deps] 节,例如 pkg> add Example#masteror 或 pkg> add https://github.com/JuliaLang/Example.jl.git,如下所示:
[[deps.Example]]
deps = ["DependencyA", "DependencyB"]
git-tree-sha1 = "54c7a512469a38312a058ec9f429e1db1f074474"
repo-rev = "master"
repo-url = "https://github.com/JuliaLang/Example.jl.git"
uuid = "7876af07-990d-54b4-ab0e-23690620f79a"
version = "1.2.4"请注意,我们正在跟踪的分支 (master) 和远程存储库 url ("https://github.com/JuliaLang/Example.jl.git") 都存储在 manifest 中。
按提交添加的包
添加由提交指定的包时生成的 [deps] 节,例如 pkg> add Example#cf6ba6cc0be0bb5f56840188563579d67048be34,如下所示:
[[deps.Example]]
deps = ["DependencyA", "DependencyB"]
git-tree-sha1 = "54c7a512469a38312a058ec9f429e1db1f074474"
repo-rev = "cf6ba6cc0be0bb5f56840188563579d67048be34"
repo-url = "https://github.com/JuliaLang/Example.jl.git"
uuid = "7876af07-990d-54b4-ab0e-23690620f79a"
version = "1.2.4"与跟踪分支的唯一区别是 repo-rev 的内容。
开发包
使用 develop 命令添加包时生成的 [deps] 节,例如 pkg> develop Example 或 pkg> develop /path/to/local/folder/Example,如下所示:
[[deps.Example]]
deps = ["DependencyA", "DependencyB"]
path = "/home/user/.julia/dev/Example/"
uuid = "7876af07-990d-54b4-ab0e-23690620f79a"
version = "1.2.4"请注意,包含源代码的路径,并且直接反映对该源代码树所做的更改。
已固定的包
已固定的包也记录在 manifest 文件中,例如由 pkg> add Example; pin Example 生成的 [deps] 节如下所示:
[[deps.Example]]
deps = ["DependencyA", "DependencyB"]
git-tree-sha1 = "54c7a512469a38312a058ec9f429e1db1f074474"
pinned = true
uuid = "7876af07-990d-54b4-ab0e-23690620f79a"
version = "1.2.4"唯一的不同是附加了 pinned = true 条目。
多个同名的包
Julia 根据 UUID 区分包,这意味着仅靠名称不足以识别包。在同一个环境中可以有多个包具有相同的名称,但具有不同的 UUID。在这种情况下,Manifest.toml 文件看起来有点不同。例如,考虑您已将包 A 和 B 添加到您的环境的情况,文件 Project.toml 如下所示:
[deps]
A = "ead4f63c-334e-11e9-00e6-e7f0a5f21b60"
B = "edca9bc6-334e-11e9-3554-9595dbb4349c"如果 A 现在依赖于 B = "f41f7b98-334e-11e9-1257-49272045fb24",即另一个名为 B 的包,在 Manifest.toml 文件中将有两个不同的 B 包。在这种情况下,为清楚起见删除了 git-tree-sha1 和 version 字段的完整 Manifest.toml 文件如下所示:
[[deps.A]]
uuid = "ead4f63c-334e-11e9-00e6-e7f0a5f21b60"
[deps.A.deps]
B = "f41f7b98-334e-11e9-1257-49272045fb24"
[[deps.B]]
uuid = "f41f7b98-334e-11e9-1257-49272045fb24"
[[deps.B]]
uuid = "edca9bc6-334e-11e9-3554-9595dbb4349c"现在,有一个包含两个 B 包的数组,并且 A 包的 [deps] 节已扩展为明确说明 A 依赖于哪个 B 包。