1
1
-module (elixir_compiler ).
2
2
-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 ]).
4
4
-include (" elixir.hrl" ).
5
5
-compile ({parse_transform , elixir_transform }).
6
6
@@ -89,11 +89,17 @@ module(Forms, S, Callback) ->
89
89
end ,
90
90
module (Forms , S # elixir_scope .file , Options , false , Callback ).
91
91
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 ),
94
95
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 ,
97
103
format_warnings (Bootstrap , File , Warnings ),
98
104
code :load_binary (ModuleName , Listname , Binary ),
99
105
Callback (ModuleName , Binary );
@@ -112,6 +118,38 @@ core() ->
112
118
113
119
% % HELPERS
114
120
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
+
115
153
no_auto_import () ->
116
154
Bifs = [{ Name , Arity } || { Name , Arity } <- erlang :module_info (exports ), erl_internal :bif (Name , Arity )],
117
155
{ attribute , 0 , compile , { no_auto_import , Bifs } }.
@@ -196,8 +234,12 @@ core_main() ->
196
234
197
235
% % ERROR HANDLING
198
236
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
+
199
241
format_errors (_File , []) ->
200
- exit ({nocompile , " compilation failed but no error was raised" });
242
+ exit ({ nocompile , " compilation failed but no error was raised" });
201
243
202
244
format_errors (File , Errors ) ->
203
245
lists :foreach (fun ({_ , Each }) ->
0 commit comments