From 25b0b4d0cc046b575bbd8f51e96877b0eb58aa58 Mon Sep 17 00:00:00 2001 From: Ambre Austen Suhamy Date: Mon, 7 Apr 2025 14:30:24 +0200 Subject: [PATCH 1/7] Don't use XDG_CACHE_HOME directly, use DUNE_CACHE_ROOT instead Signed-off-by: Ambre Austen Suhamy --- src/dune_pkg/dune | 1 + src/dune_pkg/rev_store.ml | 4 +--- src/dune_rules/pkg_toolchain.ml | 8 ++------ src/dune_rules/pkg_toolchain.mli | 2 +- .../test-cases/pkg/opam-repository-download.t | 5 +++-- .../test-cases/pkg/rev-store-lock-linux.t | 4 ++-- .../test-cases/pkg/toolchain-installation.t | 14 +++++++------- 7 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/dune_pkg/dune b/src/dune_pkg/dune index c3c4ee0e015..7a1c606f935 100644 --- a/src/dune_pkg/dune +++ b/src/dune_pkg/dune @@ -11,6 +11,7 @@ fiber_util chrome_trace dune_engine + dune_cache_storage dune_util dune_stats dune_lang diff --git a/src/dune_pkg/rev_store.ml b/src/dune_pkg/rev_store.ml index cc8d22fa57c..65e3225d621 100644 --- a/src/dune_pkg/rev_store.ml +++ b/src/dune_pkg/rev_store.ml @@ -1223,9 +1223,7 @@ let content_of_files t files = let get = Fiber.Lazy.create (fun () -> let dir = - Path.L.relative - (Path.of_string (Xdg.cache_dir (Lazy.force Dune_util.xdg))) - [ "dune"; "git-repo" ] + Path.L.relative (Lazy.force Dune_cache_storage.Layout.root_dir) [ "git-repo" ] in load_or_create ~dir) |> Fiber.Lazy.force diff --git a/src/dune_rules/pkg_toolchain.ml b/src/dune_rules/pkg_toolchain.ml index b83ac13c771..83a0125385e 100644 --- a/src/dune_rules/pkg_toolchain.ml +++ b/src/dune_rules/pkg_toolchain.ml @@ -2,13 +2,9 @@ open Import let base_dir () = let cache_dir = - Lazy.force Dune_util.xdg |> Xdg.cache_dir |> Path.Outside_build_dir.of_string - in - let path = - Path.Outside_build_dir.relative - (Path.Outside_build_dir.relative cache_dir "dune") - "toolchains" + Lazy.force Dune_cache_storage.Layout.root_dir |> Path.as_outside_build_dir_exn in + let path = Path.Outside_build_dir.relative cache_dir "toolchains" in (let path = Path.outside_build_dir path in if not (Path.Untracked.exists path) then Path.mkdir_p path; if not (Path.Untracked.is_directory path) diff --git a/src/dune_rules/pkg_toolchain.mli b/src/dune_rules/pkg_toolchain.mli index 5e22008f982..c81306f4222 100644 --- a/src/dune_rules/pkg_toolchain.mli +++ b/src/dune_rules/pkg_toolchain.mli @@ -21,7 +21,7 @@ val is_compiler_and_toolchains_enabled : Package.Name.t -> bool (** Returns the path to the directory containing the given package within the toolchain directory. This will be something like - $XDG_CACHE_HOME/dune/toolchains/ocaml-base-compiler.5.2.1.XXXXXXXX where + $DUNE_CACHE_ROOT/toolchains/ocaml-base-compiler.5.2.1.XXXXXXXX where XXXXXXXX is a hash of the package's lockfile. *) val installation_prefix : Lock_dir.Pkg.t -> Path.Outside_build_dir.t diff --git a/test/blackbox-tests/test-cases/pkg/opam-repository-download.t b/test/blackbox-tests/test-cases/pkg/opam-repository-download.t index 7e26b086d37..36a76cc0580 100644 --- a/test/blackbox-tests/test-cases/pkg/opam-repository-download.t +++ b/test/blackbox-tests/test-cases/pkg/opam-repository-download.t @@ -3,6 +3,7 @@ Helper shell function that generates an opam file for a package: $ . ../git-helpers.sh $ . ./helpers.sh $ mkrepo + $ export DUNE_CACHE_ROOT=$(pwd)/.cache Make a mock repo tarball that will get used by dune to download the package @@ -35,8 +36,8 @@ Make a mock repo tarball that will get used by dune to download the package Our cache folder should be populated with a revision store: - $ find $XDG_CACHE_HOME | grep HEAD | sort - $TESTCASE_ROOT/.cache/dune/git-repo/HEAD + $ find $DUNE_CACHE_ROOT | grep HEAD | sort + $TESTCASE_ROOT/.cache/git-repo/HEAD Make sure lock.dune contains the repo hash: diff --git a/test/blackbox-tests/test-cases/pkg/rev-store-lock-linux.t b/test/blackbox-tests/test-cases/pkg/rev-store-lock-linux.t index b61ea373c10..9302d5da28f 100644 --- a/test/blackbox-tests/test-cases/pkg/rev-store-lock-linux.t +++ b/test/blackbox-tests/test-cases/pkg/rev-store-lock-linux.t @@ -29,8 +29,8 @@ We set the project up to depend on `foo` There should be some kind of error message if getting the revision store lock fails (simulated here with a failing flock(2) call): - $ XDG_CACHE_HOME=$(pwd)/dune-workspace-cache strace -e inject=flock:error=EBADFD -o /dev/null dune pkg lock + $ DUNE_CACHE_ROOT=$(pwd)/dune-workspace-cache strace -e inject=flock:error=EBADFD -o /dev/null dune pkg lock Error: Failed to get a lock for the revision store at - $TESTCASE_ROOT/dune-workspace-cache/dune/rev-store.lock: + $TESTCASE_ROOT/dune-workspace-cache/rev-store.lock: File descriptor in bad state [1] diff --git a/test/blackbox-tests/test-cases/pkg/toolchain-installation.t b/test/blackbox-tests/test-cases/pkg/toolchain-installation.t index 4978e700cc4..3f5e8d399ca 100644 --- a/test/blackbox-tests/test-cases/pkg/toolchain-installation.t +++ b/test/blackbox-tests/test-cases/pkg/toolchain-installation.t @@ -78,12 +78,12 @@ name so the output is consistent across test runs. Attempt to build the project. This will fail due to the fake compiler but the fake compiler will end up installed as a toolchain package. - $ XDG_CACHE_HOME=$PWD/fake-cache DUNE_CONFIG__TOOLCHAINS=enabled build_pkg ocaml-base-compiler 2>&1 | remove_hash + $ DUNE_CACHE_ROOT=$PWD/fake-cache DUNE_CONFIG__TOOLCHAINS=enabled build_pkg ocaml-base-compiler 2>&1 | remove_hash Enumerate the contents of the fake toolchains directory: - $ find fake-cache/dune/toolchains | sort | remove_hash - fake-cache/dune/toolchains - fake-cache/dune/toolchains/ocaml-base-compiler.1-HASH - fake-cache/dune/toolchains/ocaml-base-compiler.1-HASH/target - fake-cache/dune/toolchains/ocaml-base-compiler.1-HASH/target/bin - fake-cache/dune/toolchains/ocaml-base-compiler.1-HASH/target/bin/ocamlc + $ find fake-cache/toolchains | sort | remove_hash + fake-cache/toolchains + fake-cache/toolchains/ocaml-base-compiler.1-HASH + fake-cache/toolchains/ocaml-base-compiler.1-HASH/target + fake-cache/toolchains/ocaml-base-compiler.1-HASH/target/bin + fake-cache/toolchains/ocaml-base-compiler.1-HASH/target/bin/ocamlc From c2cd561b8949c49629cb8011d8bfd1b6e2748331 Mon Sep 17 00:00:00 2001 From: Ambre Austen Suhamy Date: Fri, 7 Nov 2025 16:54:11 +0100 Subject: [PATCH 2/7] Expand test to show difference between xdg and dune_cache_dir Signed-off-by: Ambre Austen Suhamy --- .../test-cases/pkg/toolchain-installation.t | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/test/blackbox-tests/test-cases/pkg/toolchain-installation.t b/test/blackbox-tests/test-cases/pkg/toolchain-installation.t index 3f5e8d399ca..1afb9900141 100644 --- a/test/blackbox-tests/test-cases/pkg/toolchain-installation.t +++ b/test/blackbox-tests/test-cases/pkg/toolchain-installation.t @@ -76,13 +76,25 @@ name so the output is consistent across test runs. > sed 's/\(ocaml-base-compiler.1-\)[^/]*/\1HASH/' > } -Attempt to build the project. This will fail due to the fake compiler +Attempt to build the project. This will fail due to the fake compiler, but the fake compiler will end up installed as a toolchain package. +Also test that XDG_CACHE_HOME is respected. + $ XDG_CACHE_HOME=$PWD/fake-cache DUNE_CONFIG__TOOLCHAINS=enabled build_pkg ocaml-base-compiler 2>&1 | remove_hash + +Enumerate the contents of the fake toolchains directory: + $ find fake-cache/dune/db/toolchains/ | sort | remove_hash + fake-cache/dune/db/toolchains/ + fake-cache/dune/db/toolchains/ocaml-base-compiler.1-HASH + fake-cache/dune/db/toolchains/ocaml-base-compiler.1-HASH/target + fake-cache/dune/db/toolchains/ocaml-base-compiler.1-HASH/target/bin + fake-cache/dune/db/toolchains/ocaml-base-compiler.1-HASH/target/bin/ocamlc + +Also test that DUNE_CACHE_ROOT is respected. $ DUNE_CACHE_ROOT=$PWD/fake-cache DUNE_CONFIG__TOOLCHAINS=enabled build_pkg ocaml-base-compiler 2>&1 | remove_hash Enumerate the contents of the fake toolchains directory: - $ find fake-cache/toolchains | sort | remove_hash - fake-cache/toolchains + $ find fake-cache/toolchains/ | sort | remove_hash + fake-cache/toolchains/ fake-cache/toolchains/ocaml-base-compiler.1-HASH fake-cache/toolchains/ocaml-base-compiler.1-HASH/target fake-cache/toolchains/ocaml-base-compiler.1-HASH/target/bin From c13326fab9dda32ce61bf3c4996df55303923a89 Mon Sep 17 00:00:00 2001 From: Ambre Austen Suhamy Date: Thu, 13 Nov 2025 11:14:36 +0100 Subject: [PATCH 3/7] Implement 'compromise' option: DUNE_CACHE_HOME Signed-off-by: Ambre Austen Suhamy --- bin/common.ml | 19 +++++-- src/dune_cache_storage/dune_cache_storage.ml | 2 +- src/dune_cache_storage/layout.ml | 51 ++++++++++++++----- src/dune_cache_storage/layout.mli | 15 +++++- src/dune_pkg/rev_store.ml | 4 +- src/dune_rules/pkg_toolchain.ml | 7 ++- src/dune_rules/pkg_toolchain.mli | 2 +- .../test-cases/pkg/opam-repository-download.t | 5 +- .../test-cases/pkg/rev-store-lock-linux.t | 4 +- .../test-cases/pkg/toolchain-installation.t | 28 +++++----- 10 files changed, 92 insertions(+), 45 deletions(-) diff --git a/bin/common.ml b/bin/common.ml index 97db9c619b4..d222d30ef98 100644 --- a/bin/common.ml +++ b/bin/common.ml @@ -1380,8 +1380,18 @@ let init_with_root ~(root : Workspace_root.t) (builder : Builder.t) = ]; Log.info [ Pp.textf - "Shared cache location: %s" - (Path.to_string (Lazy.force Dune_cache_storage.Layout.root_dir)) + "Shared build cache location: %s" + (Path.to_string (Lazy.force Dune_cache_storage.Layout.build_cache_dir)) + ]; + Log.info + [ Pp.textf + "Toolchains cache location: %s" + (Path.to_string (Lazy.force Dune_cache_storage.Layout.toolchains_dir)) + ]; + Log.info + [ Pp.textf + "Revivision store cache location: %s" + (Path.to_string (Lazy.force Dune_cache_storage.Layout.rev_store)) ]; Dune_rules.Main.init ~stats:c.stats @@ -1505,8 +1515,11 @@ let envs = ~doc:"If different than $(b,0), ANSI colors should be enabled no matter what." "CLICOLOR_FORCE" ; info - "DUNE_CACHE_ROOT" ~doc:"If set, determines the location of the machine-global shared cache." + "DUNE_CACHE_ROOT" + ; info + ~doc:"If set, determines the location of all the different caches used by dune." + "DUNE_CACHE_HOME" ] ;; diff --git a/src/dune_cache_storage/dune_cache_storage.ml b/src/dune_cache_storage/dune_cache_storage.ml index b30776ac141..ea46e0477f7 100644 --- a/src/dune_cache_storage/dune_cache_storage.ml +++ b/src/dune_cache_storage/dune_cache_storage.ml @@ -376,5 +376,5 @@ let clear () = rm_rf (Lazy.force Layout.temp_dir); (* Do not catch errors when deleting the root directory so that they are reported to the user. *) - Path.rmdir (Lazy.force Layout.root_dir) + Path.rmdir (Lazy.force Layout.build_cache_dir) ;; diff --git a/src/dune_cache_storage/layout.ml b/src/dune_cache_storage/layout.ml index ac695019326..6252ceb85fe 100644 --- a/src/dune_cache_storage/layout.ml +++ b/src/dune_cache_storage/layout.ml @@ -1,25 +1,50 @@ open Stdune open Import -let default_root_dir = +let ( / ) = Path.relative + +(** The default directory of all caches. Defaults to [$XDG_CACHE_HOME/dune]. + Not to be used directly, add a layer beforehand. *) +let default_cache_dir = lazy (let cache_dir = Xdg.cache_dir (Lazy.force Dune_util.xdg) in - Path.L.relative (Path.of_filename_relative_to_initial_cwd cache_dir) [ "dune"; "db" ]) + Path.of_filename_relative_to_initial_cwd cache_dir / "dune") +;; + +let check_absolute var path = + if Filename.is_relative path + then + User_error.raise + [ Pp.paragraphf "$%s should be an absolute path, but is %S" var path ] ;; -let root_dir = +(** The home directory for all the caches. Defaults to [default_cache_dir], + or uses [$DUNE_CACHE_HOME] if set. *) +let home_dir = + lazy + (let var = "DUNE_CACHE_HOME" in + match Sys.getenv_opt var with + | None -> Lazy.force default_cache_dir + | Some path -> + check_absolute var path; + Path.external_ (Path.External.of_string path)) +;; + +(** The directory of the build cache. Defaults to [home_dir/db], + or uses [$DUNE_CACHE_ROOT] if set. *) +let build_cache_dir = lazy (let var = "DUNE_CACHE_ROOT" in match Sys.getenv_opt var with - | None -> Lazy.force default_root_dir + | None -> Lazy.force home_dir / "db" | Some path -> - if Filename.is_relative path - then failwith (sprintf "%s should be an absolute path, but is %s" var path); - Path.of_filename_relative_to_initial_cwd path) + check_absolute var path; + Path.external_ (Path.External.of_string path)) ;; -let ( / ) = Path.relative -let temp_dir = lazy (Lazy.force root_dir / "temp") +let rev_store = lazy (Lazy.force home_dir / "git-repo") +let toolchains_dir = lazy (Lazy.force home_dir / "toolchains") +let temp_dir = lazy (Lazy.force build_cache_dir / "temp") let cache_path ~dir ~hex = let two_first_chars = sprintf "%c%c" hex.[0] hex.[1] in @@ -52,13 +77,15 @@ let list_entries ~storage = module Versioned = struct let metadata_storage_dir t = - lazy (Lazy.force root_dir / "meta" / Version.Metadata.to_string t) + lazy (Lazy.force build_cache_dir / "meta" / Version.Metadata.to_string t) ;; - let file_storage_dir t = lazy (Lazy.force root_dir / "files" / Version.File.to_string t) + let file_storage_dir t = + lazy (Lazy.force build_cache_dir / "files" / Version.File.to_string t) + ;; let value_storage_dir t = - lazy (Lazy.force root_dir / "values" / Version.Value.to_string t) + lazy (Lazy.force build_cache_dir / "values" / Version.Value.to_string t) ;; let metadata_path t ~rule_or_action_digest = diff --git a/src/dune_cache_storage/layout.mli b/src/dune_cache_storage/layout.mli index 73798fc94bf..d44348e2ab9 100644 --- a/src/dune_cache_storage/layout.mli +++ b/src/dune_cache_storage/layout.mli @@ -8,8 +8,19 @@ open Stdune open Import -(** The path to the root directory of the cache. *) -val root_dir : Path.t Lazy.t +(** The home directory of all the caches. + Uses [$DUNE_CACHE_HOME] if set. *) +val home_dir : Path.t Lazy.t + +(** The directory of the build cache. Defaults to [home_dir/db], or + uses [$DUNE_CACHE_ROOT] if set. *) +val build_cache_dir : Path.t Lazy.t + +(** The cache for the git repository. Is set to [home_dir/git-repo]. *) +val rev_store : Path.t Lazy.t + +(** The cache for the toolchains. Is set to [home_dir/toolchains]. *) +val toolchains_dir : Path.t Lazy.t (** Create a few subdirectories in [root_dir]. We expose this function because we don't want to modify the file system when the cache is disabled. diff --git a/src/dune_pkg/rev_store.ml b/src/dune_pkg/rev_store.ml index 65e3225d621..41caa1b9ef8 100644 --- a/src/dune_pkg/rev_store.ml +++ b/src/dune_pkg/rev_store.ml @@ -1222,9 +1222,7 @@ let content_of_files t files = let get = Fiber.Lazy.create (fun () -> - let dir = - Path.L.relative (Lazy.force Dune_cache_storage.Layout.root_dir) [ "git-repo" ] - in + let dir = Lazy.force Dune_cache_storage.Layout.rev_store in load_or_create ~dir) |> Fiber.Lazy.force ;; diff --git a/src/dune_rules/pkg_toolchain.ml b/src/dune_rules/pkg_toolchain.ml index 83a0125385e..6fc915f608a 100644 --- a/src/dune_rules/pkg_toolchain.ml +++ b/src/dune_rules/pkg_toolchain.ml @@ -2,16 +2,15 @@ open Import let base_dir () = let cache_dir = - Lazy.force Dune_cache_storage.Layout.root_dir |> Path.as_outside_build_dir_exn + Lazy.force Dune_cache_storage.Layout.toolchains_dir |> Path.as_outside_build_dir_exn in - let path = Path.Outside_build_dir.relative cache_dir "toolchains" in - (let path = Path.outside_build_dir path in + (let path = Path.outside_build_dir cache_dir in if not (Path.Untracked.exists path) then Path.mkdir_p path; if not (Path.Untracked.is_directory path) then User_error.raise [ Pp.textf "Expected %s to be a directory but it is not." (Path.to_string path) ]); - path + cache_dir ;; let pkg_dir (pkg : Dune_pkg.Lock_dir.Pkg.t) = diff --git a/src/dune_rules/pkg_toolchain.mli b/src/dune_rules/pkg_toolchain.mli index c81306f4222..1c1d1174f4d 100644 --- a/src/dune_rules/pkg_toolchain.mli +++ b/src/dune_rules/pkg_toolchain.mli @@ -21,7 +21,7 @@ val is_compiler_and_toolchains_enabled : Package.Name.t -> bool (** Returns the path to the directory containing the given package within the toolchain directory. This will be something like - $DUNE_CACHE_ROOT/toolchains/ocaml-base-compiler.5.2.1.XXXXXXXX where + [Layout.toolchains_dir/ocaml-base-compiler.5.2.1.XXXXXXXX] where XXXXXXXX is a hash of the package's lockfile. *) val installation_prefix : Lock_dir.Pkg.t -> Path.Outside_build_dir.t diff --git a/test/blackbox-tests/test-cases/pkg/opam-repository-download.t b/test/blackbox-tests/test-cases/pkg/opam-repository-download.t index 36a76cc0580..7e26b086d37 100644 --- a/test/blackbox-tests/test-cases/pkg/opam-repository-download.t +++ b/test/blackbox-tests/test-cases/pkg/opam-repository-download.t @@ -3,7 +3,6 @@ Helper shell function that generates an opam file for a package: $ . ../git-helpers.sh $ . ./helpers.sh $ mkrepo - $ export DUNE_CACHE_ROOT=$(pwd)/.cache Make a mock repo tarball that will get used by dune to download the package @@ -36,8 +35,8 @@ Make a mock repo tarball that will get used by dune to download the package Our cache folder should be populated with a revision store: - $ find $DUNE_CACHE_ROOT | grep HEAD | sort - $TESTCASE_ROOT/.cache/git-repo/HEAD + $ find $XDG_CACHE_HOME | grep HEAD | sort + $TESTCASE_ROOT/.cache/dune/git-repo/HEAD Make sure lock.dune contains the repo hash: diff --git a/test/blackbox-tests/test-cases/pkg/rev-store-lock-linux.t b/test/blackbox-tests/test-cases/pkg/rev-store-lock-linux.t index 9302d5da28f..b61ea373c10 100644 --- a/test/blackbox-tests/test-cases/pkg/rev-store-lock-linux.t +++ b/test/blackbox-tests/test-cases/pkg/rev-store-lock-linux.t @@ -29,8 +29,8 @@ We set the project up to depend on `foo` There should be some kind of error message if getting the revision store lock fails (simulated here with a failing flock(2) call): - $ DUNE_CACHE_ROOT=$(pwd)/dune-workspace-cache strace -e inject=flock:error=EBADFD -o /dev/null dune pkg lock + $ XDG_CACHE_HOME=$(pwd)/dune-workspace-cache strace -e inject=flock:error=EBADFD -o /dev/null dune pkg lock Error: Failed to get a lock for the revision store at - $TESTCASE_ROOT/dune-workspace-cache/rev-store.lock: + $TESTCASE_ROOT/dune-workspace-cache/dune/rev-store.lock: File descriptor in bad state [1] diff --git a/test/blackbox-tests/test-cases/pkg/toolchain-installation.t b/test/blackbox-tests/test-cases/pkg/toolchain-installation.t index 1afb9900141..56ed8c3fb20 100644 --- a/test/blackbox-tests/test-cases/pkg/toolchain-installation.t +++ b/test/blackbox-tests/test-cases/pkg/toolchain-installation.t @@ -82,20 +82,20 @@ Also test that XDG_CACHE_HOME is respected. $ XDG_CACHE_HOME=$PWD/fake-cache DUNE_CONFIG__TOOLCHAINS=enabled build_pkg ocaml-base-compiler 2>&1 | remove_hash Enumerate the contents of the fake toolchains directory: - $ find fake-cache/dune/db/toolchains/ | sort | remove_hash - fake-cache/dune/db/toolchains/ - fake-cache/dune/db/toolchains/ocaml-base-compiler.1-HASH - fake-cache/dune/db/toolchains/ocaml-base-compiler.1-HASH/target - fake-cache/dune/db/toolchains/ocaml-base-compiler.1-HASH/target/bin - fake-cache/dune/db/toolchains/ocaml-base-compiler.1-HASH/target/bin/ocamlc + $ find fake-cache/dune/toolchains | sort | remove_hash + fake-cache/dune/toolchains + fake-cache/dune/toolchains/ocaml-base-compiler.1-HASH + fake-cache/dune/toolchains/ocaml-base-compiler.1-HASH/target + fake-cache/dune/toolchains/ocaml-base-compiler.1-HASH/target/bin + fake-cache/dune/toolchains/ocaml-base-compiler.1-HASH/target/bin/ocamlc -Also test that DUNE_CACHE_ROOT is respected. - $ DUNE_CACHE_ROOT=$PWD/fake-cache DUNE_CONFIG__TOOLCHAINS=enabled build_pkg ocaml-base-compiler 2>&1 | remove_hash +Also test that DUNE_CACHE_HOME is respected. + $ DUNE_CACHE_HOME=$PWD/other-fake-cache DUNE_CONFIG__TOOLCHAINS=enabled build_pkg ocaml-base-compiler 2>&1 | remove_hash Enumerate the contents of the fake toolchains directory: - $ find fake-cache/toolchains/ | sort | remove_hash - fake-cache/toolchains/ - fake-cache/toolchains/ocaml-base-compiler.1-HASH - fake-cache/toolchains/ocaml-base-compiler.1-HASH/target - fake-cache/toolchains/ocaml-base-compiler.1-HASH/target/bin - fake-cache/toolchains/ocaml-base-compiler.1-HASH/target/bin/ocamlc + $ find other-fake-cache/toolchains/ | sort | remove_hash + other-fake-cache/toolchains/ + other-fake-cache/toolchains/ocaml-base-compiler.1-HASH + other-fake-cache/toolchains/ocaml-base-compiler.1-HASH/target + other-fake-cache/toolchains/ocaml-base-compiler.1-HASH/target/bin + other-fake-cache/toolchains/ocaml-base-compiler.1-HASH/target/bin/ocamlc From f72319c88a7ad707429f4b828108b26c833db337 Mon Sep 17 00:00:00 2001 From: Ambre Austen Suhamy Date: Mon, 24 Nov 2025 17:32:54 +0100 Subject: [PATCH 4/7] Move revstore/toolchains cache out of `dune_cache_storage` and into `dune_util` Signed-off-by: Ambre Austen Suhamy --- bin/common.ml | 4 +-- src/dune_cache_storage/layout.ml | 51 +++++++++---------------------- src/dune_cache_storage/layout.mli | 16 +++------- src/dune_pkg/dune | 1 - src/dune_pkg/rev_store.ml | 2 +- src/dune_rules/pkg_toolchain.ml | 4 +-- src/dune_rules/pkg_toolchain.mli | 2 +- src/dune_util/dune_util.ml | 41 ++++++++++++++++++++++--- src/dune_util/dune_util.mli | 35 +++++++++++++++++++++ 9 files changed, 95 insertions(+), 61 deletions(-) create mode 100644 src/dune_util/dune_util.mli diff --git a/bin/common.ml b/bin/common.ml index d222d30ef98..4abcfe5ab7a 100644 --- a/bin/common.ml +++ b/bin/common.ml @@ -1386,12 +1386,12 @@ let init_with_root ~(root : Workspace_root.t) (builder : Builder.t) = Log.info [ Pp.textf "Toolchains cache location: %s" - (Path.to_string (Lazy.force Dune_cache_storage.Layout.toolchains_dir)) + (Path.to_string (Lazy.force Dune_util.toolchains_dir)) ]; Log.info [ Pp.textf "Revivision store cache location: %s" - (Path.to_string (Lazy.force Dune_cache_storage.Layout.rev_store)) + (Path.to_string (Lazy.force Dune_util.rev_store)) ]; Dune_rules.Main.init ~stats:c.stats diff --git a/src/dune_cache_storage/layout.ml b/src/dune_cache_storage/layout.ml index 6252ceb85fe..5b65df398b2 100644 --- a/src/dune_cache_storage/layout.ml +++ b/src/dune_cache_storage/layout.ml @@ -3,47 +3,26 @@ open Import let ( / ) = Path.relative -(** The default directory of all caches. Defaults to [$XDG_CACHE_HOME/dune]. - Not to be used directly, add a layer beforehand. *) -let default_cache_dir = - lazy - (let cache_dir = Xdg.cache_dir (Lazy.force Dune_util.xdg) in - Path.of_filename_relative_to_initial_cwd cache_dir / "dune") -;; - -let check_absolute var path = - if Filename.is_relative path - then - User_error.raise - [ Pp.paragraphf "$%s should be an absolute path, but is %S" var path ] -;; - -(** The home directory for all the caches. Defaults to [default_cache_dir], - or uses [$DUNE_CACHE_HOME] if set. *) -let home_dir = - lazy - (let var = "DUNE_CACHE_HOME" in - match Sys.getenv_opt var with - | None -> Lazy.force default_cache_dir - | Some path -> - check_absolute var path; - Path.external_ (Path.External.of_string path)) -;; - -(** The directory of the build cache. Defaults to [home_dir/db], - or uses [$DUNE_CACHE_ROOT] if set. *) +(** The directory containing the build cache. + Uses [$DUNE_CACHE_ROOT] if set, or + [$DUNE_CACHE_HOME/db] if set, or + [Dune_util.default_cache_dir/db] otherwise. *) let build_cache_dir = lazy - (let var = "DUNE_CACHE_ROOT" in - match Sys.getenv_opt var with - | None -> Lazy.force home_dir / "db" + (let high_priority_var = "DUNE_CACHE_ROOT" in + match Sys.getenv_opt high_priority_var with | Some path -> - check_absolute var path; - Path.external_ (Path.External.of_string path)) + Dune_util.check_absolute ~var:high_priority_var ~path; + Path.external_ (Path.External.of_string path) + | None -> + let low_priority_var = "DUNE_CACHE_HOME" in + (match Sys.getenv_opt low_priority_var with + | Some path -> + Dune_util.check_absolute ~var:low_priority_var ~path; + Path.external_ (Path.External.of_string path) / "db" + | None -> Lazy.force Dune_util.default_cache_dir / "db")) ;; -let rev_store = lazy (Lazy.force home_dir / "git-repo") -let toolchains_dir = lazy (Lazy.force home_dir / "toolchains") let temp_dir = lazy (Lazy.force build_cache_dir / "temp") let cache_path ~dir ~hex = diff --git a/src/dune_cache_storage/layout.mli b/src/dune_cache_storage/layout.mli index d44348e2ab9..905fff3f2b6 100644 --- a/src/dune_cache_storage/layout.mli +++ b/src/dune_cache_storage/layout.mli @@ -8,20 +8,12 @@ open Stdune open Import -(** The home directory of all the caches. - Uses [$DUNE_CACHE_HOME] if set. *) -val home_dir : Path.t Lazy.t - -(** The directory of the build cache. Defaults to [home_dir/db], or - uses [$DUNE_CACHE_ROOT] if set. *) +(** The directory containing the build cache. + Uses [$DUNE_CACHE_ROOT] if set, or + [$DUNE_CACHE_HOME/db] if set, or + [Dune_util.default_cache_dir/db] otherwise. *) val build_cache_dir : Path.t Lazy.t -(** The cache for the git repository. Is set to [home_dir/git-repo]. *) -val rev_store : Path.t Lazy.t - -(** The cache for the toolchains. Is set to [home_dir/toolchains]. *) -val toolchains_dir : Path.t Lazy.t - (** Create a few subdirectories in [root_dir]. We expose this function because we don't want to modify the file system when the cache is disabled. diff --git a/src/dune_pkg/dune b/src/dune_pkg/dune index 7a1c606f935..c3c4ee0e015 100644 --- a/src/dune_pkg/dune +++ b/src/dune_pkg/dune @@ -11,7 +11,6 @@ fiber_util chrome_trace dune_engine - dune_cache_storage dune_util dune_stats dune_lang diff --git a/src/dune_pkg/rev_store.ml b/src/dune_pkg/rev_store.ml index 41caa1b9ef8..91e4bfa0eee 100644 --- a/src/dune_pkg/rev_store.ml +++ b/src/dune_pkg/rev_store.ml @@ -1222,7 +1222,7 @@ let content_of_files t files = let get = Fiber.Lazy.create (fun () -> - let dir = Lazy.force Dune_cache_storage.Layout.rev_store in + let dir = Lazy.force Dune_util.rev_store in load_or_create ~dir) |> Fiber.Lazy.force ;; diff --git a/src/dune_rules/pkg_toolchain.ml b/src/dune_rules/pkg_toolchain.ml index 6fc915f608a..c196e52a922 100644 --- a/src/dune_rules/pkg_toolchain.ml +++ b/src/dune_rules/pkg_toolchain.ml @@ -1,9 +1,7 @@ open Import let base_dir () = - let cache_dir = - Lazy.force Dune_cache_storage.Layout.toolchains_dir |> Path.as_outside_build_dir_exn - in + let cache_dir = Lazy.force Dune_util.toolchains_dir |> Path.as_outside_build_dir_exn in (let path = Path.outside_build_dir cache_dir in if not (Path.Untracked.exists path) then Path.mkdir_p path; if not (Path.Untracked.is_directory path) diff --git a/src/dune_rules/pkg_toolchain.mli b/src/dune_rules/pkg_toolchain.mli index 1c1d1174f4d..b82099b84ad 100644 --- a/src/dune_rules/pkg_toolchain.mli +++ b/src/dune_rules/pkg_toolchain.mli @@ -21,7 +21,7 @@ val is_compiler_and_toolchains_enabled : Package.Name.t -> bool (** Returns the path to the directory containing the given package within the toolchain directory. This will be something like - [Layout.toolchains_dir/ocaml-base-compiler.5.2.1.XXXXXXXX] where + [Dune_util.toolchains_dir/ocaml-base-compiler.5.2.1.XXXXXXXX] where XXXXXXXX is a hash of the package's lockfile. *) val installation_prefix : Lock_dir.Pkg.t -> Path.Outside_build_dir.t diff --git a/src/dune_util/dune_util.ml b/src/dune_util/dune_util.ml index 2741bd3e812..03cb9e74b3e 100644 --- a/src/dune_util/dune_util.ml +++ b/src/dune_util/dune_util.ml @@ -1,3 +1,8 @@ +module Action = Action +module Alias_name = Alias_name +module Build_path_prefix_map = Build_path_prefix_map0 +module Gc = Gc +module Global_lock = Global_lock module Log = Log module Persistent = Persistent module Report_error = Report_error @@ -5,11 +10,6 @@ module Stringlike = Stringlike module type Stringlike = Stringlike_intf.S -module Build_path_prefix_map = Build_path_prefix_map0 -module Global_lock = Global_lock -module Action = Action -module Alias_name = Alias_name -module Gc = Gc open Stdune let manual_xdg = ref None @@ -38,6 +38,37 @@ let override_xdg : Xdg.t -> unit = else manual_xdg := Some new_xdg ;; +let ( / ) = Path.relative + +(** The default directory of all caches (build and others), used when + environment variables are unset. + Set to [$XDG_CACHE_HOME/dune]. *) +let default_cache_dir = + lazy + (let cache_dir = Xdg.cache_dir (Lazy.force xdg) in + Path.of_filename_relative_to_initial_cwd cache_dir / "dune") +;; + +let check_absolute ~var ~path = + if Filename.is_relative path + then + User_error.raise + [ Pp.paragraphf "$%s should be an absolute path, but is %S" var path ] +;; + +let cache_home_dir = + lazy + (let var = "DUNE_CACHE_HOME" in + match Sys.getenv_opt var with + | Some path -> + check_absolute ~var ~path; + Path.external_ (Path.External.of_string path) + | None -> Lazy.force default_cache_dir) +;; + +let rev_store = lazy (Lazy.force cache_home_dir / "git-repo") +let toolchains_dir = lazy (Lazy.force cache_home_dir / "toolchains") + let frames_per_second () = match Dune_config.Config.(get threaded_console_frames_per_second) with | `Custom fps -> fps diff --git a/src/dune_util/dune_util.mli b/src/dune_util/dune_util.mli new file mode 100644 index 00000000000..6fa92b1861a --- /dev/null +++ b/src/dune_util/dune_util.mli @@ -0,0 +1,35 @@ +module Action = Action +module Alias_name = Alias_name +module Build_path_prefix_map = Build_path_prefix_map0 +module Gc = Gc +module Global_lock = Global_lock +module Log = Log +module Persistent = Persistent +module Report_error = Report_error +module Stringlike = Stringlike + +module type Stringlike = Stringlike_intf.S + +open Stdune + +val xdg : Xdg.t Lazy.t +val override_xdg : Xdg.t -> unit + +(** The default directory of all caches (build and others), used when + environment variables are unset. + Set to [$XDG_CACHE_HOME/dune]. *) +val default_cache_dir : Path.t Lazy.t + +val check_absolute : var:string -> path:string -> unit + +(** The cache for the git repository. + Uses [$DUNE_CACHE_HOME/git-repo] if set, or + [default_cache_dir/git-repo] otherwise. *) +val rev_store : Path.t Lazy.t + +(** The cache for the toolchains. + Uses [$DUNE_CACHE_HOME/toolchains] if set, or + [default_cache_dir/toolchains] otherwise. *) +val toolchains_dir : Path.t Lazy.t + +val frames_per_second : unit -> int From 8791924343e310fc39f2e657b6fc0a3910421cb1 Mon Sep 17 00:00:00 2001 From: Ambre Austen Suhamy Date: Tue, 25 Nov 2025 16:43:44 +0100 Subject: [PATCH 5/7] Bring in the 'rev_store' cache along into dune_util. Signed-off-by: Ambre Austen Suhamy --- bin/common.ml | 10 ---------- src/dune_cache_storage/layout.ml | 21 +++++++------------- src/dune_cache_storage/layout.mli | 5 ++--- src/dune_pkg/rev_store.ml | 33 ++++++++++++++++--------------- src/dune_rules/pkg_toolchain.ml | 23 +++++++++++++-------- src/dune_rules/pkg_toolchain.mli | 5 +++-- src/dune_util/dune_util.ml | 15 ++++---------- src/dune_util/dune_util.mli | 20 ++++--------------- 8 files changed, 52 insertions(+), 80 deletions(-) diff --git a/bin/common.ml b/bin/common.ml index 4abcfe5ab7a..03a440052cd 100644 --- a/bin/common.ml +++ b/bin/common.ml @@ -1383,16 +1383,6 @@ let init_with_root ~(root : Workspace_root.t) (builder : Builder.t) = "Shared build cache location: %s" (Path.to_string (Lazy.force Dune_cache_storage.Layout.build_cache_dir)) ]; - Log.info - [ Pp.textf - "Toolchains cache location: %s" - (Path.to_string (Lazy.force Dune_util.toolchains_dir)) - ]; - Log.info - [ Pp.textf - "Revivision store cache location: %s" - (Path.to_string (Lazy.force Dune_util.rev_store)) - ]; Dune_rules.Main.init ~stats:c.stats ~sandboxing_preference:config.sandboxing_preference diff --git a/src/dune_cache_storage/layout.ml b/src/dune_cache_storage/layout.ml index 5b65df398b2..8c03607fca9 100644 --- a/src/dune_cache_storage/layout.ml +++ b/src/dune_cache_storage/layout.ml @@ -3,24 +3,17 @@ open Import let ( / ) = Path.relative -(** The directory containing the build cache. - Uses [$DUNE_CACHE_ROOT] if set, or - [$DUNE_CACHE_HOME/db] if set, or - [Dune_util.default_cache_dir/db] otherwise. *) let build_cache_dir = lazy - (let high_priority_var = "DUNE_CACHE_ROOT" in - match Sys.getenv_opt high_priority_var with + (let var = "DUNE_CACHE_ROOT" in + match Sys.getenv_opt var with | Some path -> - Dune_util.check_absolute ~var:high_priority_var ~path; + if Filename.is_relative path + then + User_error.raise + [ Pp.paragraphf "$%s should be an absolute path, but is %S" var path ]; Path.external_ (Path.External.of_string path) - | None -> - let low_priority_var = "DUNE_CACHE_HOME" in - (match Sys.getenv_opt low_priority_var with - | Some path -> - Dune_util.check_absolute ~var:low_priority_var ~path; - Path.external_ (Path.External.of_string path) / "db" - | None -> Lazy.force Dune_util.default_cache_dir / "db")) + | None -> Lazy.force Dune_util.cache_home_dir / "db") ;; let temp_dir = lazy (Lazy.force build_cache_dir / "temp") diff --git a/src/dune_cache_storage/layout.mli b/src/dune_cache_storage/layout.mli index 905fff3f2b6..ea0beccc27d 100644 --- a/src/dune_cache_storage/layout.mli +++ b/src/dune_cache_storage/layout.mli @@ -9,9 +9,8 @@ open Stdune open Import (** The directory containing the build cache. - Uses [$DUNE_CACHE_ROOT] if set, or - [$DUNE_CACHE_HOME/db] if set, or - [Dune_util.default_cache_dir/db] otherwise. *) + Set to [$DUNE_CACHE_ROOT] if it exists, or + [Dune_util.cache_home_dir/db] otherwise. *) val build_cache_dir : Path.t Lazy.t (** Create a few subdirectories in [root_dir]. We expose this function because diff --git a/src/dune_pkg/rev_store.ml b/src/dune_pkg/rev_store.ml index 91e4bfa0eee..a462c0bca3d 100644 --- a/src/dune_pkg/rev_store.ml +++ b/src/dune_pkg/rev_store.ml @@ -145,33 +145,28 @@ module Cache = struct Dune_config.Config.make_toggle ~name:"rev_store_cache" ~default:`Disabled ;; - let cache_dir = + let revision_store_dir = lazy - (let path = - Path.L.relative - (Lazy.force Dune_util.xdg - |> Xdg.cache_dir - |> Path.Outside_build_dir.of_string - |> Path.outside_build_dir) - [ "dune"; "rev_store" ] - in + (let path = Path.relative (Lazy.force Dune_util.cache_home_dir) "rev_store" in let rev_store_cache = Dune_config.Config.get rev_store_cache in Dune_util.Log.info [ Pp.textf "Revision store cache: %s" (Dune_config.Config.Toggle.to_string rev_store_cache) ]; - match rev_store_cache, Path.mkdir_p path with - | `Enabled, () -> + (* Why do we create the directory in all cases, and not just when enabled? *) + Path.mkdir_p path; + match rev_store_cache with + | `Enabled -> Dune_util.Log.info [ Pp.textf "Revision store cache location: %s" (Path.to_string path) ]; Some path - | `Disabled, () -> None) + | `Disabled -> None) ;; let db = lazy - (Lazy.force cache_dir + (Lazy.force revision_store_dir |> Option.map ~f:(fun path -> Lmdb.Env.create ~map_size:(Int64.to_int 5_000_000_000L) (* 5 GB *) @@ -1220,9 +1215,15 @@ let content_of_files t files = | None -> Cache.Key.Map.find_exn to_write key) ;; +let git_repo_dir = + lazy + (let dir = Path.relative (Lazy.force Dune_util.cache_home_dir) "git-repo" in + Dune_util.Log.info + [ Pp.textf "Git repository cache location: %s" (Path.to_string dir) ]; + dir) +;; + let get = - Fiber.Lazy.create (fun () -> - let dir = Lazy.force Dune_util.rev_store in - load_or_create ~dir) + Fiber.Lazy.create (fun () -> load_or_create ~dir:(Lazy.force git_repo_dir)) |> Fiber.Lazy.force ;; diff --git a/src/dune_rules/pkg_toolchain.ml b/src/dune_rules/pkg_toolchain.ml index c196e52a922..c7f2d249b55 100644 --- a/src/dune_rules/pkg_toolchain.ml +++ b/src/dune_rules/pkg_toolchain.ml @@ -1,14 +1,21 @@ open Import +let base_dir = + lazy + (let dir = Path.relative (Lazy.force Dune_util.cache_home_dir) "toolchains" in + Dune_util.Log.info [ Pp.textf "Toolchains cache location: %s" (Path.to_string dir) ]; + Path.as_outside_build_dir_exn dir) +;; + let base_dir () = - let cache_dir = Lazy.force Dune_util.toolchains_dir |> Path.as_outside_build_dir_exn in - (let path = Path.outside_build_dir cache_dir in - if not (Path.Untracked.exists path) then Path.mkdir_p path; - if not (Path.Untracked.is_directory path) - then - User_error.raise - [ Pp.textf "Expected %s to be a directory but it is not." (Path.to_string path) ]); - cache_dir + let base_dir = Lazy.force base_dir in + let path = Path.outside_build_dir base_dir in + if not (Path.Untracked.exists path) then Path.mkdir_p path; + if not (Path.Untracked.is_directory path) + then + User_error.raise + [ Pp.textf "Expected %s to be a directory but it is not." (Path.to_string path) ]; + base_dir ;; let pkg_dir (pkg : Dune_pkg.Lock_dir.Pkg.t) = diff --git a/src/dune_rules/pkg_toolchain.mli b/src/dune_rules/pkg_toolchain.mli index b82099b84ad..d6b91169e5c 100644 --- a/src/dune_rules/pkg_toolchain.mli +++ b/src/dune_rules/pkg_toolchain.mli @@ -1,7 +1,8 @@ open Import (** The path to the directory that will contain all toolchain - versions. Creates the directory if it doesn't already exist. *) + versions. Creates the directory if it doesn't already exist. + Set to [Dune_util.cache_home_dir/toolchains]. *) val base_dir : unit -> Path.Outside_build_dir.t (** Dune will download and build the ocaml-base-compiler and @@ -21,7 +22,7 @@ val is_compiler_and_toolchains_enabled : Package.Name.t -> bool (** Returns the path to the directory containing the given package within the toolchain directory. This will be something like - [Dune_util.toolchains_dir/ocaml-base-compiler.5.2.1.XXXXXXXX] where + [base_dir/ocaml-base-compiler.5.2.1.XXXXXXXX] where XXXXXXXX is a hash of the package's lockfile. *) val installation_prefix : Lock_dir.Pkg.t -> Path.Outside_build_dir.t diff --git a/src/dune_util/dune_util.ml b/src/dune_util/dune_util.ml index 03cb9e74b3e..0619fbef9a4 100644 --- a/src/dune_util/dune_util.ml +++ b/src/dune_util/dune_util.ml @@ -49,26 +49,19 @@ let default_cache_dir = Path.of_filename_relative_to_initial_cwd cache_dir / "dune") ;; -let check_absolute ~var ~path = - if Filename.is_relative path - then - User_error.raise - [ Pp.paragraphf "$%s should be an absolute path, but is %S" var path ] -;; - let cache_home_dir = lazy (let var = "DUNE_CACHE_HOME" in match Sys.getenv_opt var with | Some path -> - check_absolute ~var ~path; + if Filename.is_relative path + then + User_error.raise + [ Pp.paragraphf "$%s should be an absolute path, but is %S" var path ]; Path.external_ (Path.External.of_string path) | None -> Lazy.force default_cache_dir) ;; -let rev_store = lazy (Lazy.force cache_home_dir / "git-repo") -let toolchains_dir = lazy (Lazy.force cache_home_dir / "toolchains") - let frames_per_second () = match Dune_config.Config.(get threaded_console_frames_per_second) with | `Custom fps -> fps diff --git a/src/dune_util/dune_util.mli b/src/dune_util/dune_util.mli index 6fa92b1861a..f48a14cad45 100644 --- a/src/dune_util/dune_util.mli +++ b/src/dune_util/dune_util.mli @@ -15,21 +15,9 @@ open Stdune val xdg : Xdg.t Lazy.t val override_xdg : Xdg.t -> unit -(** The default directory of all caches (build and others), used when - environment variables are unset. - Set to [$XDG_CACHE_HOME/dune]. *) -val default_cache_dir : Path.t Lazy.t - -val check_absolute : var:string -> path:string -> unit - -(** The cache for the git repository. - Uses [$DUNE_CACHE_HOME/git-repo] if set, or - [default_cache_dir/git-repo] otherwise. *) -val rev_store : Path.t Lazy.t - -(** The cache for the toolchains. - Uses [$DUNE_CACHE_HOME/toolchains] if set, or - [default_cache_dir/toolchains] otherwise. *) -val toolchains_dir : Path.t Lazy.t +(** The directory containing all caches (build and others). + Set to [$DUNE_CACHE_HOME] if it exists, or + [$XDG_CACHE_HOME/dune] otherwise. *) +val cache_home_dir : Path.t Lazy.t val frames_per_second : unit -> int From 4de22992f30b7a466d3daa7952a99d8b709b3269 Mon Sep 17 00:00:00 2001 From: Ambre Austen Suhamy Date: Tue, 25 Nov 2025 16:43:44 +0100 Subject: [PATCH 6/7] Clarify in bin/common the different DUNE_CACHE_X variables Signed-off-by: Ambre Austen Suhamy --- bin/common.ml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/bin/common.ml b/bin/common.ml index 03a440052cd..48b8894e5ae 100644 --- a/bin/common.ml +++ b/bin/common.ml @@ -1505,11 +1505,15 @@ let envs = ~doc:"If different than $(b,0), ANSI colors should be enabled no matter what." "CLICOLOR_FORCE" ; info - ~doc:"If set, determines the location of the machine-global shared cache." - "DUNE_CACHE_ROOT" - ; info - ~doc:"If set, determines the location of all the different caches used by dune." + ~doc: + "If set, determines the location of all the different caches used by dune. \ + Defaults to XDG_CACHE_HOME/dune if unset." "DUNE_CACHE_HOME" + ; info + ~doc: + "If set, determines the location of the machine-global shared cache. This is \ + the main build cache used by dune. Defaults to DUNE_CACHE_HOME/db if unset" + "DUNE_CACHE_ROOT" ] ;; From d794acd4bea337e9b35b94a1d4cf8ede7a10108f Mon Sep 17 00:00:00 2001 From: Ambre Austen Suhamy Date: Tue, 25 Nov 2025 16:43:44 +0100 Subject: [PATCH 7/7] Added changes entry Signed-off-by: Ambre Austen Suhamy --- doc/changes/fixed/11612.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 doc/changes/fixed/11612.md diff --git a/doc/changes/fixed/11612.md b/doc/changes/fixed/11612.md new file mode 100644 index 00000000000..ed2a9706f0d --- /dev/null +++ b/doc/changes/fixed/11612.md @@ -0,0 +1,4 @@ +- Introduce a new variable `$DUNE_CACHE_HOME` encompassing all dune caches, + instead of relying only on `$XDG_CACHE_HOME` in the case of toolchains / + git-repo / rev-store caches. `$DUNE_CACHE_ROOT` still exists and has priority, + but might be removed in the future. (#11612, fixes #11584, @ElectreAAS)