@@ -139,15 +139,15 @@ defmodule Kernel.ParallelCompiler do
139139 compiler_pid = self ( )
140140 :elixir_code_server . cast ( { :reset_warnings , compiler_pid } )
141141 schedulers = max ( :erlang . system_info ( :schedulers_online ) , 2 )
142+ beam_timestamp = Keyword . get ( options , :beam_timestamp )
142143
143- result =
144+ outcome =
144145 spawn_workers ( files , 0 , [ ] , [ ] , % { } , [ ] , % {
145146 dest: Keyword . get ( options , :dest ) ,
146147 each_cycle: Keyword . get ( options , :each_cycle , fn -> { :runtime , [ ] } end ) ,
147148 each_file: Keyword . get ( options , :each_file , fn _ , _ -> :ok end ) |> each_file ( ) ,
148149 each_long_compilation: Keyword . get ( options , :each_long_compilation , fn _file -> :ok end ) ,
149150 each_module: Keyword . get ( options , :each_module , fn _file , _module , _binary -> :ok end ) ,
150- beam_timestamp: Keyword . get ( options , :beam_timestamp ) ,
151151 long_compilation_threshold: Keyword . get ( options , :long_compilation_threshold , 15 ) ,
152152 profile: Keyword . get ( options , :profile ) ,
153153 cycle_start: System . monotonic_time ( ) ,
@@ -160,7 +160,7 @@ defmodule Kernel.ParallelCompiler do
160160 # compilation status will be set to error.
161161 compilation_status = :elixir_code_server . call ( { :compilation_status , compiler_pid } )
162162
163- case { result , compilation_status } do
163+ case { outcome , compilation_status } do
164164 { { :ok , _ , warnings } , :error } ->
165165 message = "Compilation failed due to warnings while using the --warnings-as-errors option"
166166 IO . puts ( :stderr , message )
@@ -169,8 +169,11 @@ defmodule Kernel.ParallelCompiler do
169169 { { :error , errors , warnings } , :error } ->
170170 { :error , errors ++ warnings , [ ] }
171171
172- _ ->
173- result
172+ { { :ok , outcome , warnings } , _ } ->
173+ { :ok , write_module_binaries ( outcome , output , beam_timestamp ) , warnings }
174+
175+ { { :error , errors , warnings } , _ } ->
176+ { :error , errors , warnings }
174177 end
175178 end
176179
@@ -187,6 +190,74 @@ defmodule Kernel.ParallelCompiler do
187190 end
188191 end
189192
193+ defp write_module_binaries ( result , { :compile , path } , timestamp ) do
194+ Enum . flat_map ( result , fn
195+ { { :module , module } , { binary , _map } } ->
196+ full_path = Path . join ( path , Atom . to_string ( module ) <> ".beam" )
197+ File . write! ( full_path , binary )
198+ if timestamp , do: File . touch! ( full_path , timestamp )
199+ [ module ]
200+
201+ _ ->
202+ [ ]
203+ end )
204+ end
205+
206+ defp write_module_binaries ( result , _output , _timestamp ) do
207+ for { { :module , module } , _ } <- result , do: module
208+ end
209+
210+ ## Verification
211+
212+ defp verify_modules ( result , warnings , dependent_modules , state ) do
213+ checker_warnings = maybe_check_modules ( result , dependent_modules , state )
214+ warnings = Enum . reverse ( warnings , checker_warnings )
215+ { :ok , result , warnings }
216+ end
217+
218+ defp maybe_check_modules ( result , runtime_modules , state ) do
219+ % { schedulers: schedulers , profile: profile } = state
220+
221+ if :elixir_config . get ( :bootstrap ) do
222+ [ ]
223+ else
224+ compiled_modules = checker_compiled_modules ( result )
225+ runtime_modules = checker_runtime_modules ( runtime_modules )
226+
227+ profile_checker ( profile , compiled_modules , runtime_modules , fn ->
228+ Module.ParallelChecker . verify ( compiled_modules , runtime_modules , schedulers )
229+ end )
230+ end
231+ end
232+
233+ defp checker_compiled_modules ( result ) do
234+ for { { :module , _module } , { binary , module_map } } <- result do
235+ { module_map , binary }
236+ end
237+ end
238+
239+ defp checker_runtime_modules ( modules ) do
240+ for module <- modules ,
241+ path = :code . which ( module ) ,
242+ is_list ( path ) do
243+ { module , File . read! ( path ) }
244+ end
245+ end
246+
247+ defp profile_checker ( _profile = :time , compiled_modules , runtime_modules , fun ) do
248+ { time , result } = :timer . tc ( fun )
249+ time = div ( time , 1000 )
250+ num_modules = length ( compiled_modules ) + length ( runtime_modules )
251+ IO . puts ( :stderr , "[profile] Finished group pass check of #{ num_modules } modules in #{ time } ms" )
252+ result
253+ end
254+
255+ defp profile_checker ( _profile = nil , _compiled_modules , _runtime_modules , fun ) do
256+ fun . ( )
257+ end
258+
259+ ## Compiler worker spawning
260+
190261 # We already have n=schedulers currently running, don't spawn new ones
191262 defp spawn_workers (
192263 queue ,
@@ -253,10 +324,10 @@ defmodule Kernel.ParallelCompiler do
253324
254325 case each_cycle_return ( state . each_cycle . ( ) ) do
255326 { :runtime , dependent_modules } ->
256- write_and_verify_modules ( result , warnings , dependent_modules , state )
327+ verify_modules ( result , warnings , dependent_modules , state )
257328
258329 { :compile , [ ] } ->
259- write_and_verify_modules ( result , warnings , [ ] , state )
330+ verify_modules ( result , warnings , [ ] , state )
260331
261332 { :compile , more } ->
262333 spawn_workers ( more , 0 , [ ] , [ ] , result , warnings , state )
@@ -354,71 +425,6 @@ defmodule Kernel.ParallelCompiler do
354425 defp each_cycle_return ( modules ) when is_list ( modules ) , do: { :compile , modules }
355426 defp each_cycle_return ( other ) , do: other
356427
357- defp write_and_verify_modules ( result , warnings , dependent_modules , state ) do
358- modules = write_module_binaries ( result , state )
359- checker_warnings = maybe_check_modules ( result , dependent_modules , state )
360- warnings = Enum . reverse ( warnings , checker_warnings )
361- { :ok , modules , warnings }
362- end
363-
364- defp write_module_binaries ( result , % { output: { :compile , path } , beam_timestamp: timestamp } ) do
365- Enum . flat_map ( result , fn
366- { { :module , module } , { binary , _map } } ->
367- full_path = Path . join ( path , Atom . to_string ( module ) <> ".beam" )
368- File . write! ( full_path , binary )
369- if timestamp , do: File . touch! ( full_path , timestamp )
370- [ module ]
371-
372- _ ->
373- [ ]
374- end )
375- end
376-
377- defp write_module_binaries ( result , _state ) do
378- for { { :module , module } , _ } <- result , do: module
379- end
380-
381- defp maybe_check_modules ( result , runtime_modules , state ) do
382- % { schedulers: schedulers , profile: profile } = state
383-
384- if :elixir_config . get ( :bootstrap ) do
385- [ ]
386- else
387- compiled_modules = checker_compiled_modules ( result )
388- runtime_modules = checker_runtime_modules ( runtime_modules )
389-
390- profile_checker ( profile , compiled_modules , runtime_modules , fn ->
391- Module.ParallelChecker . verify ( compiled_modules , runtime_modules , schedulers )
392- end )
393- end
394- end
395-
396- defp checker_compiled_modules ( result ) do
397- for { { :module , _module } , { binary , module_map } } <- result do
398- { module_map , binary }
399- end
400- end
401-
402- defp checker_runtime_modules ( modules ) do
403- for module <- modules ,
404- path = :code . which ( module ) ,
405- is_list ( path ) do
406- { module , File . read! ( path ) }
407- end
408- end
409-
410- defp profile_checker ( _profile = :time , compiled_modules , runtime_modules , fun ) do
411- { time , result } = :timer . tc ( fun )
412- time = div ( time , 1000 )
413- num_modules = length ( compiled_modules ) + length ( runtime_modules )
414- IO . puts ( :stderr , "[profile] Finished group pass check of #{ num_modules } modules in #{ time } ms" )
415- result
416- end
417-
418- defp profile_checker ( _profile = nil , _compiled_modules , _runtime_modules , fun ) do
419- fun . ( )
420- end
421-
422428 # The goal of this function is to find leaves in the dependency graph,
423429 # i.e. to find code that depends on code that we know is not being defined.
424430 defp without_definition ( waiting , files ) do
0 commit comments