@@ -45,7 +45,7 @@ defmodule Mix.Tasks.Escript.Build do
45
45
* `:embed_elixir` - if `true` embed elixir and its children apps
46
46
(`ex_unit`, `mix`, etc.) mentioned in the `:applications` list inside the
47
47
`application` function in `mix.exs`.
48
- Defaults to `true`.
48
+ Defaults to `true` for Elixir projects .
49
49
50
50
* `:shebang` - shebang interpreter directive used to execute the escript.
51
51
Defaults to `"#! /usr/bin/env escript\n"`.
@@ -90,6 +90,7 @@ defmodule Mix.Tasks.Escript.Build do
90
90
main = escript_opts [ :main_module ]
91
91
app = Keyword . get ( escript_opts , :app , project [ :app ] )
92
92
files = project_files ( )
93
+ language = Keyword . get ( project , :language , :elixir )
93
94
94
95
escript_mod = String . to_atom ( Atom . to_string ( app ) <> "_escript" )
95
96
@@ -103,8 +104,9 @@ defmodule Mix.Tasks.Escript.Build do
103
104
"in your project configuration (under `:escript` option) to a module that implements main/1"
104
105
105
106
force || Mix.Utils . stale? ( files , [ filename ] ) ->
106
- tuples = gen_main ( escript_mod , main , app ) ++
107
- to_tuples ( files ) ++ deps_tuples ( ) ++ embed_tuples ( escript_opts )
107
+ tuples = gen_main ( escript_mod , main , app , language ) ++
108
+ to_tuples ( files ) ++ deps_tuples ( ) ++
109
+ embed_tuples ( escript_opts , language )
108
110
109
111
case :zip . create 'mem' , tuples , [ :memory ] do
110
112
{ :ok , { 'mem' , zip } } ->
@@ -156,8 +158,8 @@ defmodule Mix.Tasks.Escript.Build do
156
158
Enum . flat_map ( deps , fn dep -> get_tuples ( dep . opts [ :build ] ) end )
157
159
end
158
160
159
- defp embed_tuples ( escript_opts ) do
160
- if Keyword . get ( escript_opts , :embed_elixir , true ) do
161
+ defp embed_tuples ( escript_opts , language ) do
162
+ if Keyword . get ( escript_opts , :embed_elixir , language == :elixir ) do
161
163
Enum . flat_map [ :elixir | extra_apps ( ) ] , & app_tuples ( & 1 )
162
164
else
163
165
[ ]
@@ -190,61 +192,104 @@ defmodule Mix.Tasks.Escript.Build do
190
192
"%%! -escript main #{ escript_mod } #{ user_args } \n "
191
193
end
192
194
193
- defp gen_main ( name , module , app ) do
195
+ defp gen_main ( name , module , app , language ) do
194
196
config =
195
197
if File . regular? ( "config/config.exs" ) do
196
198
Mix.Config . read! ( "config/config.exs" )
197
199
else
198
200
[ ]
199
201
end
200
202
201
- { :module , ^ name , binary , _ } =
202
- defmodule name do
203
- @ module module
204
- @ config config
205
- @ app app
206
-
207
- # We need to use Erlang modules at this point
208
- # because we are not sure Elixir is available.
209
- def main ( args ) do
210
- case :application . ensure_all_started ( :elixir ) do
211
- { :ok , _ } ->
212
- load_config ( @ config )
213
- start_app ( @ app )
214
- args = Enum . map ( args , & List . to_string ( & 1 ) )
215
- Kernel.CLI . run fn _ -> @ module . main ( args ) end , true
216
- _ ->
217
- :io . put_chars :standard_error , "Elixir is not available, aborting.\n "
218
- :erlang . halt ( 1 )
219
- end
220
- end
203
+ module_body = quote do
204
+ @ module unquote ( module )
205
+ @ config unquote ( config )
206
+ @ app unquote ( app )
221
207
222
- defp load_config ( config ) do
223
- for { app , kw } <- config , { k , v } <- kw do
224
- :application . set_env ( app , k , v , persistent: true )
225
- end
226
- :ok
208
+ # We need to use Erlang modules at this point
209
+ # because we are not sure Elixir is available.
210
+ unquote ( module_body_for ( language ) )
211
+ end
212
+
213
+ { :module , ^ name , binary , _ } = Module . create ( name , module_body , Macro.Env . location ( __ENV__ ) )
214
+ [ { '#{ name } .beam' , binary } ]
215
+ end
216
+
217
+ defp module_body_for ( :elixir ) do
218
+ quote do
219
+ def main ( args ) do
220
+ case :application . ensure_all_started ( :elixir ) do
221
+ { :ok , _ } ->
222
+ load_config ( @ config )
223
+ start_app ( @ app )
224
+ args = Enum . map ( args , & List . to_string ( & 1 ) )
225
+ Kernel.CLI . run fn _ -> @ module . main ( args ) end , true
226
+ _ ->
227
+ :io . put_chars :standard_error , "Elixir is not available, aborting.\n "
228
+ :erlang . halt ( 1 )
227
229
end
230
+ end
228
231
229
- defp start_app ( nil ) do
230
- :ok
232
+ defp load_config ( config ) do
233
+ for { app , kw } <- config , { k , v } <- kw do
234
+ :application . set_env ( app , k , v , persistent: true )
231
235
end
236
+ :ok
237
+ end
232
238
233
- defp start_app ( app ) do
234
- case :application . ensure_all_started ( app ) do
235
- { :ok , _ } -> :ok
236
- { :error , { app , reason } } ->
237
- io_error "Could not start application #{ app } : " <>
238
- Application . format_error ( reason )
239
- System . halt ( 1 )
240
- end
239
+ defp start_app ( nil ) do
240
+ :ok
241
+ end
242
+
243
+ defp start_app ( app ) do
244
+ case :application . ensure_all_started ( app ) do
245
+ { :ok , _ } -> :ok
246
+ { :error , { app , reason } } ->
247
+ io_error "Could not start application #{ app } : " <>
248
+ Application . format_error ( reason )
249
+ System . halt ( 1 )
241
250
end
251
+ end
252
+
253
+ defp io_error ( message ) do
254
+ IO . puts :stderr , IO.ANSI . format ( [ :red , :bright , message ] )
255
+ end
256
+ end
257
+ end
258
+
259
+ defp module_body_for ( :erlang ) do
260
+ quote do
261
+ def main ( args ) do
262
+ load_config ( @ config )
263
+ start_app ( @ app )
264
+ @ module . main ( args )
265
+ end
242
266
243
- defp io_error ( message ) do
244
- IO . puts :stderr , IO.ANSI . format ( [ :red , :bright , message ] )
267
+ defp load_config ( config ) do
268
+ :lists . foreach ( fn { app , kw } ->
269
+ :lists . foreach ( fn { k , v } ->
270
+ :application . set_env ( app , k , v , persistent: true )
271
+ end , kw )
272
+ end , config )
273
+ :ok
274
+ end
275
+
276
+ defp start_app ( nil ) do
277
+ :ok
278
+ end
279
+
280
+ defp start_app ( app ) do
281
+ case :application . ensure_all_started ( app ) do
282
+ { :ok , _ } -> :ok
283
+ { :error , { app , reason } } ->
284
+ io_error [ "Could not start application #{ app } : " ,
285
+ :io_lib . format ( '~p~n' , [ reason ] ) ]
286
+ :erlang . halt ( 1 )
245
287
end
246
288
end
247
289
248
- [ { '#{ name } .beam' , binary } ]
290
+ defp io_error ( message ) do
291
+ :io . put_chars ( :standard_error , message )
292
+ end
293
+ end
249
294
end
250
295
end
0 commit comments