Документация Engee

10. Project.toml и 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"

Имя должно быть допустимым идентификатором (последовательностью символов Unicode, которая не начинается с цифры и не имеет значения ни true, ни false). При работе с пакетами рекомендуется следовать инструкциям по именованию пакетов. Поле name является обязательным для пакетов.

Поле uuid

uuid — это строка с универсальным уникальным идентификатором для пакета или проекта, например:

uuid = "7876af07-990d-54b4-ab0e-23690620f79a"

Поле uuid является обязательным для пакетов.

Для генерации случайных UUID рекомендуется использовать UUIDs.uuid4().

Поле version

version — это строка с номером версии для пакета или проекта. Она должна состоять из трех числовых значений — номера основной версии, номера дополнительной версии и номера исправления, разделенных символом ., например:

version = "1.2.5"

Julia использует семантическое управление версиями (SemVer), и поле version должно ему соответствовать. Действуют следующие базовые правила.

  • До версии 1.0.0 можно делать все, что угодно, но когда вы вносите критические изменения, номер дополнительной версии должен увеличиваться.

  • После версии 1.0.0 вносить критические изменения следует только при увеличении номера основной версии.

  • После версии 1.0.0 не следует добавлять новые общедоступные API без увеличения номера дополнительной версии. В частности, это касается новых типов, функций, методов и перегрузок методов из пакетов Base или других пакетов. См. раздел Совместимость.

Обратите внимание, что когда речь идет о версиях, предшествующих 1.0.0, Pkg.jl отклоняется от спецификации SemVer. Дополнительные сведения см. в разделе о поведении версий, предшествующих 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

Файл манифеста является абсолютной записью о состоянии пакетов в среде. Он содержит точную информацию о (прямых и косвенных) зависимостях проекта. Принимая во внимание пару Project.toml + Manifest.toml, можно создать экземпляр точно такой же среды пакета, что очень полезно для воспроизводимости. Подробнее см. в описании Pkg.instantiate.

Файл Manifest.toml генерируется и поддерживается диспетчером пакетов Pkg, и, в общем случае, этот файл никогда не следует изменять вручную.

Записи Manifest.toml

В манифесте есть три записи верхнего уровня, которые могут выглядеть следующим образом.

julia_version = "1.8.2"
manifest_format = "2.0"
project_hash = "4d9d5b552a1236d3c1171abf88d59da3aaac328a"

Здесь показана версия Julia, для которой был создан манифест, «формат» манифеста и хэш файла проекта, чтобы можно было увидеть, когда манифест будет устаревшим по сравнению с файлом проекта.

Каждая зависимость имеет свой раздел в файле манифеста, и его содержимое зависит от того, каким образом зависимость была добавлена в среду. Каждый раздел зависимостей содержит сочетание следующих записей:

  • 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-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, поскольку эта информация включена в реестр, в котором был найден данный пакет.

Добавленный пакет, указанный ветвью

Результирующий раздел зависимостей при добавлении пакета, указанного ветвью, например pkg> add Example#master или 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").

Добавленный пакет, указанный фиксацией

Результирующий раздел зависимостей при добавлении пакета, указанного фиксацией, например 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, например 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"

Обратите внимание, что включен путь к исходному коду, и изменения, внесенные в это дерево исходного кода, отражаются напрямую.

Закрепленный пакет

Закрепленные пакеты также записываются в файл манифеста. Результирующий раздел зависимостей, например pkg> add Example; pin Example, выглядит следующим образом.

[[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. В данном случае полный файл Manifest.toml, из которого для наглядности удалены поля git-tree-sha1 и version, выглядит следующим образом.

[[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, а раздел [deps] для A был расширен, чтобы явно указать, от какого пакета B зависит A.