From 6120c556f8de5cc837832fe0d46b4fd4f88618ba Mon Sep 17 00:00:00 2001
From: barracuda156 <vital.had@gmail.com>
Date: Fri, 20 Oct 2023 04:54:18 +0800
Subject: [PATCH] copyfile_stubs.c: define COPYFILE_CLONE in case it is undefined

Credit to Ali Caglayan <alizter@gmail.com>
Picked from https://github.com/ocaml/dune/pull/8942/commits/89671ada56e24af7654a5b57b9089501342a2e62
---
 otherlibs/stdune/src/copyfile_stubs.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git otherlibs/stdune/src/copyfile_stubs.c otherlibs/stdune/src/copyfile_stubs.c
index 09c9a1b14..6824c572f 100644
--- a/otherlibs/stdune/src/copyfile_stubs.c
+++ b/otherlibs/stdune/src/copyfile_stubs.c
@@ -15,6 +15,10 @@
 #include <string.h>
 #include <sys/syslimits.h>
 
+#ifndef COPYFILE_CLONE
+#define COPYFILE_CLONE (1<<24)
+#endif
+
 CAMLprim value stdune_copyfile(value v_from, value v_to) {
   CAMLparam2(v_from, v_to);
   caml_unix_check_path(v_from, "copyfile");


From bf5a2a965a17236bcbddb15e8ab5cdf35f7775b2 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <vital.had@gmail.com>
Date: Fri, 17 Oct 2025 13:57:50 +0800
Subject: [PATCH] Revert "refactor: remove the copy file impl config (#11966)"

This reverts commit 804fa3f1ae043310ec574ce0f44d36c79a13c545.
---
 otherlibs/stdune/src/io.ml               | 12 +++++++++++-
 otherlibs/stdune/src/io.mli              |  2 ++
 src/dune_config/config.ml                | 10 ++++++++++
 src/dune_config/config.mli               |  3 +++
 src/dune_config_file/dune_config_file.ml |  1 +
 5 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/otherlibs/stdune/src/io.ml b/otherlibs/stdune/src/io.ml
index efaf11c0360..bf6c58b67d5 100644
--- a/otherlibs/stdune/src/io.ml
+++ b/otherlibs/stdune/src/io.ml
@@ -211,14 +211,24 @@ module Copyfile = struct
       copy_channels ic oc)
   ;;
 
-  let copy_file =
+  let copy_file_best =
     match available with
     | `Sendfile -> sendfile_with_fallback
     | `Copyfile -> copyfile
     | `Nothing -> copy_file_portable
   ;;
+
+  let copy_file_impl = ref `Best
+
+  let copy_file ?chmod ~src ~dst () =
+    match !copy_file_impl with
+    | `Portable -> copy_file_portable ?chmod ~src ~dst ()
+    | `Best -> copy_file_best ?chmod ~src ~dst ()
+  ;;
 end
 
+let set_copy_impl m = Copyfile.copy_file_impl := m
+
 module Make (Path : sig
     type t
 
diff --git a/otherlibs/stdune/src/io.mli b/otherlibs/stdune/src/io.mli
index 4cb6510fff4..0b72d1c5117 100644
--- a/otherlibs/stdune/src/io.mli
+++ b/otherlibs/stdune/src/io.mli
@@ -14,3 +14,5 @@ val portable_symlink : src:Path.t -> dst:Path.t -> unit
 
 (** Hardlink with fallback to copy on systems that don't support it. *)
 val portable_hardlink : src:Path.t -> dst:Path.t -> unit
+
+val set_copy_impl : [ `Portable | `Best ] -> unit
diff --git a/src/dune_config/config.ml b/src/dune_config/config.ml
index 41773f6efcf..dd446b1d92a 100644
--- a/src/dune_config/config.ml
+++ b/src/dune_config/config.ml
@@ -102,6 +102,16 @@ let cutoffs_that_reduce_concurrency_in_watch_mode =
     ~default:`Disabled
 ;;
 
+let copy_file =
+  make
+    ~name:"copy_file"
+    ~of_string:(function
+      | "portable" -> Ok `Portable
+      | "fast" -> Ok `Best
+      | _ -> Error (sprintf "only %S and %S are allowed" "fast" "portable"))
+    ~default:`Best
+;;
+
 let background_default =
   match Platform.OS.value with
   | Linux | Windows | Darwin -> `Enabled
diff --git a/src/dune_config/config.mli b/src/dune_config/config.mli
index 3bd360f7890..39f78b0c1ac 100644
--- a/src/dune_config/config.mli
+++ b/src/dune_config/config.mli
@@ -39,6 +39,9 @@ val global_lock : Toggle.t t
     reduces concurrency *)
 val cutoffs_that_reduce_concurrency_in_watch_mode : Toggle.t t
 
+(** whether dune should optimize file copying on Linux/MacOS *)
+val copy_file : [ `Portable | `Best ] t
+
 (** Execute some actions in background threads. See [Action_exec] for the
     concrete list of actions *)
 val background_actions : Toggle.t t
diff --git a/src/dune_config_file/dune_config_file.ml b/src/dune_config_file/dune_config_file.ml
index 8146188278b..d46435dc43c 100644
--- a/src/dune_config_file/dune_config_file.ml
+++ b/src/dune_config_file/dune_config_file.ml
@@ -653,6 +653,7 @@ module Dune_config = struct
       | Preserve -> ()
       | Clear_on_rebuild -> Console.reset ()
       | Clear_on_rebuild_and_flush_history -> Console.reset_flush_history ());
+    Stdune.Io.set_copy_impl Config.(get copy_file);
     Log.verbose
     := match t.display with
        | Simple { verbosity = Verbose; _ } -> true
