The following are beyond the scope of the FAQ, but have been found useful for specific use-cases or for advanced users.

Simulate actions from the current switch state (for debugging)

  • opam upgrade --show-actions (stop at the action summary dialog)
  • opam upgrade --dry-run (display only)
  • if you really want to try out the results:
    • opam switch export testing-state.export
    • opam switch create tmp-testing --empty
    • opam switch import testing-state.export --fake
    • try actions with --fake (registers them in opam, but doesn't actually run the build/install commands)
    • revert to normal: opam switch <previous>; opam switch remove tmp-testing
  • Experiment with the solver:
    • opam <request> --cudf=cudf-file
    • or opam config cudf-universe >cudf-file-1.cudf
    • run e.g. aspcud with aspcud cudf-file-1.cudf /dev/stdout CRITERIA


Install in all switches

Not supported natively at the moment, but it's being considered. Quick hack:

for switch in $(opam switch list -s); do
  opam install --switch $switch PACKAGE
done

You may want to add --yes if you're confident.


Update opam environment within emacs

The best way is to use opam-user-setup (just run opam user-setup install), and that will make the opam-update-env interactive function available in emacs.

You could also define the function by hand:

(defun opam-env ()
  (interactive nil)
  (dolist (var (car (read-from-string (shell-command-to-string "opam config env --sexp"))))
    (setenv (car var) (cadr var))))

You may want to run this at emacs startup if it doesn't inherit the proper shell environment. Be also careful that tuareg-mode has its own bindings that override the environment when using the compile command, so that may get in the way (see Tuareg issue #94).


Provide a set of packages for a group of users to install

The easiest way is to create a package with your prerequisites as depends and have them pin that. A quick way to host the file is to use a Gist. Create one with minimal contents and listing your packages as dependencies -- the file name has to be opam:

opam-version: "2.0"
name: "ocaml101"
version: "0.1"
maintainer: "Louis Gesbert <louis.gesbert@ocamlpro.com>"
depends: [ "menhir" { = "20140422" }
           "merlin" { >= "2" }
           "ocp-indent"
           "ocp-index" ]

Save that and get the HTTPS clone URL. All that is needed then is to run:

$ opam pin <HTTPS clone URL>

Furthermore, opam update will then pick up any modification you made to the gist.

These other options may offer more control, with a little more work, depending on the scale you work at:

  • distribute an "export" file, as generated by opam switch export <file>
  • define and host your own repository, and use a specific opamrc file on the user's systems, to automatically select your repository and defaults on opam init.


Alternate implementations for a package

opam currently doesn't support a provides: field that would allow packages to replace others. If you have two packages a and b providing foo, you need to:

  • Define a (virtual) package foo, with depends: ["a" | "b"], for any version you want available: so if the versions of a, b and foo match you would have e.g. foo.1 with depends: ["a" {= "1"} | "b" {= "1"}]. Or, better, using opam 2.0 variables: depends: ["a" {= _:version} | "b" {= _:version}], duplicated for any version desired.

  • Make sure a and b conflict with each other. The scalable solution for this is to use the conflict-class: field: add e.g. conflict-class: "foo-implementation" to all versions of both a and b.

The need to define the virtual package explicitly also ensures that a third package can't inject a new implementation without that being visible in foo: it would otherwise be a security hole when we deploy end-to-end signing of packages.


How to rename a package

Opam doesn't technically allow packages to be renamed, but you can create a package with the new name, and a upgrade path between the two. Assuming you want to rename foo to bar:

  1. Create a new version of foo, e.g. foo.transition, depending on bar, and with a description mentioning it is a virtual package that can be safely removed. The package shouldn't have a source URL or build, install, etc. instructions.
  2. Create bar as a new package.
  3. Add conflicts: "foo" {!= "transition"}. Remember to keep that field on any new version of bar.

This ensures at the same time that users upgrading will get the new package bar, and that the package can't be installed twice under the two names.


Display the current "opam switch" in the prompt ?

This can get quite handy if you have many switches you use in parallel. You can use e.g. the command opam switch show --safe 2>/dev/null | sed 's|.*/|*|' to return a (shortened) switch name.

For bash, just include $(COMMAND) in your definition of PS1 (making sure the $ is escaped).

For zsh, use setopt prompt_subst, and include $(COMMAND) in the definition of prompt.


How to install a maximum number of packages ?

The following sequence of commands tries to install as much packages as possible in a local switch with OCaml $(VERSION).

opam update
opam switch create . ocaml-base-compiler.$(VERSION)
export OPAMSOLVERTIMEOUT=3600
opam list --available -s | xargs opam install --best-effort --yes
# Be patient