diff --git a/.gitignore b/.gitignore
index 1385ba4c323601fdce81d0cfdf678b5b93250402..a7196f61cbe7a0e03550400abc986deadb29b648 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ _build
 .merlin
 *.install
 *~
+dune-workspace.versions
diff --git a/Makefile b/Makefile
index c85caa611878af40a75ba816b9164b65f4444940..35ceb4d5fe93862c7ccc9a07c00bcef01bf544f2 100644
--- a/Makefile
+++ b/Makefile
@@ -86,3 +86,36 @@ release:
 publish:
 # Publish an opam description.
 	@ opam publish -v $(DATE) $(THIS) $(ARCHIVE) .
+
+# [make versions] compiles and tests under many versions of OCaml,
+# whose list is specified below.
+
+VERSIONS := \
+  4.03.0 \
+  4.04.2 \
+  4.05.0 \
+  4.06.1 \
+  4.07.1 \
+  4.08.1 \
+  4.09.1 \
+  4.09.0+bytecode-only \
+  4.10.0 \
+  4.11.1 \
+
+.PHONY: versions
+versions:
+	@(echo "(lang dune 2.0)" && \
+	  for v in $(VERSIONS) ; do \
+	    echo "(context (opam (switch $$v)))" ; \
+	  done) > dune-workspace.versions
+	@ dune build --workspace dune-workspace.versions @install # or: @all
+
+.PHONY: handiwork
+handiwork:
+	@ current=`opam switch show` ; \
+	  for v in $(VERSIONS) ; do \
+	    opam switch $$v && \
+	    eval $$(opam env) && \
+	    opam install --yes zarith seq fix.20201120 ; \
+	  done ; \
+	  opam switch $$current