@@ -130,50 +130,45 @@ defmodule Mix.Tasks.Compile.App do
130130 @ impl true
131131 def run ( args ) do
132132 { opts , _ , _ } = OptionParser . parse ( args , switches: [ force: :boolean , compile_path: :string ] )
133-
134133 project = Mix.Project . get! ( )
135134 config = Mix.Project . config ( )
136135
137136 app = Keyword . get ( config , :app )
138137 version = Keyword . get ( config , :version )
138+ validate_app! ( app )
139+ validate_version! ( version )
139140
140- validate_app ( app )
141- validate_version ( version )
142-
143- path = Keyword . get_lazy ( opts , :compile_path , & Mix.Project . compile_path / 0 )
144- modules = modules_from ( path ) |> Enum . sort ( )
141+ compile_path = Keyword . get_lazy ( opts , :compile_path , & Mix.Project . compile_path / 0 )
142+ target = Path . join ( compile_path , "#{ app } .app" )
145143
146- target = Path . join ( path , "#{ app } .app" )
147-
148- # We mostly depend on the project_file through the def application function,
149- # but it doesn't hurt to also include config_mtime.
144+ # If configurations changed, we may have changed compile_env.
145+ # If compile_path changed, we may have added or removed files.
146+ # If the project changed, we may have changed other properties.
150147 new_mtime =
151- max ( Mix.Project . config_mtime ( ) , Mix.Utils . last_modified ( Mix.Project . project_file ( ) ) )
148+ Mix.Project . config_mtime ( )
149+ |> max ( Mix.Utils . last_modified ( Mix.Project . project_file ( ) ) )
150+ |> max ( Mix.Utils . last_modified ( compile_path ) )
152151
153152 current_properties = current_app_properties ( target )
154- compile_env = load_compile_env ( current_properties )
155- old_mtime = Keyword . get ( current_properties , :config_mtime , 0 )
156153
157- if opts [ :force ] || new_mtime > old_mtime ||
158- app_changed? ( current_properties , modules , compile_env ) do
154+ if opts [ :force ] || new_mtime > Mix.Utils . last_modified ( target ) do
159155 properties =
160156 [
161157 description: to_charlist ( config [ :description ] || app ) ,
162- modules: modules ,
163158 registered: [ ] ,
164159 vsn: to_charlist ( version )
165160 ]
166161 |> merge_project_application ( project )
167- |> validate_properties! ( )
168162 |> handle_extra_applications ( config )
169- |> add_compile_env ( compile_env )
163+ |> add_compile_env ( current_properties )
164+ |> add_modules ( compile_path )
170165
171- properties = [ config_mtime: new_mtime ] ++ properties
172166 contents = :io_lib . format ( "~p.~n" , [ { :application , app , properties } ] )
173167 :application . load ( { :application , app , properties } )
174168
175169 Mix.Project . ensure_structure ( )
176170 File . write! ( target , IO . chardata_to_string ( contents ) )
171+ File . touch! ( target , new_mtime )
177172 Mix . shell ( ) . info ( "Generated #{ app } app" )
178173 { :ok , [ ] }
179174 else
@@ -189,27 +184,15 @@ defmodule Mix.Tasks.Compile.App do
189184 end
190185 end
191186
192- defp load_compile_env ( current_properties ) do
193- case Mix.ProjectStack . compile_env ( nil ) do
194- nil -> Keyword . get ( current_properties , :compile_env , [ ] )
195- list -> list
196- end
197- end
198-
199- defp app_changed? ( properties , mods , compile_env ) do
200- Keyword . get ( properties , :modules , [ ] ) != mods or
201- Keyword . get ( properties , :compile_env , [ ] ) != compile_env
202- end
203-
204- defp validate_app ( app ) when is_atom ( app ) , do: :ok
187+ defp validate_app! ( app ) when is_atom ( app ) , do: :ok
205188
206- defp validate_app ( app ) do
207- ensure_present ( :app , app )
189+ defp validate_app! ( app ) do
190+ ensure_present! ( :app , app )
208191 Mix . raise ( "Expected :app to be an atom, got: #{ inspect ( app ) } " )
209192 end
210193
211- defp validate_version ( version ) do
212- ensure_present ( :version , version )
194+ defp validate_version! ( version ) do
195+ ensure_present! ( :version , version )
213196
214197 if not ( is_binary ( version ) and match? ( { :ok , _ } , Version . parse ( version ) ) ) do
215198 Mix . raise (
@@ -218,11 +201,11 @@ defmodule Mix.Tasks.Compile.App do
218201 end
219202 end
220203
221- defp ensure_present ( name , nil ) do
204+ defp ensure_present! ( name , nil ) do
222205 Mix . raise ( "Please ensure mix.exs file has the #{ inspect ( name ) } in the project definition" )
223206 end
224207
225- defp ensure_present ( _name , _val ) , do: :ok
208+ defp ensure_present! ( _name , _val ) , do: :ok
226209
227210 defp modules_from ( path ) do
228211 case File . ls ( path ) do
@@ -246,7 +229,7 @@ defmodule Mix.Tasks.Compile.App do
246229 )
247230 end
248231
249- Keyword . merge ( best_guess , project_application )
232+ Keyword . merge ( best_guess , validate_properties! ( project_application ) )
250233 else
251234 best_guess
252235 end
@@ -357,8 +340,17 @@ defmodule Mix.Tasks.Compile.App do
357340 defp typed_app? ( { app , type } ) when is_atom ( app ) and type in [ :required , :optional ] , do: true
358341 defp typed_app? ( _ ) , do: false
359342
360- defp add_compile_env ( properties , [ ] ) , do: properties
361- defp add_compile_env ( properties , compile_env ) , do: [ compile_env: compile_env ] ++ properties
343+ defp add_compile_env ( properties , current_properties ) do
344+ case Mix.ProjectStack . compile_env ( nil ) do
345+ nil -> Keyword . take ( current_properties , [ :compile_env ] ) ++ properties
346+ [ ] -> properties
347+ compile_env -> Keyword . put ( properties , :compile_env , compile_env )
348+ end
349+ end
350+
351+ defp add_modules ( properties , path ) do
352+ Keyword . put_new_lazy ( properties , :modules , fn -> path |> modules_from ( ) |> Enum . sort ( ) end )
353+ end
362354
363355 defp handle_extra_applications ( properties , config ) do
364356 { extra , properties } = Keyword . pop ( properties , :extra_applications , [ ] )
0 commit comments