@@ -93,36 +93,41 @@ defmodule Kernel.ParallelCompiler do
93
93
:elixir_code_server . cast ( { :reset_warnings , compiler_pid } )
94
94
schedulers = max ( :erlang . system_info ( :schedulers_online ) , 2 )
95
95
96
- result = spawn_workers ( % {
97
- entries: files ,
98
- original: files ,
99
- output: output ,
100
- options: options ,
101
- waiting: [ ] ,
102
- queued: [ ] ,
103
- schedulers: schedulers ,
104
- result: [ ] ,
105
- warnings: [ ] ,
106
- } )
96
+ result =
97
+ spawn_workers ( % {
98
+ entries: files ,
99
+ original: files ,
100
+ output: output ,
101
+ options: options ,
102
+ waiting: [ ] ,
103
+ queued: [ ] ,
104
+ schedulers: schedulers ,
105
+ result: [ ] ,
106
+ warnings: [ ]
107
+ } )
107
108
108
109
# In case --warning-as-errors is enabled and there was a warning,
109
110
# compilation status will be set to error.
110
111
compilation_status = :elixir_code_server . call ( { :compilation_status , compiler_pid } )
111
112
112
113
case { result , compilation_status } do
113
114
{ { :ok , _ , warnings } , :error } ->
114
- IO . puts :stderr , "Compilation failed due to warnings while using the --warnings-as-errors option"
115
+ message = "Compilation failed due to warnings while using the --warnings-as-errors option"
116
+ IO . puts ( :stderr , message )
117
+
115
118
{ :error , warnings , [ ] }
119
+
116
120
{ { :error , errors , warnings } , :error } ->
117
121
{ :error , errors ++ warnings , [ ] }
122
+
118
123
_ ->
119
124
result
120
125
end
121
126
end
122
127
123
128
# We already have n=schedulers currently running, don't spawn new ones
124
129
defp spawn_workers ( % { queued: queued , waiting: waiting , schedulers: schedulers } = state )
125
- when length ( queued ) - length ( waiting ) >= schedulers do
130
+ when length ( queued ) - length ( waiting ) >= schedulers do
126
131
wait_for_messages ( state )
127
132
end
128
133
@@ -131,11 +136,13 @@ defmodule Kernel.ParallelCompiler do
131
136
waiting =
132
137
case List . keytake ( waiting , ref , 2 ) do
133
138
{ { _kind , pid , ^ ref , _on , _defining } , waiting } ->
134
- send pid , { ref , found }
139
+ send ( pid , { ref , found } )
135
140
waiting
141
+
136
142
nil ->
137
143
waiting
138
144
end
145
+
139
146
spawn_workers ( % { state | entries: t , waiting: waiting } )
140
147
end
141
148
@@ -144,7 +151,7 @@ defmodule Kernel.ParallelCompiler do
144
151
parent = self ( )
145
152
146
153
{ pid , ref } =
147
- :erlang . spawn_monitor fn ->
154
+ :erlang . spawn_monitor ( fn ->
148
155
:erlang . put ( :elixir_compiler_pid , parent )
149
156
:erlang . put ( :elixir_compiler_file , file )
150
157
@@ -155,23 +162,26 @@ defmodule Kernel.ParallelCompiler do
155
162
{ :compile , path } ->
156
163
:erlang . process_flag ( :error_handler , Kernel.ErrorHandler )
157
164
:elixir_compiler . file_to_path ( file , path )
165
+
158
166
:compile ->
159
167
:erlang . process_flag ( :error_handler , Kernel.ErrorHandler )
160
168
:elixir_compiler . file ( file , Keyword . get ( options , :dest ) )
169
+
161
170
:require ->
162
171
Code . require_file ( file )
163
172
end
173
+
164
174
:ok
165
175
catch
166
176
kind , reason ->
167
- { kind , reason , System . stacktrace }
177
+ { kind , reason , System . stacktrace ( ) }
168
178
end
169
179
170
180
send ( parent , { :file_done , self ( ) , file , result } )
171
181
exit ( :shutdown )
172
- end
182
+ end )
173
183
174
- timeout = Keyword . get ( options , :long_compilation_threshold , 10 ) * 1_000
184
+ timeout = Keyword . get ( options , :long_compilation_threshold , 10 ) * 1000
175
185
timer_ref = Process . send_after ( self ( ) , { :timed_out , pid } , timeout )
176
186
177
187
new_queued = [ { pid , ref , file , timer_ref } | queued ]
@@ -186,11 +196,13 @@ defmodule Kernel.ParallelCompiler do
186
196
end
187
197
188
198
# Queued x, waiting for x: POSSIBLE ERROR! Release processes so we get the failures
189
- defp spawn_workers ( % { entries: [ ] , waiting: waiting , queued: queued , warnings: warnings } = state ) when length ( waiting ) == length ( queued ) do
190
- entries = for { pid , _ , _ , _ } <- queued ,
191
- entry = waiting_on_without_definition ( waiting , pid ) ,
192
- { _ , _ , ref , on , _ } = entry ,
193
- do: { on , { ref , :not_found } }
199
+ defp spawn_workers ( % { entries: [ ] , waiting: waiting , queued: queued , warnings: warnings } = state )
200
+ when length ( waiting ) == length ( queued ) do
201
+ entries =
202
+ for { pid , _ , _ , _ } <- queued ,
203
+ entry = waiting_on_without_definition ( waiting , pid ) ,
204
+ { _ , _ , ref , on , _ } = entry ,
205
+ do: { on , { ref , :not_found } }
194
206
195
207
# Instead of releasing all files at once, we release them in groups
196
208
# based on the module they are waiting on. We pick the module being
@@ -205,12 +217,13 @@ defmodule Kernel.ParallelCompiler do
205
217
|> Enum . group_by ( & elem ( & 1 , 0 ) , & elem ( & 1 , 1 ) )
206
218
|> Enum . sort_by ( & length ( elem ( & 1 , 1 ) ) )
207
219
|> case do
208
- [ { _on , refs } | _ ] ->
209
- spawn_workers ( % { state | entries: refs } )
210
- [ ] ->
211
- errors = handle_deadlock ( waiting , queued )
212
- { :error , errors , warnings }
213
- end
220
+ [ { _on , refs } | _ ] ->
221
+ spawn_workers ( % { state | entries: refs } )
222
+
223
+ [ ] ->
224
+ errors = handle_deadlock ( waiting , queued )
225
+ { :error , errors , warnings }
226
+ end
214
227
end
215
228
216
229
# No more files, but queue and waiting are not full or do not match
@@ -220,6 +233,7 @@ defmodule Kernel.ParallelCompiler do
220
233
221
234
defp waiting_on_without_definition ( waiting , pid ) do
222
235
{ _ , ^ pid , _ , on , _ } = entry = List . keyfind ( waiting , pid , 1 )
236
+
223
237
if Enum . any? ( waiting , fn { _ , _ , _ , _ , defining } -> on in defining end ) do
224
238
nil
225
239
else
@@ -241,30 +255,41 @@ defmodule Kernel.ParallelCompiler do
241
255
242
256
receive do
243
257
{ :struct_available , module } ->
244
- available = for { :struct , _ , ref , waiting_module , _defining } <- waiting ,
245
- module == waiting_module ,
246
- do: { ref , :found }
258
+ available =
259
+ for { :struct , _ , ref , waiting_module , _defining } <- waiting ,
260
+ module == waiting_module ,
261
+ do: { ref , :found }
247
262
248
- spawn_workers ( % { state | entries: available ++ entries , result: [ { :struct , module } | result ] } )
263
+ spawn_workers ( % {
264
+ state
265
+ | entries: available ++ entries ,
266
+ result: [ { :struct , module } | result ]
267
+ } )
249
268
250
269
{ :module_available , child , ref , file , module , binary } ->
251
270
if callback = Keyword . get ( options , :each_module ) do
252
271
callback . ( file , module , binary )
253
272
end
254
273
255
274
# Release the module loader which is waiting for an ack
256
- send child , { ref , :ack }
275
+ send ( child , { ref , :ack } )
257
276
258
- available = for { :module , _ , ref , waiting_module , _defining } <- waiting ,
259
- module == waiting_module ,
260
- do: { ref , :found }
277
+ available =
278
+ for { :module , _ , ref , waiting_module , _defining } <- waiting ,
279
+ module == waiting_module ,
280
+ do: { ref , :found }
261
281
262
282
cancel_waiting_timer ( queued , child )
263
283
264
- spawn_workers ( % { state | entries: available ++ entries , result: [ { :module , module } | result ] } )
284
+ spawn_workers ( % {
285
+ state
286
+ | entries: available ++ entries ,
287
+ result: [ { :module , module } | result ]
288
+ } )
265
289
266
290
# If we are simply requiring files, we do not add to waiting.
267
- { :waiting , _kind , child , ref , _on , _defining } when output == :require ->
291
+ { :waiting , _kind , child , ref , _on , _defining }
292
+ when output == :require ->
268
293
send ( child , { ref , :not_found } )
269
294
spawn_workers ( state )
270
295
@@ -274,7 +299,7 @@ defmodule Kernel.ParallelCompiler do
274
299
# send :found so that we can crash with a better error.
275
300
waiting =
276
301
if :lists . any ( & match? ( { ^ kind , ^ on } , & 1 ) , result ) or on in defining do
277
- send child , { ref , :found }
302
+ send ( child , { ref , :found } )
278
303
waiting
279
304
else
280
305
[ { kind , child , ref , on , defining } | waiting ]
@@ -284,12 +309,15 @@ defmodule Kernel.ParallelCompiler do
284
309
285
310
{ :timed_out , child } ->
286
311
callback = Keyword . get ( options , :each_long_compilation )
312
+
287
313
case List . keyfind ( queued , child , 0 ) do
288
314
{ ^ child , _ , file , _ } when not is_nil ( callback ) ->
289
315
callback . ( file )
316
+
290
317
_ ->
291
318
:ok
292
319
end
320
+
293
321
spawn_workers ( state )
294
322
295
323
{ :warning , file , line , message } ->
@@ -310,7 +338,7 @@ defmodule Kernel.ParallelCompiler do
310
338
# Sometimes we may have spurious entries in the waiting
311
339
# list because someone invoked try/rescue UndefinedFunctionError
312
340
new_entries = List . delete ( entries , child_pid )
313
- new_queued = List . keydelete ( queued , child_pid , 0 )
341
+ new_queued = List . keydelete ( queued , child_pid , 0 )
314
342
new_waiting = List . keydelete ( waiting , child_pid , 1 )
315
343
spawn_workers ( % { state | entries: new_entries , waiting: new_waiting , queued: new_queued } )
316
344
@@ -337,12 +365,14 @@ defmodule Kernel.ParallelCompiler do
337
365
defp handle_down ( _queued , _ref , :normal ) do
338
366
:ok
339
367
end
368
+
340
369
defp handle_down ( queued , ref , reason ) do
341
370
case List . keyfind ( queued , ref , 1 ) do
342
371
{ _child , ^ ref , file , _timer_ref } ->
343
372
print_error ( file , :exit , reason , [ ] )
344
373
terminate ( queued )
345
374
{ :error , [ to_error ( file , :exit , reason , [ ] ) ] }
375
+
346
376
_ ->
347
377
:ok
348
378
end
@@ -355,29 +385,29 @@ defmodule Kernel.ParallelCompiler do
355
385
Process . exit ( pid , :kill )
356
386
357
387
{ _kind , ^ pid , _ , on , _ } = List . keyfind ( waiting , pid , 1 )
358
- description = "deadlocked waiting on module #{ inspect on } "
388
+ description = "deadlocked waiting on module #{ inspect ( on ) } "
359
389
error = CompileError . exception ( description: description , file: nil , line: nil )
360
390
print_error ( file , :error , error , stacktrace )
361
391
362
392
{ file , on , description }
363
393
end
364
394
365
- IO . puts """
366
-
395
+ IO . puts ( """
396
+
367
397
Compilation failed because of a deadlock between files.
368
398
The following files depended on the following modules:
369
- """
399
+ """ )
370
400
371
401
max =
372
402
deadlock
373
- |> Enum . map ( & & 1 |> elem ( 0 ) |> String . length )
374
- |> Enum . max
403
+ |> Enum . map ( & ( & 1 |> elem ( 0 ) |> String . length ( ) ) )
404
+ |> Enum . max ( )
375
405
376
406
for { file , mod , _ } <- deadlock do
377
- IO . puts [ " " , String . pad_leading ( file , max ) , " => " | inspect ( mod ) ]
407
+ IO . puts ( [ " " , String . pad_leading ( file , max ) , " => " | inspect ( mod ) ] )
378
408
end
379
409
380
- IO . puts ""
410
+ IO . puts ( "" )
381
411
382
412
for { file , _ , description } <- deadlock , do: { Path . absname ( file ) , nil , description }
383
413
end
@@ -389,8 +419,10 @@ defmodule Kernel.ParallelCompiler do
389
419
end
390
420
391
421
defp print_error ( file , kind , reason , stack ) do
392
- IO . write [ "\n == Compilation error in file #{ Path . relative_to_cwd ( file ) } ==\n " ,
393
- Kernel.CLI . format_error ( kind , reason , stack ) ]
422
+ IO . write ( [
423
+ "\n == Compilation error in file #{ Path . relative_to_cwd ( file ) } ==\n " ,
424
+ Kernel.CLI . format_error ( kind , reason , stack )
425
+ ] )
394
426
end
395
427
396
428
defp cancel_waiting_timer ( queued , child_pid ) do
@@ -404,6 +436,7 @@ defmodule Kernel.ParallelCompiler do
404
436
after
405
437
0 -> :ok
406
438
end
439
+
407
440
nil ->
408
441
:ok
409
442
end
0 commit comments