diff --git a/.github/scripts/main.sh b/.github/scripts/main.sh
index e81a3a3b95c..4762e8f4e77 100644
--- a/.github/scripts/main.sh
+++ b/.github/scripts/main.sh
@@ -20,6 +20,9 @@ export OCAMLRUNPARAM=b
   fi
 
   ./configure --prefix ~/local --with-mccs
+  if [ "$OPAM_TEST" != "1" ]; then
+    echo 'DUNE_PROFILE=dev' >> Makefile.config
+  fi
 
   if [[ $OPAM_TEST$OPAM_COLD -eq 0 ]] ; then
     make lib-ext
diff --git a/Makefile b/Makefile
index da99763894b..a18da5fe808 100644
--- a/Makefile
+++ b/Makefile
@@ -2,13 +2,11 @@ ifeq ($(findstring clean,$(MAKECMDGOALS)),)
 -include Makefile.config
 endif
 
-# TODO: Replace --profile=$(DUNE_PROFILE) by --release when we require on dune >= 2.5
-
 all: opam opam-installer
 	@
 
 admin:
-	$(DUNE) build --profile=$(DUNE_PROFILE) --root . $(DUNE_ARGS) opam-admin.install
+	$(DUNE) build $(DUNE_PROFILE_ARG) --root . $(DUNE_ARGS) opam-admin.install
 
 DUNE_PROMOTE_ARG =
 DUNE_PROMOTE_ARG += --promote-install-files
@@ -39,6 +37,13 @@ JBUILDER_ARGS ?=
 DUNE_ARGS ?= $(JBUILDER_ARGS)
 DUNE_PROFILE ?= release
 
+ifeq ($(DUNE_PROFILE_ARG),release)
+  # TODO Replace with --release when we require dune >= 2.5
+  DUNE_PROFILE_ARG = --profile=release
+else
+  DUNE_PROFILE_ARG = --profile=$(DUNE_PROFILE)
+endif
+
 src_ext/dune-local/dune.exe: src_ext/dune-local.stamp $(DUNE_SECONDARY)
 ifeq ($(DUNE_SECONDARY),)
 	cd src_ext/dune-local && ocaml bootstrap.ml
@@ -50,7 +55,7 @@ src_ext/dune-local.stamp:
 	$(MAKE) -C src_ext dune-local.stamp
 
 dune: $(DUNE_DEP)
-	@$(DUNE) build --profile=$(DUNE_PROFILE) --root . $(DUNE_ARGS) @install
+	@$(DUNE) build $(DUNE_PROFILE_ARG) --root . $(DUNE_ARGS) @install
 
 opam: $(DUNE_DEP) build-opam processed-opam.install
 	@$(LN_S) -f _build/default/src/client/opamMain.exe $@$(EXE)
@@ -66,7 +71,7 @@ opam-installer: $(DUNE_DEP) build-opam-installer processed-opam-installer.instal
 	@$(LN_S) -f _build/default/src/tools/opam_installer.exe $@$(EXE)
 
 opam-admin.top: $(DUNE_DEP)
-	$(DUNE) build --profile=$(DUNE_PROFILE) --root . $(DUNE_ARGS) src/tools/opam_admin_topstart.bc
+	$(DUNE) build $(DUNE_PROFILE_ARG) --root . $(DUNE_ARGS) src/tools/opam_admin_topstart.bc
 	$(LN_S) -f _build/default/src/tools/opam_admin_topstart.bc $@$(EXE)
 
 lib-ext:
@@ -121,23 +126,23 @@ opam-%.install: $(DUNE_DEP)
 
 .PHONY: build-opam-installer
 build-opam-installer: $(DUNE_DEP) 
-	$(DUNE) build --profile=$(DUNE_PROFILE) --root . $(DUNE_ARGS) $(DUNE_PROMOTE_ARG) opam-installer.install
+	$(DUNE) build $(DUNE_PROFILE_ARG) --root . $(DUNE_ARGS) $(DUNE_PROMOTE_ARG) opam-installer.install
 opam-installer.install: $(DUNE_DEP)
-	$(DUNE) build --profile=$(DUNE_PROFILE) --root . $(DUNE_ARGS) $(DUNE_PROMOTE_ARG) opam-installer.install
+	$(DUNE) build $(DUNE_PROFILE_ARG) --root . $(DUNE_ARGS) $(DUNE_PROMOTE_ARG) opam-installer.install
 
 .PHONY: build-opam
 build-opam: $(DUNE_DEP)
-	$(DUNE) build --profile=$(DUNE_PROFILE) --root . $(DUNE_ARGS) $(DUNE_PROMOTE_ARG) opam-installer.install opam.install
+	$(DUNE) build $(DUNE_PROFILE_ARG) --root . $(DUNE_ARGS) $(DUNE_PROMOTE_ARG) opam-installer.install opam.install
 opam.install: $(DUNE_DEP)
-	$(DUNE) build --profile=$(DUNE_PROFILE) --root . $(DUNE_ARGS) $(DUNE_PROMOTE_ARG) opam-installer.install opam.install
+	$(DUNE) build $(DUNE_PROFILE_ARG) --root . $(DUNE_ARGS) $(DUNE_PROMOTE_ARG) opam-installer.install opam.install
 
 OPAMLIBS = core format solver repository state client
 
 opam-%: $(DUNE_DEP)
-	$(DUNE) build --profile=$(DUNE_PROFILE) --root . $(DUNE_ARGS) $(DUNE_PROMOTE_ARG) opam-$*.install
+	$(DUNE) build $(DUNE_PROFILE_ARG) --root . $(DUNE_ARGS) $(DUNE_PROMOTE_ARG) opam-$*.install
 
 opam-lib: $(DUNE_DEP)
-	$(DUNE) build --profile=$(DUNE_PROFILE) --root . $(DUNE_ARGS) $(DUNE_PROMOTE_ARG) $(patsubst %,opam-%.install,$(OPAMLIBS))
+	$(DUNE) build $(DUNE_PROFILE_ARG) --root . $(DUNE_ARGS) $(DUNE_PROMOTE_ARG) $(patsubst %,opam-%.install,$(OPAMLIBS))
 
 installlib-%: opam-installer opam-%.install
 	$(if $(wildcard src_ext/lib/*),\
@@ -173,7 +178,7 @@ uninstall: opam.install
 
 .PHONY: tests
 tests: $(DUNE_DEP)
-	@$(DUNE) runtest --profile=$(DUNE_PROFILE) --root . $(DUNE_ARGS) src/ tests/ --no-buffer; \
+	@$(DUNE) runtest $(DUNE_PROFILE_ARG) --root . $(DUNE_ARGS) src/ tests/ --no-buffer; \
 	ret=$$?; \
 	echo "###     TESTS RESULT SUMMARY     ###"; \
 	for t in _build/default/tests/reftests/*.test; do \
@@ -200,19 +205,19 @@ crowbar-afl: $(DUNE_DEP)
 
 # tests-local, tests-git
 tests-%: $(DUNE_DEP)
-	$(DUNE) build $(DUNE_ARGS) --profile=$(DUNE_PROFILE) --root . @reftest-legacy-$* --force
+	$(DUNE) build $(DUNE_ARGS) $(DUNE_PROFILE_ARG) --root . @reftest-legacy-$* --force
 
 reftest-gen: $(DUNE_DEP)
-	$(DUNE) build $(DUNE_ARGS) --profile=$(DUNE_PROFILE) --root . @reftest-gen --auto-promote --force
+	$(DUNE) build $(DUNE_ARGS) $(DUNE_PROFILE_ARG) --root . @reftest-gen --auto-promote --force
 
 reftest-runner: $(DUNE_DEP)
-	$(DUNE) build $(DUNE_ARGS) --profile=$(DUNE_PROFILE) --root . tests/reftests/run.exe
+	$(DUNE) build $(DUNE_ARGS) $(DUNE_PROFILE_ARG) --root . tests/reftests/run.exe
 
 reftests: $(DUNE_DEP)
-	$(DUNE) build $(DUNE_ARGS) --profile=$(DUNE_PROFILE) --root . @reftest
+	$(DUNE) build $(DUNE_ARGS) $(DUNE_PROFILE_ARG) --root . @reftest
 
 reftests-%: $(DUNE_DEP)
-	$(DUNE) build $(DUNE_ARGS) --profile=$(DUNE_PROFILE) --root . @reftest-$* --force
+	$(DUNE) build $(DUNE_ARGS) $(DUNE_PROFILE_ARG) --root . @reftest-$* --force
 
 reftests-meld:
 	meld `for t in tests/reftests/*.test; do echo --diff $$t _build/default/$${t%.test}.out; done`
diff --git a/appveyor_build.cmd b/appveyor_build.cmd
index 723c1de3df9..7bac1bb224d 100644
--- a/appveyor_build.cmd
+++ b/appveyor_build.cmd
@@ -181,7 +181,9 @@ set PRIVATE_RUNTIME=
 if "%OCAML_PORT:~0,5%" equ "mingw" set PRIVATE_RUNTIME=--with-private-runtime
 set WITH_MCCS=--with-mccs
 if "%DEP_MODE%" equ "lib-pkg" set WITH_MCCS=
-"%CYG_ROOT%\bin\bash.exe" -lc "cd $APPVEYOR_BUILD_FOLDER %LIB_PKG% && ./configure %PRIVATE_RUNTIME% %WITH_MCCS% %LIB_EXT% && make opam %POST_COMMAND%" || exit /b 1
+"%CYG_ROOT%\bin\bash.exe" -lc "cd $APPVEYOR_BUILD_FOLDER %LIB_PKG% && ./configure %PRIVATE_RUNTIME% %WITH_MCCS% %LIB_EXT%" || exit /b 1
+"%CYG_ROOT%\bin\bash.exe" -lc "cd $APPVEYOR_BUILD_FOLDER && echo DUNE_PROFILE=dev >> Makefile.config" || exit /b 1
+"%CYG_ROOT%\bin\bash.exe" -lc "cd $APPVEYOR_BUILD_FOLDER && make opam %POST_COMMAND%" || exit /b 1
 goto :EOF
 
 :test
diff --git a/doc/Makefile b/doc/Makefile
index 1709291de15..0edcf0e49a5 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -14,6 +14,13 @@ endif
 DUNE_PROFILE ?= release
 DUNE_ARGS ?= 
 
+ifeq ($(DUNE_PROFILE_ARG),release)
+  # TODO Replace with --release when we require dune >= 2.5
+  DUNE_PROFILE_ARG = --profile=release
+else
+  DUNE_PROFILE_ARG = --profile=$(DUNE_PROFILE)
+endif
+
 .PHONY: man html pages
 all: html pages
 
@@ -38,7 +45,7 @@ man-html:
 
 html:
 	rm -rf html
-	cd .. && $(DUNE) build --profile=$(DUNE_PROFILE) --root . $(DUNE_ARGS) @doc
+	cd .. && $(DUNE) build $(DUNE_PROFILE_ARG) --root . $(DUNE_ARGS) @doc
 	cp -r ../_build/default/_doc/_html html
 	sed 's/%{OPAMVERSION}%/'$(version)'/g' index.html > html/index.html
 # Not to break older links, add manpages to the `ocamldoc` dir
diff --git a/master_changes.md b/master_changes.md
index 6cb4e0bf15d..ef9a42b9bd0 100644
--- a/master_changes.md
+++ b/master_changes.md
@@ -160,6 +160,7 @@ New option/command/subcommand are prefixed with ◈.
   * Add switch creation tests: (dead)locking and switch defitinion at action time [#4612 @rjbou]
   * Remove debug information from reftest [#4612 @rjbou]
   * Add preserved format test [#4634 @rjbou]
+  * Use the dev profile when testing [#4672 @dra27]
 
 ## Shell
   *
diff --git a/src/state/dune b/src/state/dune
index d2ec2537c6b..3da67ef6bd3 100644
--- a/src/state/dune
+++ b/src/state/dune
@@ -4,10 +4,12 @@
   (libraries   opam-repository)
   (synopsis    "OCaml Package Manager instance management library")
   (modules_without_implementation OpamStateTypes)
+  (modules     :standard \ flags)
   (flags       (:standard
                (:include ../ocaml-flags-standard.sexp)
                (:include ../ocaml-flags-configure.sexp)
-               (:include ../ocaml-context-flags.sexp)))
+               (:include ../ocaml-context-flags.sexp)
+               (:include flags.sexp)))
   (wrapped     false))
 
 (rule
@@ -44,3 +46,11 @@
     (system
       "curl https://raw.githubusercontent.com/spdx/license-list-data/master/json/exceptions.json |
        jq -rc '.exceptions | map(\"  \\\"\" + .licenseExceptionId + \"\\\";\") | join(\"\\n\")'"))))
+
+(rule
+  (with-stdout-to flags.ml
+    (echo "print_string (if String.sub Sys.ocaml_version 0 5 = \"4.02.\" then \"(-w -50)\" else \"()\")")))
+
+(rule
+  (with-stdout-to flags.sexp
+    (run ocaml %{dep:flags.ml})))
diff --git a/src_ext/Makefile b/src_ext/Makefile
index 4e76946ce3f..b075f10f4cf 100644
--- a/src_ext/Makefile
+++ b/src_ext/Makefile
@@ -121,6 +121,7 @@ build-pkg: clone-pkg $(PKG_EXTS:=.pkgbuild)
 ext-ignore:
 	@echo "; This file is automatically generated" > dune
 	@echo "(dirs :standard \ dune-local $(filter-out dune-local $(SRC_EXTS),$(PKG_EXTS)))" >> dune
+	@echo "(vendored_dirs $(SRC_EXTS))" >> dune
 
 clone: $(DUNE_CLONE) $(SRC_EXTS:=.stamp) | ext-ignore
 	@
diff --git a/src_ext/dune-dose3-algo b/src_ext/dune-dose3-algo
index e6d8d3b64e8..cc0b6f31680 100644
--- a/src_ext/dune-dose3-algo
+++ b/src_ext/dune-dose3-algo
@@ -1,7 +1,8 @@
 (library
   (name algo)
   (public_name dose3.algo)
-  (flags :standard -w -3)
+  ; -no-strict-sequence not added until 4.03!
+  (flags (:standard \ -strict-sequence) -w -3)
   (modules (:standard \ tests bench))
   (libraries dose3.common ocamlgraph)
   (preprocess (action (run %{bin:cppo} -D "OCAMLGRAPHVERSION 200" -V OCAML:%{ocaml_version} %{input-file}))))
diff --git a/src_ext/dune-extlib-src b/src_ext/dune-extlib-src
index ec66eb87a28..3ac56dad5d5 100644
--- a/src_ext/dune-extlib-src
+++ b/src_ext/dune-extlib-src
@@ -1,7 +1,8 @@
 (library
   (name extlib)
   (public_name extlib)
-  (flags :standard -w -3)
+  ; -no-strict-sequence not added until 4.03!
+  (flags (:standard \ -strict-sequence) -w -3)
   (modules (:standard \ configure install uChar uTF8))
   (preprocess (action (run %{bin:cppo} %{read-lines:compat-level} %{input-file})))
   (wrapped false))
diff --git a/tests/reftests/run.ml b/tests/reftests/run.ml
index f1add61a315..af4e14f3021 100644
--- a/tests/reftests/run.ml
+++ b/tests/reftests/run.ml
@@ -124,11 +124,6 @@ let rec waitpid pid =
 
 exception Command_failure of int * string * string
 
-let str_replace filters s =
-  List.fold_left (fun s (re, by) ->
-      Re.replace_string (Re.compile re) ~by s)
-    s filters
-
 let str_replace_path ?(escape=false) whichway filters s =
   let escape =
     if escape then Re.(replace_string (compile @@ char '\\') ~by:"\\\\")
@@ -300,11 +295,6 @@ module Parse = struct
       rep space;
     ]
 
-  let re_cmd =
-    seq [group re_str_atom;
-         rep space;
-         rep @@ seq [group re_str_atom; rep space]]
-
   let command str =
     if str.[0] = '<' && str.[String.length str - 1] = '>' then
       let f = String.sub str 1 (String.length str - 2) in
@@ -422,7 +412,7 @@ let rec list_remove x = function
   | [] -> []
   | y :: r -> if x = y then r else y :: list_remove x r
 
-let run_test t ?(vars=[]) ~opam =
+let run_test ?(vars=[]) ~opam t =
   let opamroot0 = Filename.concat (Sys.getcwd ()) ("root-"^t.repo_hash) in
   with_temp_dir @@ fun dir ->
   let old_cwd = Sys.getcwd () in
@@ -473,7 +463,7 @@ let run_test t ?(vars=[]) ~opam =
                  if rl = el then (print_endline el; diffl acc r e)
                  else if expect_has rl then diffl (rl::acc) r (el :: e)
                  else (print_endline rl; diffl acc r (el :: e))
-               | [], e::el ->
+               | [], _::el ->
                  diffl acc [] el
                | r, [] ->
                  assert (acc = []); List.iter print_endline r