@@ -198,7 +198,7 @@ defmodule Kernel.ParallelCompiler do
198198 { :ok , [ atom ] , [ warning ] | info ( ) }
199199 | { :error , [ error ] | [ Code . diagnostic ( :error ) ] , [ warning ] | info ( ) }
200200 def compile_to_path ( files , path , options \\ [ ] ) when is_binary ( path ) and is_list ( options ) do
201- spawn_workers ( files , { :compile , path } , options )
201+ spawn_workers ( files , { :compile , path } , Keyword . put ( options , :dest , path ) )
202202 end
203203
204204 @ doc """
@@ -338,6 +338,9 @@ defmodule Kernel.ParallelCompiler do
338338 end
339339
340340 defp write_module_binaries ( result , { :compile , path } , timestamp ) do
341+ File . mkdir_p! ( path )
342+ Code . prepend_path ( path )
343+
341344 Enum . flat_map ( result , fn
342345 { { :module , module } , binary } when is_binary ( binary ) ->
343346 full_path = Path . join ( path , Atom . to_string ( module ) <> ".beam" )
@@ -439,8 +442,8 @@ defmodule Kernel.ParallelCompiler do
439442
440443 try do
441444 case output do
442- { :compile , path } -> compile_file ( file , path , parent )
443- :compile -> compile_file ( file , dest , parent )
445+ { :compile , _ } -> compile_file ( file , dest , false , parent )
446+ :compile -> compile_file ( file , dest , true , parent )
444447 :require -> require_file ( file , parent )
445448 end
446449 catch
@@ -546,9 +549,9 @@ defmodule Kernel.ParallelCompiler do
546549 wait_for_messages ( [ ] , spawned , waiting , files , result , warnings , errors , state )
547550 end
548551
549- defp compile_file ( file , path , parent ) do
552+ defp compile_file ( file , path , force_load? , parent ) do
550553 :erlang . process_flag ( :error_handler , Kernel.ErrorHandler )
551- :erlang . put ( :elixir_compiler_dest , path )
554+ :erlang . put ( :elixir_compiler_dest , { path , force_load? } )
552555 :elixir_compiler . file ( file , & each_file ( & 1 , & 2 , parent ) )
553556 end
554557
@@ -649,19 +652,30 @@ defmodule Kernel.ParallelCompiler do
649652 state
650653 )
651654
652- { :module_available , child , ref , file , module , binary } ->
655+ { :module_available , child , ref , file , module , binary , loaded? } ->
653656 state . each_module . ( file , module , binary )
654657
658+ available =
659+ case Map . get ( result , { :module , module } ) do
660+ [ _ | _ ] = pids ->
661+ # We prefer to load in the client, if possible,
662+ # to avoid locking the compilation server.
663+ loaded? or load_module ( module , binary , state )
664+ Enum . map ( pids , & { & 1 , :found } )
665+
666+ _ ->
667+ [ ]
668+ end
669+
655670 # Release the module loader which is waiting for an ack
656671 send ( child , { ref , :ack } )
657- { available , result } = update_result ( result , :module , module , binary )
658672
659673 spawn_workers (
660674 available ++ queue ,
661675 spawned ,
662676 waiting ,
663677 files ,
664- result ,
678+ Map . put ( result , { :module , module } , binary ) ,
665679 warnings ,
666680 errors ,
667681 state
@@ -680,6 +694,8 @@ defmodule Kernel.ParallelCompiler do
680694
681695 { waiting , files , result } =
682696 if not is_list ( available_or_pending ) or on in defining do
697+ # If what we are waiting on was defined but not loaded, we do it now.
698+ load_pending ( kind , on , result , state )
683699 send ( child_pid , { ref , :found } )
684700 { waiting , files , result }
685701 else
@@ -774,6 +790,30 @@ defmodule Kernel.ParallelCompiler do
774790 { { :error , Enum . reverse ( errors , fun . ( ) ) , info } , state }
775791 end
776792
793+ defp load_pending ( kind , module , result , state ) do
794+ with true <- kind in [ :module , :struct ] ,
795+ % { { :module , ^ module } => binary } when is_binary ( binary ) <- result ,
796+ false <- :erlang . module_loaded ( module ) do
797+ load_module ( module , binary , state )
798+ end
799+ end
800+
801+ defp load_module ( module , binary , state ) do
802+ beam_location =
803+ case state . dest do
804+ nil ->
805+ [ ]
806+
807+ dest ->
808+ :filename . join (
809+ :elixir_utils . characters_to_list ( dest ) ,
810+ Atom . to_charlist ( module ) ++ ~c" .beam"
811+ )
812+ end
813+
814+ :code . load_binary ( module , beam_location , binary )
815+ end
816+
777817 defp update_result ( result , kind , module , value ) do
778818 available =
779819 case Map . get ( result , { kind , module } ) do
0 commit comments