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 tmp-testing --alias-of system
    • 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
    • admin-scripts/cudf-debug.ml cudf-file-1.cudf may help with conflicts


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).


Easily 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 add ocaml101 <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 explicitely 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.