The following are beyond the scope of the FAQ, but have been found useful for specific use-cases or for advanced users.
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
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.
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).
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 onopam init
.
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
, withdepends: ["a" | "b"]
, for any version you want available: so if the versions ofa
,b
andfoo
match you would have e.g.foo.1
withdepends: ["a" {= "1"} | "b" {= "1"}]
. Or, better, using opam 2.0 variables:depends: ["a" {= _:version} | "b" {= _:version}]
, duplicated for any version desired. -
Make sure
a
andb
conflict with each other. The scalable solution for this is to use theconflict-class:
field: add e.g.conflict-class: "foo-implementation"
to all versions of botha
andb
.
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.
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
:
- Create a new version of
foo
, e.g.foo.transition
, depending onbar
, 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. - Create
bar
as a new package. - Add
conflicts: "foo" {!= "transition"}
. Remember to keep that field on any new version ofbar
.
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.
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
.
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
export OPAMSOLVERTOLERANCE=1.0
opam list --available -s | xargs opam install --best-effort --yes
# Be patient