@@ -139,15 +139,15 @@ defmodule Kernel.ParallelCompiler do
139
139
compiler_pid = self ( )
140
140
:elixir_code_server . cast ( { :reset_warnings , compiler_pid } )
141
141
schedulers = max ( :erlang . system_info ( :schedulers_online ) , 2 )
142
+ beam_timestamp = Keyword . get ( options , :beam_timestamp )
142
143
143
- result =
144
+ outcome =
144
145
spawn_workers ( files , 0 , [ ] , [ ] , % { } , [ ] , % {
145
146
dest: Keyword . get ( options , :dest ) ,
146
147
each_cycle: Keyword . get ( options , :each_cycle , fn -> { :runtime , [ ] } end ) ,
147
148
each_file: Keyword . get ( options , :each_file , fn _ , _ -> :ok end ) |> each_file ( ) ,
148
149
each_long_compilation: Keyword . get ( options , :each_long_compilation , fn _file -> :ok end ) ,
149
150
each_module: Keyword . get ( options , :each_module , fn _file , _module , _binary -> :ok end ) ,
150
- beam_timestamp: Keyword . get ( options , :beam_timestamp ) ,
151
151
long_compilation_threshold: Keyword . get ( options , :long_compilation_threshold , 15 ) ,
152
152
profile: Keyword . get ( options , :profile ) ,
153
153
cycle_start: System . monotonic_time ( ) ,
@@ -160,7 +160,7 @@ defmodule Kernel.ParallelCompiler do
160
160
# compilation status will be set to error.
161
161
compilation_status = :elixir_code_server . call ( { :compilation_status , compiler_pid } )
162
162
163
- case { result , compilation_status } do
163
+ case { outcome , compilation_status } do
164
164
{ { :ok , _ , warnings } , :error } ->
165
165
message = "Compilation failed due to warnings while using the --warnings-as-errors option"
166
166
IO . puts ( :stderr , message )
@@ -169,8 +169,11 @@ defmodule Kernel.ParallelCompiler do
169
169
{ { :error , errors , warnings } , :error } ->
170
170
{ :error , errors ++ warnings , [ ] }
171
171
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 }
174
177
end
175
178
end
176
179
@@ -187,6 +190,74 @@ defmodule Kernel.ParallelCompiler do
187
190
end
188
191
end
189
192
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
+
190
261
# We already have n=schedulers currently running, don't spawn new ones
191
262
defp spawn_workers (
192
263
queue ,
@@ -253,10 +324,10 @@ defmodule Kernel.ParallelCompiler do
253
324
254
325
case each_cycle_return ( state . each_cycle . ( ) ) do
255
326
{ :runtime , dependent_modules } ->
256
- write_and_verify_modules ( result , warnings , dependent_modules , state )
327
+ verify_modules ( result , warnings , dependent_modules , state )
257
328
258
329
{ :compile , [ ] } ->
259
- write_and_verify_modules ( result , warnings , [ ] , state )
330
+ verify_modules ( result , warnings , [ ] , state )
260
331
261
332
{ :compile , more } ->
262
333
spawn_workers ( more , 0 , [ ] , [ ] , result , warnings , state )
@@ -354,71 +425,6 @@ defmodule Kernel.ParallelCompiler do
354
425
defp each_cycle_return ( modules ) when is_list ( modules ) , do: { :compile , modules }
355
426
defp each_cycle_return ( other ) , do: other
356
427
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
-
422
428
# The goal of this function is to find leaves in the dependency graph,
423
429
# i.e. to find code that depends on code that we know is not being defined.
424
430
defp without_definition ( waiting , files ) do
0 commit comments