11-module (elixir_compiler ).
22-export ([get_opts /0 , get_opt /1 , get_opt /2 , string /2 , file /1 , file_to_path /2 ]).
3- -export ([core /0 , module /3 , eval_forms /4 ]).
3+ -export ([core /0 , module /3 , eval_forms /4 , format_error / 1 ]).
44-include (" elixir.hrl" ).
55-compile ({parse_transform , elixir_transform }).
66
@@ -89,11 +89,17 @@ module(Forms, S, Callback) ->
8989 end ,
9090 module (Forms , S # elixir_scope .file , Options , false , Callback ).
9191
92- module (Forms , File , Options , Bootstrap , Callback ) when
93- is_binary (File ), is_list (Forms ), is_list (Options ), is_boolean (Bootstrap ), is_function (Callback ) ->
92+ module (Forms , File , RawOptions , Bootstrap , Callback ) when
93+ is_binary (File ), is_list (Forms ), is_list (RawOptions ), is_boolean (Bootstrap ), is_function (Callback ) ->
94+ { Options , SkipNative } = compile_opts (Forms , RawOptions ),
9495 Listname = binary_to_list (File ),
95- case compile :forms ([no_auto_import ()|Forms ], [return ,{source ,Listname }|Options ]) of
96- {ok , ModuleName , Binary , Warnings } ->
96+
97+ case compile :noenv_forms ([no_auto_import ()|Forms ], [return ,{source ,Listname }|Options ]) of
98+ {ok , ModuleName , Binary , RawWarnings } ->
99+ Warnings = case SkipNative of
100+ true -> [{? MODULE ,[{0 ,? MODULE ,{skip_native ,ModuleName }}]}|RawWarnings ];
101+ false -> RawWarnings
102+ end ,
97103 format_warnings (Bootstrap , File , Warnings ),
98104 code :load_binary (ModuleName , Listname , Binary ),
99105 Callback (ModuleName , Binary );
@@ -112,6 +118,38 @@ core() ->
112118
113119% % HELPERS
114120
121+ compile_opts (Forms , Options ) ->
122+ EnvOptions = env_default_opts (),
123+ SkipNative = lists :member (native , EnvOptions ) and contains_on_load (Forms ),
124+ case SkipNative or lists :member ([{native ,false }], Options ) of
125+ true -> { Options ++ lists :delete (native , EnvOptions ), SkipNative };
126+ false -> { Options ++ EnvOptions , SkipNative }
127+ end .
128+
129+ env_default_opts () ->
130+ Key = " ERL_COMPILER_OPTIONS" ,
131+ case os :getenv (Key ) of
132+ false -> [];
133+ Str when is_list (Str ) ->
134+ case erl_scan :string (Str ) of
135+ {ok ,Tokens ,_ } ->
136+ case erl_parse :parse_term (Tokens ++ [{dot , 1 }]) of
137+ {ok ,List } when is_list (List ) -> List ;
138+ {ok ,Term } -> [Term ];
139+ {error ,_Reason } ->
140+ io :format (" Ignoring bad term in ~s \n " , [Key ]),
141+ []
142+ end ;
143+ {error , {_ ,_ ,_Reason }, _ } ->
144+ io :format (" Ignoring bad term in ~s \n " , [Key ]),
145+ []
146+ end
147+ end .
148+
149+ contains_on_load ([{ attribute , _ , on_load , _ }|_ ]) -> true ;
150+ contains_on_load ([_ |T ]) -> contains_on_load (T );
151+ contains_on_load ([]) -> false .
152+
115153no_auto_import () ->
116154 Bifs = [{ Name , Arity } || { Name , Arity } <- erlang :module_info (exports ), erl_internal :bif (Name , Arity )],
117155 { attribute , 0 , compile , { no_auto_import , Bifs } }.
@@ -196,8 +234,12 @@ core_main() ->
196234
197235% % ERROR HANDLING
198236
237+ format_error ({ skip_native , Module }) ->
238+ io_lib :format (" skipping native compilation for ~s because it contains on_load attribute" ,
239+ [elixir_errors :inspect (Module )]).
240+
199241format_errors (_File , []) ->
200- exit ({nocompile , " compilation failed but no error was raised" });
242+ exit ({ nocompile , " compilation failed but no error was raised" });
201243
202244format_errors (File , Errors ) ->
203245 lists :foreach (fun ({_ , Each }) ->
0 commit comments