@@ -159,7 +159,7 @@ defmodule Mix.Compilers.Elixir do
159159
160160 stale = changed -- removed
161161
162- { sources , removed_modules } =
162+ { sources , stale_exports } =
163163 update_stale_sources ( sources , stale , removed_modules , sources_stats )
164164
165165 consolidation_status =
@@ -186,12 +186,26 @@ defmodule Mix.Compilers.Elixir do
186186
187187 try do
188188 consolidation = { consolidation_status , old_protocols_and_impls , protocols_and_impls }
189- state = { % { } , exports , sources , [ ] , modules , removed_modules , consolidation }
189+
190+ state = % {
191+ modules: % { } ,
192+ exports: exports ,
193+ sources: sources ,
194+ changed: [ ] ,
195+ pending_modules: modules ,
196+ stale_exports: stale_exports ,
197+ consolidation: consolidation
198+ }
199+
190200 compiler_loop ( stale , stale_modules , dest , timestamp , opts , state )
191201 else
192202 { :ok , % { runtime_warnings: runtime_warnings , compile_warnings: compile_warnings } , state } ->
193- { modules , _exports , sources , _changed , pending_modules , _stale_exports ,
194- protocols_and_impls } = state
203+ % {
204+ modules: modules ,
205+ sources: sources ,
206+ pending_modules: pending_modules ,
207+ consolidation: protocols_and_impls
208+ } = state
195209
196210 previous_warnings =
197211 if Keyword . get ( opts , :all_warnings , true ) ,
@@ -233,11 +247,10 @@ defmodule Mix.Compilers.Elixir do
233247 else: { errors , r_warnings ++ c_warnings }
234248
235249 # In case of errors, we show all previous warnings and all new ones.
236- { _ , _ , sources , _ , _ , _ , _ } = state
237250 errors = Enum . map ( errors , & diagnostic / 1 )
238251 warnings = Enum . map ( warnings , & diagnostic / 1 )
239252 all_warnings = Keyword . get ( opts , :all_warnings , errors == [ ] )
240- { :error , previous_warnings ( sources , all_warnings ) ++ warnings ++ errors }
253+ { :error , previous_warnings ( state . sources , all_warnings ) ++ warnings ++ errors }
241254 after
242255 Code . compiler_options ( previous_opts )
243256 end
@@ -1012,7 +1025,7 @@ defmodule Mix.Compilers.Elixir do
10121025 spawn_link ( fn ->
10131026 compile_opts = [
10141027 after_compile: fn ->
1015- compiler_call ( parent , ref , { :after_compile , opts } )
1028+ compiler_call ( parent , ref , { :after_compile , dest , opts } )
10161029 end ,
10171030 each_cycle: fn ->
10181031 compiler_call ( parent , ref , { :each_cycle , stale_modules , dest , timestamp } )
@@ -1060,8 +1073,8 @@ defmodule Mix.Compilers.Elixir do
10601073
10611074 defp compiler_loop ( ref , pid , state , cwd ) do
10621075 receive do
1063- { ^ ref , { :after_compile , opts } } ->
1064- { response , state } = after_compile ( state , opts )
1076+ { ^ ref , { :after_compile , dest , opts } } ->
1077+ { response , state } = after_compile ( dest , state , opts )
10651078 send ( pid , { ref , response } )
10661079 compiler_loop ( ref , pid , state , cwd )
10671080
@@ -1098,21 +1111,39 @@ defmodule Mix.Compilers.Elixir do
10981111 end
10991112 end
11001113
1101- defp after_compile ( state , opts ) do
1102- { modules , exports , sources , changed , pending_modules , stale_exports , consolidation } = state
1103-
1104- state =
1105- { modules , exports , sources , changed , pending_modules , stale_exports ,
1106- maybe_consolidate ( consolidation , modules , pending_modules , opts ) }
1107-
1108- { :ok , state }
1114+ defp after_compile ( _dest , state , opts ) do
1115+ % { modules: modules , pending_modules: pending_modules , consolidation: consolidation } = state
1116+ consolidation = maybe_consolidate ( consolidation , modules , pending_modules , opts )
1117+ { :ok , % { state | consolidation: consolidation } }
11091118 end
11101119
1111- defp each_cycle ( stale_modules , compile_path , timestamp , state ) do
1112- { modules , _exports , sources , changed , pending_modules , stale_exports , consolidation } = state
1113-
1120+ defp each_cycle ( stale_modules , dest , timestamp , state ) do
1121+ % {
1122+ modules: modules ,
1123+ sources: sources ,
1124+ changed: changed ,
1125+ pending_modules: pending_modules ,
1126+ stale_exports: stale_exports
1127+ } = state
1128+
1129+ # At this point, we may have additional files to compile.
1130+ # There are two potential sources:
1131+ #
1132+ # * We need to go through all exports that we have confirmed that changed.
1133+ # When we first compile, we store all removed/changed modules as stale
1134+ # exports. Then, if they are not compiled again, or compiled with a
1135+ # different exports MD5, they remain as stale, causing the next cycle.
1136+ #
1137+ # * In case a module is defined in two places, we add all sources to changed
11141138 { pending_modules , exports , changed } =
1115- update_stale_entries ( pending_modules , sources , changed , % { } , stale_exports , compile_path )
1139+ update_stale_entries ( pending_modules , sources , changed , % { } , stale_exports , dest )
1140+
1141+ state = % {
1142+ state
1143+ | changed: [ ] ,
1144+ exports: exports ,
1145+ pending_modules: pending_modules
1146+ }
11161147
11171148 # Those files have been changed transitively, so we mark them as changed
11181149 # in case compilation fails mid-cycle. The combination of the outdated
@@ -1152,36 +1183,30 @@ defmodule Mix.Compilers.Elixir do
11521183 end )
11531184
11541185 runtime_paths =
1155- Enum . map ( runtime_modules , & { & 1 , Path . join ( compile_path , Atom . to_string ( & 1 ) <> ".beam" ) } )
1186+ Enum . map ( runtime_modules , & { & 1 , Path . join ( dest , Atom . to_string ( & 1 ) <> ".beam" ) } )
11561187
1157- state = { modules , exports , sources , [ ] , pending_modules , stale_exports , consolidation }
1188+ state = % { state | sources: sources }
11581189 { { :runtime , runtime_paths , [ ] } , state }
11591190 else
11601191 Mix.Utils . compiling_n ( length ( changed ) , :ex )
11611192
1162- # If we have a compile time dependency to a module, as soon as its file
1163- # change, we will detect the compile time dependency and recompile. However,
1164- # the whole goal of pending exports is to delay this decision, so we need to
1165- # track which modules were removed and start them as our pending exports and
1166- # remove the pending exports as we notice they have not gone stale.
1167- { sources , removed_modules } =
1168- Enum . reduce ( changed , { sources , % { } } , fn file , { acc_sources , acc_modules } ->
1193+ # Now we need to detect the new stale_exports.
1194+ # This is a simplified version of update_stale_sources.
1195+ { sources , % { } } =
1196+ Enum . reduce ( changed , { sources , stale_exports } , fn file , { acc_sources , acc_modules } ->
11691197 source ( size: size , digest: digest , modules: modules ) = Map . fetch! ( acc_sources , file )
11701198 acc_modules = Enum . reduce ( modules , acc_modules , & Map . put ( & 2 , & 1 , true ) )
1171-
1172- # Define empty records for the sources that needs
1173- # to be recompiled (but were not changed on disk)
11741199 { Map . replace! ( acc_sources , file , source ( size: size , digest: digest ) ) , acc_modules }
11751200 end )
11761201
1177- state = { modules , exports , sources , [ ] , pending_modules , removed_modules , consolidation }
1202+ state = % { state | sources: sources , stale_exports: stale_exports }
11781203 { { :compile , changed , [ ] } , state }
11791204 end
11801205 end
11811206
11821207 defp each_file ( file , references , verbose , state , cwd ) do
11831208 { compile_references , export_references , runtime_references , compile_env } = references
1184- { modules , exports , sources , changed , pending_modules , stale_exports , consolidation } = state
1209+ % { sources: sources } = state
11851210
11861211 file = Path . relative_to ( file , cwd )
11871212
@@ -1208,12 +1233,18 @@ defmodule Mix.Compilers.Elixir do
12081233 compile_env: compile_env
12091234 )
12101235
1211- sources = Map . replace! ( sources , file , source )
1212- { modules , exports , sources , changed , pending_modules , stale_exports , consolidation }
1236+ % { state | sources: Map . replace! ( sources , file , source ) }
12131237 end
12141238
12151239 defp each_module ( file , module , kind , external , new_export , recompile? , state , timestamp , cwd ) do
1216- { modules , exports , sources , changed , pending_modules , stale_exports , consolidation } = state
1240+ % {
1241+ modules: modules ,
1242+ exports: exports ,
1243+ sources: sources ,
1244+ changed: changed ,
1245+ pending_modules: pending_modules ,
1246+ stale_exports: stale_exports
1247+ } = state
12171248
12181249 file = Path . relative_to ( file , cwd )
12191250 external = process_external_resources ( external , cwd )
@@ -1266,7 +1297,7 @@ defmodule Mix.Compilers.Elixir do
12661297 % { } -> changed
12671298 end
12681299
1269- { modules , exports , sources , changed , pending_modules , stale_exports , consolidation }
1300+ % { state | modules: modules , changed: changed , sources: sources , stale_exports: stale_exports }
12701301 end
12711302
12721303 defp detect_kind ( module ) do
0 commit comments