11defmodule Mix.Compilers.Elixir do
22 @ moduledoc false
33
4- @ manifest_vsn :v3
4+ @ manifest_vsn :v2
55
66 @ doc """
77 Compiles stale Elixir files.
@@ -18,12 +18,10 @@ defmodule Mix.Compilers.Elixir do
1818 def compile ( manifest , srcs , skip , exts , dest , force , on_start ) do
1919 keep = srcs -- skip
2020 all = Mix.Utils . extract_files ( keep , exts )
21- { all_entries , skip_entries , all_sources , skip_sources } = parse_manifest ( manifest , keep )
22-
23- modified = Mix.Utils . last_modified ( manifest )
21+ { all_entries , skip_entries } = parse_manifest ( manifest , keep )
2422
2523 removed =
26- for { source , _files } <- all_sources ,
24+ for { _b , _m , _k , source , _cd , _rd , _f , _bin } <- all_entries ,
2725 not ( source in all ) ,
2826 do: source
2927
@@ -33,44 +31,44 @@ defmodule Mix.Compilers.Elixir do
3331 # changed, let's just compile everything
3432 all
3533 else
36- sources_mtimes = mtimes ( all_sources )
34+ modified = Mix.Utils . last_modified ( manifest )
35+ all_mtimes = mtimes ( all_entries )
3736
38- # Otherwise let's start with the new sources
37+ # Otherwise let's start with the new ones
38+ # plus the ones that have changed
3939 for ( source <- all ,
40- not Map . has_key? ( all_sources , source ) ,
40+ not Enum . any? ( all_entries , fn { _b , _m , _k , s , _cd , _rd , _f , _bin } -> s == source end ) ,
4141 do: source )
4242 ++
43- # Plus the sources that have changed in disk
44- for ( { source , files } <- all_sources ,
45- times = Enum . map ( [ source | files ] , & Map . fetch! ( sources_mtimes , & 1 ) ) ,
43+ for ( { _b , _m , _k , source , _cd , _rd , files , _bin } <- all_entries ,
44+ times = Enum . map ( [ source | files ] , & Map . fetch! ( all_mtimes , & 1 ) ) ,
4645 Mix.Utils . stale? ( times , [ modified ] ) ,
4746 do: source )
4847 end
4948
50- sources = update_stale_sources ( all_sources , removed , changed )
51- { entries , changed } = update_stale_entries ( all_entries , removed ++ changed ,
52- stale_local_deps ( modified ) )
53-
49+ { entries , changed } = remove_stale_entries ( all_entries , removed ++ changed )
5450 stale = changed -- removed
55- new_entries = entries ++ skip_entries
56- new_sources = Map . merge ( sources , skip_sources )
5751
5852 cond do
5953 stale != [ ] ->
60- compile_manifest ( manifest , new_entries , new_sources , stale , dest , on_start )
54+ compile_manifest ( manifest , entries ++ skip_entries , stale , dest , on_start )
6155 :ok
6256 removed != [ ] ->
63- write_manifest ( manifest , new_entries , new_sources )
57+ write_manifest ( manifest , entries ++ skip_entries )
6458 :ok
6559 true ->
6660 :noop
6761 end
6862 end
6963
70- defp mtimes ( sources ) do
71- Enum . reduce ( sources , % { } , fn { source , files } , map ->
72- Enum . reduce ( [ source | files ] , map , fn file , map ->
73- Map . put_new_lazy ( map , file , fn -> Mix.Utils . last_modified ( file ) end )
64+ defp mtimes ( entries ) do
65+ Enum . reduce ( entries , % { } , fn { _b , _m , _k , source , _cd , _rd , files , _bin } , dict ->
66+ Enum . reduce ( [ source | files ] , dict , fn file , dict ->
67+ if Map . has_key? ( dict , file ) do
68+ dict
69+ else
70+ Map . put ( dict , file , Mix.Utils . last_modified ( file ) )
71+ end
7472 end )
7573 end )
7674 end
@@ -79,24 +77,22 @@ defmodule Mix.Compilers.Elixir do
7977 Removes compiled files.
8078 """
8179 def clean ( manifest ) do
82- Enum . each read_manifest ( manifest ) , fn
83- { beam , _ , _ , _ , _ , _ , _ } ->
84- File . rm ( beam )
85- { _ , _ } ->
86- :ok
80+ Enum . map read_manifest ( manifest ) , fn { beam , _ , _ , _ , _ , _ , _ , _ } ->
81+ File . rm ( beam )
8782 end
83+ :ok
8884 end
8985
9086 @ doc """
9187 Returns protocols and implementations for the given manifest.
9288 """
9389 def protocols_and_impls ( manifest ) do
94- for { beam , module , kind , _ , _ , _ , _ } <- read_manifest ( manifest ) ,
90+ for { _ , module , kind , _ , _ , _ , _ , _ } <- read_manifest ( manifest ) ,
9591 match? ( :protocol , kind ) or match? ( { :impl , _ } , kind ) ,
96- do: { module , kind , beam }
92+ do: { module , kind }
9793 end
9894
99- defp compile_manifest ( manifest , entries , sources , stale , dest , on_start ) do
95+ defp compile_manifest ( manifest , entries , stale , dest , on_start ) do
10096 Mix.Project . ensure_structure ( )
10197 true = Code . prepend_path ( dest )
10298
@@ -105,16 +101,16 @@ defmodule Mix.Compilers.Elixir do
105101
106102 # Starts a server responsible for keeping track which files
107103 # were compiled and the dependencies between them.
108- { :ok , pid } = Agent . start_link ( fn -> { entries , sources } end )
104+ { :ok , pid } = Agent . start_link ( fn -> entries end )
109105
110106 try do
111107 _ = Kernel.ParallelCompiler . files :lists . usort ( stale ) ,
112108 each_module: & each_module ( pid , dest , cwd , & 1 , & 2 , & 3 ) ,
113109 each_file: & each_file ( & 1 ) ,
114110 dest: dest
115- Agent . cast pid , fn { entries , sources } ->
116- write_manifest ( manifest , entries , sources )
117- { entries , sources }
111+ Agent . cast pid , fn entries ->
112+ write_manifest ( manifest , entries )
113+ entries
118114 end
119115 after
120116 Agent . stop ( pid , :normal , :infinity )
@@ -144,12 +140,8 @@ defmodule Mix.Compilers.Elixir do
144140 kind = detect_kind ( module )
145141 source = Path . relative_to ( source , cwd )
146142 files = get_external_resources ( module , cwd )
147-
148- Agent . cast pid , fn { entries , sources } ->
149- entries = List . keystore ( entries , beam , 0 , { beam , module , kind , source , compile , runtime , binary } )
150- sources = Map . update ( sources , source , files , & files ++ & 1 )
151- { entries , sources }
152- end
143+ tuple = { beam , module , kind , source , compile , runtime , files , binary }
144+ Agent . cast pid , & :lists . keystore ( beam , 1 , & 1 , tuple )
153145 end
154146
155147 defp detect_kind ( module ) do
@@ -171,27 +163,22 @@ defmodule Mix.Compilers.Elixir do
171163 do: relative
172164 end
173165
174- defp each_file ( source ) do
175- Mix . shell . info "Compiled #{ source } "
166+ defp each_file ( file ) do
167+ Mix . shell . info "Compiled #{ file } "
176168 end
177169
178170 ## Resolution
179171
180- defp update_stale_sources ( sources , removed , changed ) do
181- Enum . reduce changed , Map . drop ( sources , removed ) , & Map . put ( & 2 , & 1 , [ ] )
182- end
183-
184172 # This function receives the manifest entries and some source
185173 # files that have changed. It then, recursively, figures out
186174 # all the files that changed (via the module dependencies) and
187175 # return the non-changed entries and the removed sources.
188- defp update_stale_entries ( all , [ ] , stale ) when stale == % { } do
176+ defp remove_stale_entries ( all , [ ] ) do
189177 { all , [ ] }
190178 end
191179
192- defp update_stale_entries ( all , changed , stale ) do
193- removed = Enum . into ( changed , % { } , & { & 1 , true } )
194- remove_stale_entries ( all , stale , removed )
180+ defp remove_stale_entries ( all , changed ) do
181+ remove_stale_entries ( all , % { } , Enum . into ( changed , % { } , & { & 1 , true } ) )
195182 end
196183
197184 defp remove_stale_entries ( entries , old_stale , old_removed ) do
@@ -206,13 +193,15 @@ defmodule Mix.Compilers.Elixir do
206193 end
207194 end
208195
209- defp remove_stale_entry ( { beam , module , _kind , source , compile , runtime , _bin } = entry ,
196+ defp remove_stale_entry ( { beam , module , _kind , source , compile , runtime , _f , _bin } = entry ,
210197 { rest , stale , removed } ) do
211198 cond do
212199 # If I changed in disk or have a compile time dependency
213200 # on something stale, I need to be recompiled.
214201 Map . has_key? ( removed , source ) or Enum . any? ( compile , & Map . has_key? ( stale , & 1 ) ) ->
215- remove_and_purge ( beam , module )
202+ _ = File . rm ( beam )
203+ _ = :code . purge ( module )
204+ _ = :code . delete ( module )
216205 { rest , Map . put ( stale , module , true ) , Map . put ( removed , source , true ) }
217206
218207 # If I have a runtime time dependency on something stale,
@@ -226,22 +215,6 @@ defmodule Mix.Compilers.Elixir do
226215 end
227216 end
228217
229- defp stale_local_deps ( modified ) do
230- for % { scm: scm } = dep <- Mix.Dep . children ,
231- not scm . fetchable? ,
232- path <- Mix.Dep . load_paths ( dep ) ,
233- beam <- Path . wildcard ( Path . join ( path , "*.beam" ) ) ,
234- Mix.Utils . last_modified ( beam ) > modified ,
235- do: { beam |> Path . basename |> Path . rootname |> String . to_atom , true } ,
236- into: % { }
237- end
238-
239- defp remove_and_purge ( beam , module ) do
240- _ = File . rm ( beam )
241- _ = :code . purge ( module )
242- _ = :code . delete ( module )
243- end
244-
245218 ## Manifest handling
246219
247220 defp read_manifest ( manifest ) do
@@ -251,58 +224,31 @@ defmodule Mix.Compilers.Elixir do
251224 end
252225 end
253226
254- # Similar to read manifest but supports data migration.
255227 defp parse_manifest ( manifest , keep_paths ) do
256- state = { [ ] , [ ] , % { } , % { } }
257-
258- case :file . consult ( manifest ) do
259- { :ok , [ @ manifest_vsn | data ] } ->
260- parse_manifest ( data , keep_paths , state )
261- { :ok , [ :v2 | data ] } ->
262- for { beam , module , _ , _ , _ , _ , _ , _ } <- data do
263- remove_and_purge ( beam , module )
264- end
265- state
266- _ ->
267- state
268- end
269- end
270-
271- defp parse_manifest ( data , keep_paths , state ) do
272- Enum . reduce data , state , fn
273- { _ , _ , _ , source , _ , _ , _ } = entry , { keep , skip , keep_sources , skip_sources } ->
274- if String . starts_with? ( source , keep_paths ) do
275- { [ entry | keep ] , skip , keep_sources , skip_sources }
276- else
277- { keep , [ entry | skip ] , keep_sources , skip_sources }
278- end
279- { source , files } , { keep , skip , keep_sources , skip_sources } ->
228+ Enum . reduce read_manifest ( manifest ) , { [ ] , [ ] } , fn
229+ { _ , _ , _ , source , _ , _ , _ , _ } = entry , { keep , skip } ->
280230 if String . starts_with? ( source , keep_paths ) do
281- { keep , skip , Map . put ( keep_sources , source , files ) , skip_sources }
231+ { [ entry | keep ] , skip }
282232 else
283- { keep , skip , keep_sources , Map . put ( skip_sources , source , files ) }
233+ { keep , [ entry | skip ] }
284234 end
285235 end
286236 end
287237
288- defp write_manifest ( manifest , [ ] , sources ) when sources == % { } do
238+ defp write_manifest ( manifest , [ ] ) do
289239 File . rm ( manifest )
290240 :ok
291241 end
292242
293- defp write_manifest ( manifest , entries , sources ) do
243+ defp write_manifest ( manifest , entries ) do
294244 File . mkdir_p! ( Path . dirname ( manifest ) )
295245
296246 File . open! ( manifest , [ :write ] , fn device ->
297247 :io . format ( device , '~p.~n' , [ @ manifest_vsn ] )
298248
299- Enum . each entries , fn { beam , _ , _ , _ , _ , _ , binary } = entry ->
249+ Enum . map entries , fn { beam , _ , _ , _ , _ , _ , _ , binary } = entry ->
300250 if binary , do: File . write! ( beam , binary )
301- :io . format ( device , '~p.~n' , [ put_elem ( entry , 6 , nil ) ] )
302- end
303-
304- Enum . each sources , fn { _ , _ } = entry ->
305- :io . format ( device , '~p.~n' , [ entry ] )
251+ :io . format ( device , '~p.~n' , [ put_elem ( entry , 7 , nil ) ] )
306252 end
307253
308254 :ok
0 commit comments