@@ -23,34 +23,38 @@ defmodule Mix.Compilers.Protocol do
2323 opts ++ Keyword . take ( config , [ :consolidate_protocols ] )
2424 end
2525
26- manifest = manifest ( )
27- config_mtime = Mix.Project . config_mtime ( )
28- { old_config_mtime , old_protocols_and_impls } = read_manifest ( manifest )
29-
30- case status ( config_mtime > old_config_mtime , opts ) do
31- :off ->
32- res
33-
34- :on when res == :noop ->
35- :noop
36-
37- on_or_force ->
38- deps_paths =
39- for % { scm: scm , opts: opts } <- Mix.Dep . cached ( ) ,
40- not scm . fetchable? ( ) ,
41- do: opts [ :build ]
42-
43- protocols_and_impls = Mix.Compilers.Elixir . protocols_and_impls_from_paths ( deps_paths )
44-
45- case compile ( on_or_force == :force , old_protocols_and_impls , protocols_and_impls , opts ) do
46- :ok ->
47- write_manifest ( manifest , { config_mtime , protocols_and_impls } )
48- :ok
49-
50- :noop ->
51- res
52- end
53- end
26+ # Because this function is called outside of the usual compiler loop,
27+ # we need a build lock.
28+ Mix.Project . with_build_lock ( config , fn ->
29+ manifest = manifest ( )
30+ config_mtime = Mix.Project . config_mtime ( )
31+ { old_config_mtime , old_protocols_and_impls } = read_manifest ( manifest )
32+
33+ case status ( config_mtime > old_config_mtime , opts ) do
34+ :off ->
35+ res
36+
37+ :on when res == :noop ->
38+ :noop
39+
40+ on_or_force ->
41+ deps_paths =
42+ for % { scm: scm , opts: opts } <- Mix.Dep . cached ( ) ,
43+ not scm . fetchable? ( ) ,
44+ do: opts [ :build ]
45+
46+ protocols_and_impls = Mix.Compilers.Elixir . protocols_and_impls_from_paths ( deps_paths )
47+
48+ case compile ( on_or_force == :force , old_protocols_and_impls , protocols_and_impls , opts ) do
49+ :ok ->
50+ write_manifest ( manifest , { config_mtime , protocols_and_impls } )
51+ :ok
52+
53+ :noop ->
54+ res
55+ end
56+ end
57+ end )
5458 end
5559
5660 defp manifest , do: Path . join ( Mix.Project . manifest_path ( ) , @ manifest )
0 commit comments