Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 40 additions & 22 deletions bin/lock_dev_tool.ml
Original file line number Diff line number Diff line change
Expand Up @@ -197,28 +197,46 @@ let lockdir_status dev_tool =
with
| false -> Memo.return (`Lockdir_ok_with_tool_pkg pkg)
| true ->
let open Memo.O in
let* compiler = compiler_package () in
let+ compiler = compiler_package () in
(match Package_name.Map.find packages compiler.info.name with
| None -> Memo.return `No_compiler_lockfile_in_lockdir
| Some pkg ->
let+ ocaml_compiler = compiler_package () in
(match Lock_dir.Pkg.equal pkg ocaml_compiler with
| true -> `Lockdir_ok_with_tool_pkg pkg
| false ->
`Dev_tool_needs_to_be_relocked_because_project_compiler_version_changed
(User_message.make
[ Pp.textf
"The version of the compiler package (%S) in this project's \
lockdir has changed to %s (formerly the compiler version \
was %s). The dev-tool %S will be re-locked and rebuilt with \
this version of the compiler."
(Package_name.to_string compiler.info.name)
(Package_version.to_string ocaml_compiler.info.version)
(Package_version.to_string pkg.info.version)
(Dune_pkg.Dev_tool.package_name dev_tool
|> Package_name.to_string)
]))))))
| None -> `No_compiler_lockfile_in_lockdir
| Some locked_compiler ->
let same_compiler_package =
Lock_dir.Pkg.equal_on_platform locked_compiler compiler ~platform
in
if same_compiler_package
then `Lockdir_ok_with_tool_pkg pkg
else (
let compiler_name = Package_name.to_string compiler.info.name in
let dev_tool_name =
Dune_pkg.Dev_tool.package_name dev_tool |> Package_name.to_string
in
let message =
if
Package_version.equal
compiler.info.version
locked_compiler.info.version
then
Pp.textf
"The compiler package (%S) in this project's lockdir has changed \
without changing its version (%s). The dev-tool %S will be \
re-locked and rebuilt with the updated compiler package."
compiler_name
(Package_version.to_string compiler.info.version)
dev_tool_name
else
Pp.textf
"The version of the compiler package (%S) in this project's \
lockdir has changed to %s (formerly the compiler version was \
%s). The dev-tool %S will be re-locked and rebuilt with this \
version of the compiler."
compiler_name
(Package_version.to_string compiler.info.version)
(Package_version.to_string locked_compiler.info.version)
dev_tool_name
in
`Dev_tool_needs_to_be_relocked_because_project_compiler_changed
(User_message.make [ message ]))))))
;;

(* [lock_dev_tool_at_version dev_tool version] generates the lockdir for the
Expand Down Expand Up @@ -261,7 +279,7 @@ let lock_dev_tool_at_version dev_tool version =
"ocaml"
];
true
| `Dev_tool_needs_to_be_relocked_because_project_compiler_version_changed message ->
| `Dev_tool_needs_to_be_relocked_because_project_compiler_changed message ->
Console.print_user_message message;
true
| `Lockdir_missing_entry_for_tool message ->
Expand Down
3 changes: 3 additions & 0 deletions doc/changes/fixed/16173.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Avoid unnecessarily relocking and rebuilding dev tools when the project's
compiler package is unchanged, while still relocking after same-version
compiler recipe changes. (#16173, @Alizter)
22 changes: 22 additions & 0 deletions src/dune_pkg/lock_dir.ml
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,28 @@ module Pkg = struct
List.is_empty t.enabled_on_platforms
|| Solver_env_disjunction.matches_platform t.enabled_on_platforms ~platform
;;

let equal_on_platform a b ~platform =
match is_enabled_on_platform a ~platform, is_enabled_on_platform b ~platform with
| false, false -> true
| true, false | false, true -> false
| true, true ->
let choose choice =
match Conditional_choice.choose_for_platform choice ~platform with
| None -> Conditional_choice.empty
| Some value -> Conditional_choice.singleton Solver_env.empty value
in
let normalize pkg =
{ pkg with
build_command = choose pkg.build_command
; install_command = choose pkg.install_command
; depends = choose pkg.depends
; enabled_on_platforms = [ Solver_env.empty ]
}
|> remove_locs
in
equal (normalize a) (normalize b)
;;
end

module Repositories = struct
Expand Down
6 changes: 6 additions & 0 deletions src/dune_pkg/lock_dir.mli
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ module Pkg : sig

val remove_locs : t -> t
val equal : t -> t -> bool

(** Compare package behavior on a platform, ignoring source locations, choices
for other platforms, and availability on other platforms. Packages disabled
on the platform compare equal if both are disabled. *)
val equal_on_platform : t -> t -> platform:Solver_env.t -> bool

val hash : t -> int
val digest_feed : t Dune_digest.Feed.t
val to_dyn : t -> Dyn.t
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Use an extra file to distinguish reuse from an identical regenerated lockdir.
> else
> echo 'unchanged dev-tool lock regenerated'
> fi
unchanged dev-tool lock regenerated
unchanged dev-tool lock reused
$ rm -f "${dev_tool_lock_dir}"/relock-sentinel

Change the compiler package's build recipe without changing its version, then
Expand All @@ -42,10 +42,9 @@ Executing Merlin must notice the changed compiler package and regenerate its
lock directory from the updated recipe.

$ dune tools exec ocamlmerlin
The version of the compiler package ("ocaml-base-compiler") in this project's
lockdir has changed to 5.2.0 (formerly the compiler version was 5.2.0). The
dev-tool "merlin" will be re-locked and rebuilt with this version of the
compiler.
The compiler package ("ocaml-base-compiler") in this project's lockdir has
changed without changing its version (5.2.0). The dev-tool "merlin" will be
re-locked and rebuilt with the updated compiler package.
Solution for _build/.dev-tools.locks/merlin:
- merlin.0.0.1
- ocaml-base-compiler.5.2.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,6 @@ Initially merlin will depend on ocaml-base-compiler.5.2.0 to match the project.

We can re-run "dune tools exec ocamlmerlin" without relocking or rebuilding.
$ dune tools exec ocamlmerlin
The version of the compiler package ("ocaml-base-compiler") in this project's
lockdir has changed to 5.2.0 (formerly the compiler version was 5.2.0). The
dev-tool "merlin" will be re-locked and rebuilt with this version of the
compiler.
Solution for _build/.dev-tools.locks/merlin:
- merlin.0.0.1
- ocaml-base-compiler.5.2.0
- ocaml-compiler.5.2.0
Running 'ocamlmerlin'
hello from fake ocamlmerlin

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,5 @@ rather than "ocaml-base-compiler.5.2.0" from opam-repository.
- ocaml-lsp-server.0.0.1

$ dune tools exec ocamllsp
The version of the compiler package ("ocaml-base-compiler") in this project's
lockdir has changed to dev (formerly the compiler version was dev). The
dev-tool "ocaml-lsp-server" will be re-locked and rebuilt with this version
of the compiler.
Solution for _build/.dev-tools.locks/ocaml-lsp-server:
- ocaml-base-compiler.dev
- ocaml-lsp-server.0.0.1
Running 'ocamllsp'
hello from fake ocamllsp
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,6 @@ Initially ocamllsp will depend on ocaml-base-compiler.5.2.0 to match the project

We can re-run "dune tools exec ocamllsp" without relocking or rebuilding.
$ dune tools exec ocamllsp
The version of the compiler package ("ocaml-base-compiler") in this project's
lockdir has changed to 5.2.0 (formerly the compiler version was 5.2.0). The
dev-tool "ocaml-lsp-server" will be re-locked and rebuilt with this version
of the compiler.
Solution for _build/.dev-tools.locks/ocaml-lsp-server:
- ocaml-base-compiler.5.2.0
- ocaml-compiler.5.2.0
- ocaml-lsp-server.0.0.1
Running 'ocamllsp'
hello from fake ocamllsp

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,6 @@ Initially odoc will depend on ocaml-base-compiler.5.2.0 to match the project.

We can re-run "dune ocaml doc" without relocking or rebuilding.
$ DUNE_CONFIG__LOCK_DEV_TOOL=enabled dune ocaml doc
The version of the compiler package ("ocaml-base-compiler") in this project's
lockdir has changed to 5.2.0 (formerly the compiler version was 5.2.0). The
dev-tool "odoc" will be re-locked and rebuilt with this version of the
compiler.
Solution for _build/.dev-tools.locks/odoc:
- ocaml-base-compiler.5.2.0
- ocaml-compiler.5.2.0
- odoc.0.0.1
hello from fake odoc
hello from fake odoc
File "_doc/_html/_unknown_", line 1, characters 0-0:
Expand Down
Loading