opam
manualB0_opam
has support for opam
, the OCaml package manager. It provides:
opam
packages in the metadata of b0 packs.b0 -- .opam
action to generate opam package files and publish packages on the public OCaml opam
repository.opam
packages are represented by build packs tagged with the B0_opam.tag
. The name of the defined opam
package is the basename of the pack or the value of the B0_opam.name
meta key; see B0_opam.pkg_name_of_pack
for the full details.
The final metadata of the opam
package is defined by standard and opam
specific meta key values. The map between metadata key and opam fields is described in B0_opam.File.pkg_of_meta
. Some keys are derived by B0_opam.pkg_meta_of_pack
if unspecified.
The pack should contain exactly the build units that must be built by the opam
package, this allows B0_opam.pkg_meta_of_pack
to automatically infer some of the fields (e.g. build:
or depends:
).
Here's an example:
let mypkg =
let meta =
B0_meta.empty
|> ~~ B0_meta.authors ["The mylib programmers"]
|> ~~ B0_meta.maintainers ["mylib@example.org"]
|> ~~ B0_meta.homepage "https://example.org/software/mylib"
|> ~~ B0_meta.online_doc "https://example.org/software/mylib/doc"
|> ~~ B0_meta.license ["MIT"]
|> ~~ B0_meta.repo "git+https://example.org/repos/mylib.git"
|> ~~ B0_meta.issues "https://github.com/mylib/mylib/issues"
|> B0_meta.tag B0_opam.tag
|> B0_meta.add B0_opam.Meta.depends [ "ocaml", {|>= "4.14.0" |} ]
in
B0_pack.v "mypkg" ~doc:"opam package mypkg" ~meta ~locked:true @@
B0_unit.list () (* You likely want to be more refined than that *)
The opam
packages defined in a b0 root along with the pack in which they are defined can be listed with the .opam list
command:
b0 -- .opam list # List opam packages in the b0 root b0 -- .opam list --help # See more options
The opam
file for a package is generated from its pack metadata via B0_opam.pkg_meta_of_pack
and B0_opam.File.pkg_of_meta
.
The .opam file
command outputs the generated files in various ways.
b0 -- .opam file mypkg # opam file for mypkg on stdout b0 -- .opam file # All packages, on stdout b0 -- .opam file -d /tmp/opam/ # Write them to /tmp/opam b0 -- .opam file --in-scope-dir # Write them in their scopes b0 -- .opam file --help # See more options
Note that the generation differs slightly when opam
files are written to stdout, the name:
field is added; use option --no-name
to prevent that.
The .opam publish
command publishes packages on opam
by making a pull request on the OCaml opam
package repository on GitHub.
In order to be able to make a pull request on the OCaml opam
package repository in the name of your GitHub $USER
you need to:
Create a personal access token for $USER
with repo
permission by following these instructions. Paste the token in the file ~/.config/b0/github/$USER.token
and:
chmod 600 ~/.config/b0/github/$USER.token
Alternatively you can specify the user and the token in the B0_GITHUB_{USER,TOKEN}
environment variables.
https://github.com/$USER/opam-repository
.opam
package publication happens after the software source archive has been released on the web. To get help for releasing your software with b0 see the b0 release manual.
The publication process depends on the current work tree of the VCSes that are in your b0 root as follows:
opam
packages is used to generate the opam
package files to publish. See Package file generation.opam
packages define the published versions; unless they are explictely specified on the command line. See Version determination.Multiple package releases and incompatibilites with existing packages can be stated via a single pull request. For example:
b0 -- .opam publish p1 p2 p3.2.0.1 -i otherpackage
publishes the opam
packages p1
and p2
at a version determined by the VCSes in charge of the packs that define them, p3
at version 2.0.1
and states that all versions of otherpackage
are incompatible with these new versions – for those that exist in its dependencies.
Effectively it does the following. For each opam
package p
given on the command line it:
shasum
tool.url:
field to the archive.If everything worked well it continues with:
opam
repository to the bare repository ~/.caches/opam-repository.git
(the XDG spec is honoured).opam
repository on GitHub.opam
repository on GitHub.Invoking the action with --check-only
outputs on stdout the various bits that are being derived and performs various checks; e.g. it lints opam
files and HTTP HEADs archives to checks that they are not 404.
The version number of a package can be specified explicitely on the command line by separating it with a dot from the opam
package name. For example mypkg.2.0.1
publishes version 2.0.1
of the package. If no version number is explicitely given it is defined by using B0_release.vcs_repo_version_of_pack
on its pack.
The URL to the source archive of the opam
package is determined by its pack and version via B0_release.src_archive_url_of_pack
.
Note that the archive name defaults to the pack name when unspecified. If you want to define multiple packages for the same source archive you will need to define the B0_release.src_archive_name
appropriately.
For example suppose that in addition to mypkg
you publish on opam
a separate package mypkg-unix
which compiles the Unix
library support from the same source achive as mypkg
. In the metadata of the pack defining the package mypkg-unix
you can add:
let mypkg = ...
let mypkg_unix =
let meta =
B0_meta.empty
...
|> ~~ B0_release.src_archive_name (B0_pack.basename mypkg)
in
B0_pack.v "mypkg-unix" ~meta @@ mypkg_unix_units
The release notes of the opam
package are determined by looking for a file CHANGES.md
in the scope directory of its pack and picking up the first section. See B0_release.changes_file_of_pack
and B0_release.changes_latest_of_file
.
Packages sharing the same release notes are aggregated in the pull request.
FIXME. We need this in opam-admin
to make that a reality. For now the best way is to make a separate request manually to state the incompatibilities and have it merged before your pull request and/or manually tweak the automated pull request.
For the latter the simplest is to clone your github opam-repository checkout the branch of publication and push changes on it.
git clone git@github.com:$(GHUSER)/opam-repository.git git checkout $B0-PUBLISH-BRANCH … # Edit git commit -m 'Handle first round of failures' git push # This will automatically update the PR.
fails because of the new releases. You can state the incompatibility with the repeatable -i PKG[.version]
option. This will add an upper bound on PKG
as needed.
For example the following publishes a new mypkg
and states that all versions of otherpack
and the version 2.1.0 of thispack
are incompatible with it – provided mypkg
is in their dependencies:
b0 -- .opam publish mypkg -i otherpack -i thispack.2.1.0
If you discover the incompatibilites only once the pull request has been made, repeat the same .opam publish
invocation with more -i
options, this will update the pull request.
If there are issues with the pull request you can adjust your metadata and invoke again the same .opam publish
command. As long as the same set of opam
packages with the same version end-up being published this updates the existing pull request.
In particular gradually stating incompatibilites will update the pull request.
TODO. Review.
If the build failure is due to a missing constraint, follow the instruction of the next item to correct the opam file. If the failure is due to a defect in the distribution archive, call it a day and start over with a patch version release that corrects the problem. Do not try to reuse the version string of the failed release, other systems may already have picked up the broken archive.
TODO. Review.
These pesky but loved maintainers and robots... If they complain about certain aspects of your opam submission, you can either try to correct it manually from the opam package description found in the build directory and reinvoke topkg opam submit or edit the opam file of the source repository and regenerate the opam Package description with topkg opam pkg and the --pkg-opam option. Note that if the VCS moved meanwhile you may have to use the various command line options of topkg-opam(1) to make sure you point to the right package version and distribution archive. In either case you should be aware that there will be a mismatch between the opam file in the distribution archive and the one you submitted to the opam repository. If this happens to be a problem, start over with a new patch version release.
If you want to define multiple packages from a single archive tarball follow the instructions in Release archive URL determination.
.opam publish
hangs after pushIf publish hangs after push: go to cd ~/.cache/opam-repository && git gc
and try again.