What is the difference between a build command and an install command in an proj.opam file?

I am looking at:

opam-version: "2.0"
maintainer: "..."

homepage: "https://github.com/pestun/lf"
dev-repo: "git+https://github.com/pestun/lf.git"
bug-reports: "https://github.com/pestun/lf/issues"
license: "LGPL-2.1"

synopsis: "..."
description: """

version: "dev"

build: [make "-j%{jobs}%"]
install: [make "install"]

depends: [
  "coq" {(>= "8.11" & < "8.12~") | (= "dev")}

tags: [
  "category:Miscellaneous/Coq Extensions"
  "keyword:integer numbers"
authors: [

What is the difference between the build and the install command? Do I need both?


Generally a make will build files. A make install will copy them over to install directories in a unix prefix e.g. /usr/local/{bin,lib,include}

Do I need both?

If you want to install stuff yes. One reason for the separation is that you may need to get more privileges to install files and you don’t want to run the build with these privileges.

@dbuenzli ok so the difference is due to make install and not opam install ...?

I am mostly interested when I personally have the src to the ocaml repo (mostly Coq for me).

I don’t understand your question. But opam install PKG will first execute the build: instructions and then the install: instructions.

1 Like

what about opam pin?

Sounds like with an opam file I don’t need to execute make clean myself :slight_smile:

BTw, thanks for your responses super helpful!

Maybe this is it:

  1. opam uses a sandbox for running builds and installs; then it copies files over to their final location.
  2. if you don’t distinguish between build and install, then how can opam know what files are meant to be installed, and which are merely created as part of the build-process, right?

I think that’s the reason this matters. B/c otherwise, well, it really wouldn’t matter, would it?

P.S. But also, I have this nagging thought that maybe there’s some other way that opam distinguishes between “I built this file in the process of making the package” and “I built this file and put it its final location”, in which case, this distinction (for opam) is superfluous. But even if it were superfluous, having a distinction is a valuable form of documentation for people coming to your project and finding an error: they can do the “build” step knowing it won’t pollute installation-directories. I often look at the build-step in the opam file for just this reason.

Thanks for the response!

I think even conceptually I don’t understand what install vs build means. For me it I am realizing I assume build means “compile the binaries needed for the project to work and put it in some location e.g. usally ~/.local/bin or /usr/bin for system ones” but that is what install means to me too. I just don’t know what the distinction is in opam since for me installing always just means compiling so it’s available for use.

Thanks for the discussion I think we are moving forward.

Let me try again:

  1. files created during the “build” process never need to be considered for inclusion in the set of files that a package actually installs.

  2. files created during the “install” process do need to be considered for this.

Since far, far more files are created during #1 than during #2, this might simply be a good efficiency distinction.

You can imagine the difference being:

  • build: generate some files (e.g. binaries, library archives, etc…)
  • install: copy the generated files where they need to be (e.g. copy the binary into /usr/bin )

There is another way which is the reason why many packages do not sport an install: field in their opam file.

After building, opam looks at the root of the source directory for an a $(PKG).install file which declares which files need to be installed where. Your build system can generate this file. In this case your opam file just needs build: instructions. See the manual.